Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cytometry4emulsions

Python package for size and fluorescence analysis of emulsion droplets by flow cytometry, using Mie scattering theory to convert raw FSC/SSC signals into absolute droplet radii.

Based on the methodology of:

Fattaccioli et al., Size and fluorescence measurements of individual droplets by flow cytometry, Soft Matter 2009, 5, 2232–2238. https://doi.org/10.1039/b814954b


Physical principle

A flow cytometer measures two light-scattering signals per particle:

  • Forward scatter (FSC) — collected over a narrow annular cone at low angles (typically 0.7°–4°), sensitive to particle size.
  • Side scatter (SSC) — collected at 90° through a high-NA lens, sensitive to both size and internal structure.

For an emulsion droplet (homogeneous sphere of refractive index n_oil in a medium of index n_water), both signals are computed from the Mie amplitude functions S₁(θ) and S₂(θ) via numerical integration over the detector apertures, accounting for the polarisation state of the laser beam and the azimuthal acceptance of the SSC lens.

The theoretical I_SS(I_FS) curve is a 1D parametric curve in the 2D scatter diagram. Each measured event is assigned a radius by nearest-neighbour projection onto this curve. The method is instrument-calibratable and requires no a priori assumption about the size distribution.


Installation

pip install .

Dependencies: numpy, scipy, pandas, matplotlib
No external Mie library is required — the scattering functions are implemented directly from Bohren & Huffman (1983).
The FCS 2.0/3.0/3.1 parser is also built-in; no fcsparser needed.

Optional, for the notebook:

pip install jupyter

Quick start

from cytometry4emulsions import InstrumentParams, FCSFile, assign_radii, size_distribution
from cytometry4emulsions import plots

# 1. Instrument model — use a preset or set parameters manually
params = InstrumentParams(
    wavelength_nm    = 488.0,
    theta_fs_min_deg = 0.716,   # inner FS cone angle (deg)
    theta_fs_max_deg = 3.954,   # outer FS cone angle (deg)
    theta_ss_max_deg = 52.38,   # SS lens half-angle = arcsin(NA) * 180/pi
    n_medium         = 1.337,   # PBS at 488 nm
    n_particle       = 1.468,   # soybean oil at 488 nm
)
# or: params = InstrumentParams.from_preset("FACSCalibur")

# 2. Load FCS file (channels auto-detected; override with explicit names if needed)
fcs = FCSFile("my_sample.fcs")
fcs.print_summary()
IFS, ISS, fl = fcs.get_scatter_data()

# 3. (Optional) Calibrate on a monodisperse reference emulsion
from cytometry4emulsions import calibrate
fcs_ref = FCSFile("monodisperse_reference.fcs")
IFS_ref, ISS_ref, _ = fcs_ref.get_scatter_data()
params = calibrate(IFS_ref, ISS_ref, params, fit_angles=True)
params.to_json("my_instrument.json")

# 4. Assign radii
events = assign_radii(IFS, ISS, params, fl_data=fl)

# 5. Size distribution
dist = size_distribution(events, n_bins=50, weighting="volume")

# 6. Plot
fig, ax = plots.plot_scattering_diagram(events, params=params)
fig2, ax2 = plots.plot_size_distribution(dist)

See notebooks/tutorial.ipynb for a complete interactive walkthrough.


Instrument presets

Preset Instrument λ (nm) θ_FS (°) θ_SS (°) n_medium n_particle
FACSCalibur BD FACSCalibur 488 0.716 – 3.954 52.38 1.337 1.468
Accuri_C6 BD Accuri C6 488 0.7 – 29.2 29.2 1.337 1.468

Parameters can be saved and reloaded:

params.to_json("my_cytometer.json")
params = InstrumentParams.from_json("my_cytometer.json")

Calibration

Minimises the mean point-to-curve distance between measured and theoretical I_SS(I_FS) using Nelder-Mead. A monodisperse emulsion (e.g. 2 µm mean diameter) is recommended as reference.

params_cal = calibrate(
    IFS_ref, ISS_ref, params,
    fit_angles     = True,   # optimise theta_fs_min, theta_fs_max
    fit_n_particle = False,  # fix n_oil if known
)

Fluorescence analysis

from cytometry4emulsions import fluorescence_per_area, fluorescence_per_volume

# Surface-localised dye (e.g. labelled lipid) → surface density
ev = fluorescence_per_area(events, fl_column="FL1-H")
# → adds: surface_nm2, fl_per_area

# Encapsulated dye (e.g. Nile Red) → volume concentration
ev = fluorescence_per_volume(events, fl_column="FL1-H")
# → adds: volume_nm3, fl_per_volume

Repository structure

cytometry4emulsions/     importable package
    __init__.py          public API and usage docstring
    mie.py               Mie S1/S2 functions and detector integrals
    instrument.py        InstrumentParams dataclass, presets, Nelder-Mead calibration
    fcs_io.py            FCS 2.0/3.0/3.1 parser with channel auto-detection
    analysis.py          KD-tree radius assignment, size histograms, FL normalisation
    plots.py             matplotlib figures

notebooks/
    tutorial.ipynb       interactive walkthrough with synthetic data

tests/
    test_mie.py
    test_fcs_io.py
    test_analysis.py

data/example/
    FACSCalibur_params.json

Roadmap

  • Core-shell particles: extend mie.py with coated-sphere coefficients (Bohren & Huffman §4.4) for lipid-shelled droplets or polymer capsules.
  • Multi-instrument presets: Sony, Beckman Coulter geometries.
  • GUI wrapper: simple tkinter or panel interface for non-programmers in the group.

Reference

@article{fattaccioli2009,
  author  = {Fattaccioli, Jacques and Baudry, Jean and Henry, Nicolas
             and Brochard-Wyart, Françoise and Bibette, Jérôme},
  title   = {Size and fluorescence measurements of individual droplets
             by flow cytometry},
  journal = {Soft Matter},
  year    = {2009},
  volume  = {5},
  pages   = {2232--2238},
  doi     = {10.1039/b814954b}
}

About

Python package for sizing and fluorescence analysis of emulsion droplets by flow cytometry, based on Mie scattering theory (Fattaccioli et al., Soft Matter 2009).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages