Skip to content

FattaccioliLab/cytometry4emulsions

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

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors