FlowCyPy 0.7.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- FlowCyPy/__init__.py +13 -0
- FlowCyPy/_version.py +16 -0
- FlowCyPy/acquisition.py +652 -0
- FlowCyPy/classifier.py +208 -0
- FlowCyPy/coupling_mechanism/__init__.py +4 -0
- FlowCyPy/coupling_mechanism/empirical.py +47 -0
- FlowCyPy/coupling_mechanism/mie.py +207 -0
- FlowCyPy/coupling_mechanism/rayleigh.py +116 -0
- FlowCyPy/coupling_mechanism/uniform.py +40 -0
- FlowCyPy/coupling_mechanism.py +205 -0
- FlowCyPy/cytometer.py +314 -0
- FlowCyPy/detector.py +439 -0
- FlowCyPy/directories.py +36 -0
- FlowCyPy/distribution/__init__.py +16 -0
- FlowCyPy/distribution/base_class.py +79 -0
- FlowCyPy/distribution/delta.py +104 -0
- FlowCyPy/distribution/lognormal.py +124 -0
- FlowCyPy/distribution/normal.py +128 -0
- FlowCyPy/distribution/particle_size_distribution.py +132 -0
- FlowCyPy/distribution/uniform.py +117 -0
- FlowCyPy/distribution/weibull.py +115 -0
- FlowCyPy/flow_cell.py +198 -0
- FlowCyPy/helper.py +81 -0
- FlowCyPy/logger.py +136 -0
- FlowCyPy/noises.py +34 -0
- FlowCyPy/particle_count.py +127 -0
- FlowCyPy/peak_locator/__init__.py +4 -0
- FlowCyPy/peak_locator/base_class.py +163 -0
- FlowCyPy/peak_locator/basic.py +108 -0
- FlowCyPy/peak_locator/derivative.py +143 -0
- FlowCyPy/peak_locator/moving_average.py +166 -0
- FlowCyPy/physical_constant.py +19 -0
- FlowCyPy/plottings.py +269 -0
- FlowCyPy/population.py +136 -0
- FlowCyPy/populations_instances.py +65 -0
- FlowCyPy/scatterer_collection.py +306 -0
- FlowCyPy/signal_digitizer.py +90 -0
- FlowCyPy/source.py +249 -0
- FlowCyPy/units.py +30 -0
- FlowCyPy/utils.py +191 -0
- FlowCyPy-0.7.0.dist-info/LICENSE +21 -0
- FlowCyPy-0.7.0.dist-info/METADATA +252 -0
- FlowCyPy-0.7.0.dist-info/RECORD +45 -0
- FlowCyPy-0.7.0.dist-info/WHEEL +5 -0
- FlowCyPy-0.7.0.dist-info/top_level.txt +1 -0
FlowCyPy/utils.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from typing import List, Dict
|
|
3
|
+
from FlowCyPy.units import second, volt, Quantity
|
|
4
|
+
import pandas as pd
|
|
5
|
+
import pint_pandas
|
|
6
|
+
from tabulate import tabulate
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from FlowCyPy.peak_locator import BasePeakLocator
|
|
9
|
+
from copy import copy
|
|
10
|
+
from FlowCyPy.helper import plot_helper
|
|
11
|
+
import matplotlib.pyplot as plt
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ProxyDetector():
|
|
15
|
+
def __init__(self, signal, time):
|
|
16
|
+
self.name = str(id(self))
|
|
17
|
+
self.signal = signal
|
|
18
|
+
self.time = time
|
|
19
|
+
self.dt = time[1] - time[0]
|
|
20
|
+
|
|
21
|
+
self.dataframe = pd.DataFrame(
|
|
22
|
+
data={
|
|
23
|
+
'Signal': pint_pandas.PintArray(self.signal, dtype=self.signal.units),
|
|
24
|
+
'Time': pint_pandas.PintArray(self.time, dtype=self.time.units)
|
|
25
|
+
}
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def set_peak_locator(self, algorithm: BasePeakLocator, compute_peak_area: bool = True) -> None:
|
|
29
|
+
# Ensure the algorithm is an instance of BasePeakLocator
|
|
30
|
+
if not isinstance(algorithm, BasePeakLocator):
|
|
31
|
+
raise TypeError("The algorithm must be an instance of BasePeakLocator.")
|
|
32
|
+
|
|
33
|
+
# Ensure the detector has signal data available for analysis
|
|
34
|
+
if not hasattr(self, 'dataframe') or self.dataframe is None:
|
|
35
|
+
raise RuntimeError("The detector does not have signal data available for peak detection.")
|
|
36
|
+
|
|
37
|
+
# Set the algorithm and perform peak detection
|
|
38
|
+
self.algorithm = copy(algorithm)
|
|
39
|
+
self.algorithm.init_data(self.dataframe)
|
|
40
|
+
self.algorithm.detect_peaks(compute_area=compute_peak_area)
|
|
41
|
+
|
|
42
|
+
def get_properties(self) -> List[List[str]]:
|
|
43
|
+
return [
|
|
44
|
+
['name', 'proxy']
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
@plot_helper
|
|
48
|
+
def plot(self, color: str = 'C0', ax: plt.Axes = None, time_unit: str | Quantity = None, signal_unit: str | Quantity = None, add_peak_locator: bool = False) -> None:
|
|
49
|
+
"""
|
|
50
|
+
Visualizes the processed signal as a function of time.
|
|
51
|
+
|
|
52
|
+
This method generates a plot of the processed signal data over time,
|
|
53
|
+
allowing customization of appearance and axis scaling.
|
|
54
|
+
|
|
55
|
+
Parameters
|
|
56
|
+
----------
|
|
57
|
+
show : bool, optional
|
|
58
|
+
Whether to display the plot immediately. Default is True.
|
|
59
|
+
figure_size : tuple, optional
|
|
60
|
+
Size of the plot in inches as (width, height). Default is None, which uses the default Matplotlib settings.
|
|
61
|
+
color : str, optional
|
|
62
|
+
Color of the signal line in the plot. Default is 'C0' (Matplotlib's default color cycle).
|
|
63
|
+
ax : matplotlib.axes.Axes, optional
|
|
64
|
+
Pre-existing Matplotlib Axes to plot on. If None, a new figure and axes will be created.
|
|
65
|
+
time_unit : str or Quantity, optional
|
|
66
|
+
Unit to use for the time axis. If None, it defaults to the unit of the maximum time value in the data.
|
|
67
|
+
signal_unit : str or Quantity, optional
|
|
68
|
+
Unit to use for the signal axis. If None, it defaults to the unit of the maximum signal value in the data.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
None
|
|
73
|
+
Displays the plot if `show` is True. The function also updates the data's time and signal columns to the specified units.
|
|
74
|
+
|
|
75
|
+
Notes
|
|
76
|
+
-----
|
|
77
|
+
- The method automatically converts the data's `Time` and `Signal` columns to the specified units,
|
|
78
|
+
ensuring consistency between the data and plot axes.
|
|
79
|
+
- If `show` is False, the plot will not be displayed but can be retrieved through the provided `ax`.
|
|
80
|
+
"""
|
|
81
|
+
signal_unit = signal_unit or self.dataframe.Signal.max().to_compact().units
|
|
82
|
+
time_unit = time_unit or self.dataframe.Time.max().to_compact().units
|
|
83
|
+
|
|
84
|
+
y = self.dataframe['Signal'].pint.to(signal_unit)
|
|
85
|
+
x = self.dataframe['Time'].pint.to(time_unit)
|
|
86
|
+
|
|
87
|
+
ax.plot(x, y, color=color, label='Signal')
|
|
88
|
+
|
|
89
|
+
if add_peak_locator:
|
|
90
|
+
self.algorithm._add_to_ax(ax=ax, signal_unit=signal_unit, time_unit=time_unit)
|
|
91
|
+
|
|
92
|
+
ax.set_xlabel(f"Time [{time_unit:P}]")
|
|
93
|
+
ax.set_ylabel(f"{self.name} [{signal_unit:P}]")
|
|
94
|
+
|
|
95
|
+
return time_unit, signal_unit
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def generate_dummy_detector(time: np.ndarray, centers: List[float], heights: List[float], stds: List[float]):
|
|
99
|
+
"""
|
|
100
|
+
Generate a synthetic signal composed of multiple Gaussian pulses.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
time : numpy.ndarray
|
|
105
|
+
A numpy array representing the time axis over which the signal is generated.
|
|
106
|
+
centers : list of floats
|
|
107
|
+
A list of centers (in time) for each Gaussian pulse.
|
|
108
|
+
heights : list of floats
|
|
109
|
+
A list of peak heights (amplitudes) for each Gaussian pulse.
|
|
110
|
+
stds : list of floats
|
|
111
|
+
A list of widths (standard deviations) for each Gaussian pulse.
|
|
112
|
+
|
|
113
|
+
Returns
|
|
114
|
+
-------
|
|
115
|
+
numpy.ndarray
|
|
116
|
+
A numpy array representing the generated signal composed of Gaussian pulses.
|
|
117
|
+
"""
|
|
118
|
+
time = Quantity(time, second)
|
|
119
|
+
centers = Quantity(centers, second)
|
|
120
|
+
heights = Quantity(heights, volt)
|
|
121
|
+
stds = Quantity(stds, second)
|
|
122
|
+
|
|
123
|
+
signal = np.zeros_like(time) * volt
|
|
124
|
+
|
|
125
|
+
for center, height, sigma in zip(centers, heights, stds):
|
|
126
|
+
signal += height * np.exp(-((time - center) ** 2) / (2 * sigma ** 2))
|
|
127
|
+
|
|
128
|
+
return ProxyDetector(time=time, signal=signal)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def find_matching_indices(array_0: np.ndarray, array_1: np.ndarray, margin: float):
|
|
132
|
+
"""
|
|
133
|
+
Finds the indices where the values of two arrays match within a certain margin.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
array_0 (np.ndarray): First array.
|
|
138
|
+
array_1 (np.ndarray): Second array.
|
|
139
|
+
margin (float): The margin within which values are considered matching.
|
|
140
|
+
|
|
141
|
+
Returns
|
|
142
|
+
-------
|
|
143
|
+
np.ndarray
|
|
144
|
+
Array of index pairs (i, j) where array_0[i] and array_1[j] match within the margin.
|
|
145
|
+
"""
|
|
146
|
+
# Use broadcasting to compute the absolute difference between every value in array_0 and array_1
|
|
147
|
+
difference_matrix = np.abs(array_0[:, np.newaxis] - array_1)
|
|
148
|
+
|
|
149
|
+
# Get the indices where the difference is within the margin
|
|
150
|
+
matching_indices = np.argwhere(difference_matrix <= margin)
|
|
151
|
+
|
|
152
|
+
return matching_indices
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def array_to_compact(array: np.ndarray):
|
|
156
|
+
compact_unit = array.mean().to_compact().units
|
|
157
|
+
return array.to(compact_unit)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass(slots=True)
|
|
161
|
+
class PropertiesReport:
|
|
162
|
+
def print_properties(self, **properties_dict: Dict[str, Quantity]) -> None:
|
|
163
|
+
"""
|
|
164
|
+
Prints the detector's properties in a tabular format.
|
|
165
|
+
|
|
166
|
+
This method formats the properties into a grid and prints them for easy visualization.
|
|
167
|
+
"""
|
|
168
|
+
properties = self.get_properties(**properties_dict)
|
|
169
|
+
|
|
170
|
+
print(f"\n{self.__class__.__name__} [{self.name if hasattr(self, 'name') else ''}] Properties")
|
|
171
|
+
print(tabulate(properties, headers=["Property", "Value"], tablefmt="grid"))
|
|
172
|
+
|
|
173
|
+
def add_to_report(self) -> List:
|
|
174
|
+
"""
|
|
175
|
+
Returns the detector's key properties as a list for inclusion in reports.
|
|
176
|
+
|
|
177
|
+
The list is formatted similarly to `get_properties`, providing a summary of the detector's characteristics.
|
|
178
|
+
"""
|
|
179
|
+
return self.get_properties()
|
|
180
|
+
|
|
181
|
+
def get_properties(self, **properties_dict: Dict[str, Quantity]) -> List[List[str]]:
|
|
182
|
+
"""
|
|
183
|
+
Returns a list of key properties of the detector.
|
|
184
|
+
|
|
185
|
+
The list contains formatted strings representing the detector's physical and operational characteristics.
|
|
186
|
+
"""
|
|
187
|
+
properties_dict = {
|
|
188
|
+
k: f"{v.to_compact():.1f~P}" if isinstance(v, Quantity) else v for k, v in properties_dict.items()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return list(properties_dict.items())
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Martin de Sivry
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: FlowCyPy
|
|
3
|
+
Version: 0.7.0
|
|
4
|
+
Summary: A package for flow-cytometry simulations.
|
|
5
|
+
Author-email: Martin Poinsinet de Sivry-Houle <martin.poinsinet.de.sivry@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2020 Martin de Sivry
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/MartinPdeS/FlowCyPy
|
|
29
|
+
Project-URL: Documentation, https://martinpdes.github.io/FlowCyPy/
|
|
30
|
+
Project-URL: Repository, https://github.com/MartinPdeS/FlowCyPy.git
|
|
31
|
+
Keywords: refracive index,optics,microbeads,Mie scattering
|
|
32
|
+
Classifier: Programming Language :: Python
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
35
|
+
Classifier: Development Status :: 3 - Alpha
|
|
36
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
37
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
38
|
+
Classifier: Intended Audience :: Science/Research
|
|
39
|
+
Requires-Python: >=3.10
|
|
40
|
+
Description-Content-Type: text/x-rst
|
|
41
|
+
License-File: LICENSE
|
|
42
|
+
Requires-Dist: pandas~=2.2
|
|
43
|
+
Requires-Dist: pint-pandas~=0.6
|
|
44
|
+
Requires-Dist: seaborn~=0.13
|
|
45
|
+
Requires-Dist: pydantic~=2.9
|
|
46
|
+
Requires-Dist: tabulate~=0.9
|
|
47
|
+
Requires-Dist: numpy<3.0,>=1.26
|
|
48
|
+
Requires-Dist: pint~=0.24
|
|
49
|
+
Requires-Dist: scipy~=1.14
|
|
50
|
+
Requires-Dist: PyMieSim
|
|
51
|
+
Requires-Dist: MPSPlots
|
|
52
|
+
Requires-Dist: scikit-learn
|
|
53
|
+
Provides-Extra: testing
|
|
54
|
+
Requires-Dist: pytest>=0.6; extra == "testing"
|
|
55
|
+
Requires-Dist: pytest-cov>=2.0; extra == "testing"
|
|
56
|
+
Requires-Dist: pytest-json-report==1.5.0; extra == "testing"
|
|
57
|
+
Requires-Dist: coverage==7.6.10; extra == "testing"
|
|
58
|
+
Provides-Extra: documentation
|
|
59
|
+
Requires-Dist: numpydoc==1.8.0; extra == "documentation"
|
|
60
|
+
Requires-Dist: sphinx>=5.1.1; extra == "documentation"
|
|
61
|
+
Requires-Dist: sphinx-rtd-theme==3.0.2; extra == "documentation"
|
|
62
|
+
Requires-Dist: sphinx-gallery==0.18.0; extra == "documentation"
|
|
63
|
+
Requires-Dist: pydata-sphinx-theme==0.16.1; extra == "documentation"
|
|
64
|
+
Provides-Extra: dev
|
|
65
|
+
Requires-Dist: flake8==7.1.1; extra == "dev"
|
|
66
|
+
|
|
67
|
+
|logo|
|
|
68
|
+
|
|
69
|
+
FlowCyPy: Flow Cytometer Simulation Tool
|
|
70
|
+
========================================
|
|
71
|
+
|
|
72
|
+
.. list-table::
|
|
73
|
+
:widths: 10 25 25 25
|
|
74
|
+
:header-rows: 0
|
|
75
|
+
|
|
76
|
+
* - Meta
|
|
77
|
+
- |python|
|
|
78
|
+
- |docs|
|
|
79
|
+
-
|
|
80
|
+
* - Testing
|
|
81
|
+
- |ci/cd|
|
|
82
|
+
- |coverage|
|
|
83
|
+
-
|
|
84
|
+
* - PyPi
|
|
85
|
+
- |PyPi|
|
|
86
|
+
- |PyPi_download|
|
|
87
|
+
-
|
|
88
|
+
* - Anaconda
|
|
89
|
+
- |anaconda|
|
|
90
|
+
- |anaconda_download|
|
|
91
|
+
- |anaconda_date|
|
|
92
|
+
|
|
93
|
+
Overview
|
|
94
|
+
--------
|
|
95
|
+
|
|
96
|
+
**FlowCyPy** is a cutting-edge Python library designed to simulate flow cytometer experiments. By generating realistic Forward Scatter (FSC) and Side Scatter (SSC) signals, FlowCyPy enables detailed modeling of flow cytometry setups, making it ideal for researchers and engineers working with extracellular vesicles (EVs) or other scatterers.
|
|
97
|
+
|
|
98
|
+
Key Features
|
|
99
|
+
------------
|
|
100
|
+
|
|
101
|
+
- **Particle Event Simulation**: Create detailed FSC/SSC signals with customizable particle size and refractive index distributions.
|
|
102
|
+
- **Noise and Signal Modeling**: Incorporate realistic noise sources (thermal, shot, dark current) and baseline shifts.
|
|
103
|
+
- **Detector Configurations**: Simulate real-world detector behaviors, including saturation and responsivity.
|
|
104
|
+
- **Fluorescence Modeling**: Simulate fluorescence signals for labeled particles (e.g., EV surface markers).
|
|
105
|
+
- **Visualization Tools**: Generate advanced plots, including density maps and signal traces.
|
|
106
|
+
|
|
107
|
+
For full documentation and examples, visit the `FlowCyPy Documentation <https://martinpdes.github.io/FlowCyPy/>`_.
|
|
108
|
+
|
|
109
|
+
Installation
|
|
110
|
+
------------
|
|
111
|
+
|
|
112
|
+
Install FlowCyPy via `pip` or `conda``:
|
|
113
|
+
|
|
114
|
+
.. code-block:: bash
|
|
115
|
+
|
|
116
|
+
pip install FlowCyPy
|
|
117
|
+
conda install FlowCyPy --channels MartinPdeS
|
|
118
|
+
|
|
119
|
+
**Requirements**: Python 3.10 or higher with dependencies:
|
|
120
|
+
`numpy`, `scipy`, `pint`, `tabulate`, `seaborn`, `MPSPlots`, `PyMieSim`, `pydantic>=2.6.3`
|
|
121
|
+
|
|
122
|
+
Quick Start
|
|
123
|
+
-----------
|
|
124
|
+
|
|
125
|
+
Simulate a simple flow cytometer experiment:
|
|
126
|
+
|
|
127
|
+
.. code-block:: python
|
|
128
|
+
|
|
129
|
+
from FlowCyPy import FlowCytometer, ScattererCollection, FlowCell
|
|
130
|
+
from FlowCyPy.units import particle, liter, nanometer, RIU
|
|
131
|
+
|
|
132
|
+
# Define the flow cell
|
|
133
|
+
flow_cell = FlowCell(
|
|
134
|
+
flow_speed=1.0, flow_area=10e-6, run_time=0.01
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Define scatterer properties
|
|
138
|
+
scatterer = ScattererCollection(medium_refractive_index=1.33 * RIU)
|
|
139
|
+
scatterer.add_population(
|
|
140
|
+
name='EVs',
|
|
141
|
+
concentration=1e9 * particle / liter,
|
|
142
|
+
size=distribution.Normal(mean=100 * nanometer, std_dev=20 * nanometer),
|
|
143
|
+
refractive_index=distribution.Normal(mean=1.45 * RIU, std_dev=0.01 * RIU)
|
|
144
|
+
)
|
|
145
|
+
flow_cell.initialize(scatterer=scatterer)
|
|
146
|
+
|
|
147
|
+
# Simulate the cytometer signals
|
|
148
|
+
cytometer = FlowCytometer(
|
|
149
|
+
flow_cell=flow_cell,
|
|
150
|
+
source=source,
|
|
151
|
+
detectors=[detector_fsc, detector_ssc]
|
|
152
|
+
)
|
|
153
|
+
cytometer.simulate_pulse()
|
|
154
|
+
cytometer.plot()
|
|
155
|
+
|
|
156
|
+
Explore more examples in the `FlowCyPy Examples <https://martinpdes.github.io/FlowCyPy/gallery/index.html>`_.
|
|
157
|
+
|
|
158
|
+
Development and Contribution
|
|
159
|
+
-----------------------------
|
|
160
|
+
|
|
161
|
+
Clone the Repository
|
|
162
|
+
~~~~~~~~~~~~~~~~~~~~
|
|
163
|
+
|
|
164
|
+
.. code-block:: bash
|
|
165
|
+
|
|
166
|
+
git clone https://github.com/MartinPdeS/FlowCyPy.git
|
|
167
|
+
cd FlowCyPy
|
|
168
|
+
|
|
169
|
+
Install Locally
|
|
170
|
+
~~~~~~~~~~~~~~~
|
|
171
|
+
|
|
172
|
+
Install in editable mode with testing and documentation dependencies:
|
|
173
|
+
|
|
174
|
+
.. code-block:: bash
|
|
175
|
+
|
|
176
|
+
pip install -e .[testing,documentation]
|
|
177
|
+
|
|
178
|
+
Run Tests
|
|
179
|
+
~~~~~~~~~
|
|
180
|
+
|
|
181
|
+
Use `pytest` to validate functionality:
|
|
182
|
+
|
|
183
|
+
.. code-block:: bash
|
|
184
|
+
|
|
185
|
+
pytest
|
|
186
|
+
|
|
187
|
+
Build Documentation
|
|
188
|
+
~~~~~~~~~~~~~~~~~~~
|
|
189
|
+
|
|
190
|
+
Build the documentation locally:
|
|
191
|
+
|
|
192
|
+
.. code-block:: bash
|
|
193
|
+
|
|
194
|
+
cd docs
|
|
195
|
+
make html
|
|
196
|
+
|
|
197
|
+
Find the documentation in `docs/_build/html`.
|
|
198
|
+
|
|
199
|
+
Additional Resources
|
|
200
|
+
--------------------
|
|
201
|
+
|
|
202
|
+
- **Documentation**: Full guide and API reference at `FlowCyPy Documentation <https://martinpdes.github.io/FlowCyPy/>`_
|
|
203
|
+
- **Examples**: Explore use cases in the `Examples Section <https://martinpdes.github.io/FlowCyPy/gallery/index.html>`_
|
|
204
|
+
|
|
205
|
+
Contributions
|
|
206
|
+
-------------
|
|
207
|
+
|
|
208
|
+
Contributions are welcome! If you have suggestions, issues, or would like to collaborate, visit the `GitHub repository <https://github.com/MartinPdeS/FlowCyPy>`_.
|
|
209
|
+
|
|
210
|
+
Contact
|
|
211
|
+
-------
|
|
212
|
+
|
|
213
|
+
For inquiries or collaboration, contact `Martin Poinsinet de Sivry-Houle <mailto:martin.poinsinet.de.sivry@gmail.com>`_.
|
|
214
|
+
|
|
215
|
+
.. |logo| image:: https://github.com/MartinPdeS/FlowCyPy/raw/master/docs/images/logo.png
|
|
216
|
+
:align: middle
|
|
217
|
+
:alt: FlowCyPy Logo
|
|
218
|
+
|
|
219
|
+
.. |python| image:: https://img.shields.io/pypi/pyversions/flowcypy.svg
|
|
220
|
+
:alt: Python
|
|
221
|
+
:target: https://www.python.org/
|
|
222
|
+
|
|
223
|
+
.. |docs| image:: https://github.com/martinpdes/flowcypy/actions/workflows/deploy_documentation.yml/badge.svg
|
|
224
|
+
:target: https://martinpdes.github.io/FlowCyPy/
|
|
225
|
+
:alt: Documentation Status
|
|
226
|
+
|
|
227
|
+
.. |PyPi| image:: https://badge.fury.io/py/FlowCyPy.svg
|
|
228
|
+
:alt: PyPi version
|
|
229
|
+
:target: https://badge.fury.io/py/FlowCyPy
|
|
230
|
+
|
|
231
|
+
.. |PyPi_download| image:: https://img.shields.io/pypi/dm/FlowCyPy?style=plastic&label=PyPi%20downloads&labelColor=hex&color=hex
|
|
232
|
+
:alt: PyPI - Downloads
|
|
233
|
+
:target: https://pypistats.org/packages/flowcypy
|
|
234
|
+
|
|
235
|
+
.. |coverage| image:: https://raw.githubusercontent.com/MartinPdeS/FlowCyPy/python-coverage-comment-action-data/badge.svg
|
|
236
|
+
:alt: Unittest coverage
|
|
237
|
+
:target: https://htmlpreview.github.io/?https://github.com/MartinPdeS/FlowCyPy/blob/python-coverage-comment-action-data/htmlcov/index.html
|
|
238
|
+
|
|
239
|
+
.. |ci/cd| image:: https://github.com/martinpdes/flowcypy/actions/workflows/deploy_coverage.yml/badge.svg
|
|
240
|
+
:alt: Unittest Status
|
|
241
|
+
|
|
242
|
+
.. |anaconda| image:: https://anaconda.org/martinpdes/flowcypy/badges/version.svg
|
|
243
|
+
:alt: Anaconda version
|
|
244
|
+
:target: https://anaconda.org/martinpdes/flowcypy
|
|
245
|
+
|
|
246
|
+
.. |anaconda_download| image:: https://anaconda.org/martinpdes/flowcypy/badges/downloads.svg
|
|
247
|
+
:alt: Anaconda downloads
|
|
248
|
+
:target: https://anaconda.org/martinpdes/flowcypy
|
|
249
|
+
|
|
250
|
+
.. |anaconda_date| image:: https://anaconda.org/martinpdes/flowcypy/badges/latest_release_relative_date.svg
|
|
251
|
+
:alt: Latest release date
|
|
252
|
+
:target: https://anaconda.org/martinpdes/flowcypy
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
FlowCyPy/__init__.py,sha256=iW6Yy8nJbmTXx8YpwVDwkEM4M0xo2u_LIyqjpRlKQro,386
|
|
2
|
+
FlowCyPy/_version.py,sha256=akvr8ObxvMF-aaLBzW41juT4_KL3BjQUrjbwkIuQXMk,411
|
|
3
|
+
FlowCyPy/acquisition.py,sha256=zqOjQEE8_niPjRKOAzfOEK3Z6a3C9XnRXzZ82J7Dg60,26434
|
|
4
|
+
FlowCyPy/classifier.py,sha256=Zgr8qZbSgZA5XKyprGojogXDZ9e2YD0pDKlvo1ORsYY,7141
|
|
5
|
+
FlowCyPy/coupling_mechanism.py,sha256=PTy3qNTd96Mr6WO2iSA02bmUnyzaVctywQpqPLtBUJ4,7284
|
|
6
|
+
FlowCyPy/cytometer.py,sha256=ttyI-hs71D8EaVOdswSRSSuRMFg0XqADXHo-56ypQzE,12525
|
|
7
|
+
FlowCyPy/detector.py,sha256=j-WHF2izbgtOrMhzS6Ub7RwbZRwdFoMS36HniOF9LpQ,17740
|
|
8
|
+
FlowCyPy/directories.py,sha256=kp4c7Aqkr8g0t8zCcnBf-2aght6UoWiU9IKKXsQRfrc,709
|
|
9
|
+
FlowCyPy/flow_cell.py,sha256=u9qvdwnqM3qKS_DXN7rPeNIMHdUASk1uL1qwbJ70sz4,7555
|
|
10
|
+
FlowCyPy/helper.py,sha256=hU8YLUuL8ZCWv9jem_r_Q5e_Av6Vsw9BdqiQhD6DkFg,2962
|
|
11
|
+
FlowCyPy/logger.py,sha256=fiOVIJRfR6u_HKEHe0rb6hawjHR4ToBDOfa1eMv-vFE,5026
|
|
12
|
+
FlowCyPy/noises.py,sha256=ItsytFnSZ0wnf4amXCi4moE6aoPrj1YvB28VCHOJmf4,1073
|
|
13
|
+
FlowCyPy/particle_count.py,sha256=82KmMdRsFmz37pGqe-aDiZJR3VGhHXF7GBcZuizeTG4,4269
|
|
14
|
+
FlowCyPy/physical_constant.py,sha256=giBHQvIMGA4Ukr7C7XenQN3cOgxBKknIzJyBgx3DZB0,555
|
|
15
|
+
FlowCyPy/plottings.py,sha256=JVZE3aMCDCzdVQbbrzdk8M_Z5IyATdWJaaeKr2EBSTg,8629
|
|
16
|
+
FlowCyPy/population.py,sha256=3e5ULnPSavgXoInl2RAABJQKUAD0NXJGHFjk_zthBdI,4510
|
|
17
|
+
FlowCyPy/populations_instances.py,sha256=dzGtYyRzocr6_nr8M68-tIy7kJ-NwolOX0oyqSnlQwY,2327
|
|
18
|
+
FlowCyPy/scatterer_collection.py,sha256=sNyG7eyaFYJ4aF4STbh-64KSgLkqFVQmj-Y_UE6rIPU,12198
|
|
19
|
+
FlowCyPy/signal_digitizer.py,sha256=ASU6_SxFYcOaHy66stWxytPtMXmhpJE9Kpjela_WL-8,2588
|
|
20
|
+
FlowCyPy/source.py,sha256=VZX2Jt3GvnlhbqEXKmI1EQzoH6sPnliNyQjGOa-TQMc,9792
|
|
21
|
+
FlowCyPy/units.py,sha256=1hAG0cQeLzT5nk4dmTF4PdpGSpT_oy7AS3rrtyw4xMM,851
|
|
22
|
+
FlowCyPy/utils.py,sha256=o-EwrTZnpQKgGVPgNVg3_tCHiKYfvVmlcuJmlMjxQcI,7501
|
|
23
|
+
FlowCyPy/coupling_mechanism/__init__.py,sha256=NSxKZl8_Tfg-0AzwYgR8B7Yz2SapvXSQCqW6qEN3X1w,87
|
|
24
|
+
FlowCyPy/coupling_mechanism/empirical.py,sha256=KCHxfWCSR3ja3wTnffZM4sX4E1WKm3UHLuA-xlUoqpQ,2201
|
|
25
|
+
FlowCyPy/coupling_mechanism/mie.py,sha256=IJdJOmeKxqoK9AYlNo3eM2f4TZW8hv-1vJjbrPU4X7Q,7408
|
|
26
|
+
FlowCyPy/coupling_mechanism/rayleigh.py,sha256=2BroKQV5APPKS7JLvgfQWodkODN-7tnoX0xQCSjJ6fY,5026
|
|
27
|
+
FlowCyPy/coupling_mechanism/uniform.py,sha256=_LlgU20RAYEKr-iGz2MSvBJ-GTzSJk9zCC-OHN1YqT0,1611
|
|
28
|
+
FlowCyPy/distribution/__init__.py,sha256=mzkKDY0lUl5O2PpUrV0D2s1Y6x6MipY4w88BYjA2P7s,321
|
|
29
|
+
FlowCyPy/distribution/base_class.py,sha256=3RRoKsfBK2Y-MezMP36i9MOzMXjg_npTO1Wv9iMYa2o,2826
|
|
30
|
+
FlowCyPy/distribution/delta.py,sha256=xyiykhIeYcQ3EAzpH5k8XXtNjSf64g7GSLOphxJ_ZB4,3361
|
|
31
|
+
FlowCyPy/distribution/lognormal.py,sha256=Zi8bG9-jQeubXfi35iWy-dkPd7XDpPJdSNgPWczV8VM,4104
|
|
32
|
+
FlowCyPy/distribution/normal.py,sha256=aw9JBrPlpdupOw2cQKOUiUu6RxTznX4dtWwZl5yZp0s,4256
|
|
33
|
+
FlowCyPy/distribution/particle_size_distribution.py,sha256=iIFbKWQmrQCjL99wdxVHmVHKgk4FympvOw6P4idvJpg,4664
|
|
34
|
+
FlowCyPy/distribution/uniform.py,sha256=xHg2-zhFBD_MDfJYpKUB3XkfoiOGYGYdeB9G3C_AjZI,3472
|
|
35
|
+
FlowCyPy/distribution/weibull.py,sha256=_5FgwHrVViwd3OYUaRDhV0D_DU4vktFyseUQSAdOTp8,3673
|
|
36
|
+
FlowCyPy/peak_locator/__init__.py,sha256=cw2PeNmhB_u1pAHz4L-TZaRei3T3yYl1u-mvpuHBLF0,164
|
|
37
|
+
FlowCyPy/peak_locator/base_class.py,sha256=pySBG0GNKJc55vg5KRd7mF_BP-euefSOM5kkDbKOCjc,5887
|
|
38
|
+
FlowCyPy/peak_locator/basic.py,sha256=GUizuF2yN8jNQRUXYBCHmRdJJeg6-k5rkTwYOpSW50M,3794
|
|
39
|
+
FlowCyPy/peak_locator/derivative.py,sha256=vr9qMqrveiNH4HzSMsLsysJWsn2v_yMBwvbJEcpoKO0,5205
|
|
40
|
+
FlowCyPy/peak_locator/moving_average.py,sha256=BEqZHuryL2G8oZBgxbb98JZ41PF67LGhy_RWCRIWXX8,5853
|
|
41
|
+
FlowCyPy-0.7.0.dist-info/LICENSE,sha256=U6YG4UEW9XJzHa53oijR0qw6JNN_SZ38WOBmYn3NPd0,1072
|
|
42
|
+
FlowCyPy-0.7.0.dist-info/METADATA,sha256=VjFAkdZjdI9_lSRJvoFgtvJ7PdLjaXtLLnkoP4rDacs,8970
|
|
43
|
+
FlowCyPy-0.7.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
44
|
+
FlowCyPy-0.7.0.dist-info/top_level.txt,sha256=jlJHf2aCnk9VyjazDO7LVaNwaB4CfZGK89drjnDG2Uo,9
|
|
45
|
+
FlowCyPy-0.7.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
FlowCyPy
|