Note
Go to the end to download the full example code.
Flow Cytometry Workflow: Single Population Example#
This tutorial demonstrates a basic flow cytometry simulation using the FlowCyPy library.
The example covers the configuration of: - A fluidic channel with hydrodynamic focusing - A synthetic particle population (Exosome + HDL) - A laser source and dual-detector optical system - Scattering intensity calculation per detector
The resulting data are visualized using event-based plots.
Workflow Steps:#
Define laser source and flow cell geometry
Add synthetic particle populations
Model optical scattering with two detectors
Visualize population and scattering response
Step 0: Imports and Setup#
from TypedUnit import ureg
from FlowCyPy import OptoElectronics
from FlowCyPy.detector import PMT
from FlowCyPy.fluidics import FlowCell, Fluidics, ScattererCollection, population
from FlowCyPy.opto_electronics import TransimpedanceAmplifier, source
from FlowCyPy.signal_processing import Digitizer
Step 1: Define Optical Source#
laser = source.GaussianBeam(
numerical_aperture=0.3 * ureg.AU,
wavelength=750 * ureg.nanometer,
optical_power=20 * ureg.milliwatt,
)
Step 2: Configure Flow Cell and Fluidics#
flow_cell = FlowCell(
sample_volume_flow=0.02 * ureg.microliter / ureg.second,
sheath_volume_flow=0.1 * ureg.microliter / ureg.second,
width=20 * ureg.micrometer,
height=10 * ureg.micrometer,
)
scatterer_collection = ScattererCollection(medium_refractive_index=1.33 * ureg.RIU)
# Add Exosome and HDL populations
scatterer_collection.add_population(
population.Exosome(particle_count=5e10 * ureg.particle / ureg.milliliter),
)
fluidics = Fluidics(scatterer_collection=scatterer_collection, flow_cell=flow_cell)
Step 3: Generate Particle Event DataFrame#
event_dataframe = fluidics.generate_event_dataframe(run_time=3.5 * ureg.millisecond)
# Plot the diameter distribution of the particles
event_dataframe.plot(x="Diameter", bins="auto")

<Figure size 1200x500 with 1 Axes>
Step 4: Define Detectors and Amplifier#
detector_forward = PMT(
name="forward", phi_angle=0 * ureg.degree, numerical_aperture=0.3 * ureg.AU
)
detector_side = PMT(
name="side", phi_angle=90 * ureg.degree, numerical_aperture=0.3 * ureg.AU
)
amplifier = TransimpedanceAmplifier(
gain=100 * ureg.volt / ureg.ampere, bandwidth=10 * ureg.megahertz
)
Step 5: Configure Digitizer and Opto-Electronics#
digitizer = Digitizer(
bit_depth="14bit", saturation_levels="auto", sampling_rate=60 * ureg.megahertz
)
opto_electronics = OptoElectronics(
detectors=[detector_forward, detector_side], source=laser, amplifier=amplifier
)
Step 6: Model Scattering Signals#
event_dataframe = opto_electronics.model_event(
event_dataframe=event_dataframe, compute_cross_section=True
)
Population ScattererID
Exosome 0 1.5795017586881102e-07
1 -3.7054548306477813e-07
2 1.3726862882218792e-06
3 1.2881161137246904e-06
4 -2.0775551048896938e-07
...
3535 -5.950548036265585e-07
3536 -1.1251534683360597e-06
3537 -2.3877871043832875e-09
3538 1.3353450892354185e-06
3539 -1.2096358602645537e-06
Name: y, Length: 3540, dtype: pint[meter][Float64] 795.7747154594767 nanometer
/opt/hostedtoolcache/Python/3.11.13/x64/lib/python3.11/site-packages/FlowCyPy/source.py:255: UserWarning: Transverse distribution of particle flow exceed the waist of the source
warnings.warn(
Population ScattererID
Exosome 0 1.5795017586881102e-07
1 -3.7054548306477813e-07
2 1.3726862882218792e-06
3 1.2881161137246904e-06
4 -2.0775551048896938e-07
...
3535 -5.950548036265585e-07
3536 -1.1251534683360597e-06
3537 -2.3877871043832875e-09
3538 1.3353450892354185e-06
3539 -1.2096358602645537e-06
Name: y, Length: 3540, dtype: pint[meter][Float64] 795.7747154594767 nanometer
/opt/hostedtoolcache/Python/3.11.13/x64/lib/python3.11/site-packages/FlowCyPy/source.py:255: UserWarning: Transverse distribution of particle flow exceed the waist of the source
warnings.warn(
Step 7: Visualize Scattering Intensity#
event_dataframe.plot(x="side", y="Csca") # Color-coded by scattering cross-section

<seaborn.axisgrid.JointGrid object at 0x7f8a3e2bd790>
Total running time of the script: (0 minutes 3.829 seconds)