AMS-BP 0.0.231__py3-none-any.whl → 0.2.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.
- AMS_BP/__init__.py +1 -1
- AMS_BP/cells/__init__.py +30 -4
- AMS_BP/cells/budding_yeast_cell.py +274 -0
- AMS_BP/cells/cell_factory.py +148 -0
- AMS_BP/configio/configmodels.py +9 -6
- AMS_BP/configio/convertconfig.py +37 -29
- AMS_BP/groundtruth_generators/__init__.py +3 -0
- AMS_BP/groundtruth_generators/nuclearporecomplexes.py +68 -0
- AMS_BP/motion/condensate_movement.py +28 -29
- AMS_BP/motion/movement/__init__.py +1 -6
- AMS_BP/motion/movement/boundary_conditions.py +12 -1
- AMS_BP/motion/track_gen.py +35 -84
- AMS_BP/optics/lasers/laser_profiles.py +27 -185
- AMS_BP/optics/lasers/scanning_patterns.py +102 -0
- AMS_BP/optics/psf/psf_engine.py +25 -8
- AMS_BP/photophysics/photon_physics.py +4 -4
- AMS_BP/photophysics/state_kinetics.py +37 -2
- AMS_BP/probabilityfuncs/probability_functions.py +33 -100
- AMS_BP/sample/sim_sampleplane.py +55 -24
- AMS_BP/sim_config.toml +13 -8
- AMS_BP/sim_microscopy.py +40 -9
- AMS_BP/utils/util_functions.py +9 -0
- {ams_bp-0.0.231.dist-info → ams_bp-0.2.0.dist-info}/METADATA +25 -4
- {ams_bp-0.0.231.dist-info → ams_bp-0.2.0.dist-info}/RECORD +27 -27
- AMS_BP/cells/base_cell.py +0 -55
- AMS_BP/cells/rectangular_cell.py +0 -82
- AMS_BP/cells/rod_cell.py +0 -98
- AMS_BP/cells/spherical_cell.py +0 -74
- AMS_BP/motion/movement/fbm_BP.py +0 -244
- {ams_bp-0.0.231.dist-info → ams_bp-0.2.0.dist-info}/WHEEL +0 -0
- {ams_bp-0.0.231.dist-info → ams_bp-0.2.0.dist-info}/entry_points.txt +0 -0
- {ams_bp-0.0.231.dist-info → ams_bp-0.2.0.dist-info}/licenses/LICENSE +0 -0
@@ -31,7 +31,7 @@ prob_func = multiple_top_hat_probability(
|
|
31
31
|
subspace_centers=np.array([[1, 1], [2, 2], [3, 3]]),
|
32
32
|
subspace_radius=np.array([1.0, 0.5, 0.75]),
|
33
33
|
density_dif=0.2,
|
34
|
-
|
34
|
+
cell=BaseCell type
|
35
35
|
)
|
36
36
|
|
37
37
|
prob = prob_func(np.array([1.5, 1.5]))
|
@@ -41,77 +41,19 @@ Note:
|
|
41
41
|
After initialization, do not change the parameters directly. Use the update_parameters method to modify any values.
|
42
42
|
"""
|
43
43
|
|
44
|
-
|
45
|
-
from typing import
|
46
|
-
from ..cells.spherical_cell import SphericalCell
|
47
|
-
from ..cells.rod_cell import RodCell
|
48
|
-
from ..cells.rectangular_cell import RectangularCell
|
49
|
-
|
50
|
-
CellType = Union[SphericalCell, RodCell, RectangularCell]
|
51
|
-
|
52
|
-
|
53
|
-
def generate_points(
|
54
|
-
pdf: callable,
|
55
|
-
total_points: int,
|
56
|
-
min_x: float,
|
57
|
-
max_x: float,
|
58
|
-
center: np.ndarray,
|
59
|
-
radius: float,
|
60
|
-
bias_subspace_x: float,
|
61
|
-
space_prob: float,
|
62
|
-
density_dif: float,
|
63
|
-
) -> np.ndarray:
|
64
|
-
"""
|
65
|
-
Generates random (x, y) points using the accept/reject method based on a given distribution.
|
44
|
+
from collections.abc import Callable
|
45
|
+
from typing import Tuple
|
66
46
|
|
67
|
-
|
68
|
-
-----------
|
69
|
-
pdf : callable
|
70
|
-
Probability density function to sample from.
|
71
|
-
total_points : int
|
72
|
-
Number of points to generate.
|
73
|
-
min_x : float
|
74
|
-
Minimum x value for sampling.
|
75
|
-
max_x : float
|
76
|
-
Maximum x value for sampling.
|
77
|
-
center : np.ndarray
|
78
|
-
Coordinates of the center of the top-hat distribution.
|
79
|
-
radius : float
|
80
|
-
Radius of the top-hat region.
|
81
|
-
bias_subspace_x : float
|
82
|
-
Probability at the top of the top-hat.
|
83
|
-
space_prob : float
|
84
|
-
Probability outside the top-hat region.
|
85
|
-
density_dif : float
|
86
|
-
Scaling factor for density differences.
|
47
|
+
import numpy as np
|
87
48
|
|
88
|
-
|
89
|
-
--------
|
90
|
-
np.ndarray
|
91
|
-
Array of generated points.
|
92
|
-
"""
|
93
|
-
xy_coords = []
|
94
|
-
while len(xy_coords) < total_points:
|
95
|
-
# generate candidate variable
|
96
|
-
var = np.random.uniform([min_x, min_x], [max_x, max_x])
|
97
|
-
# generate varibale to condition var1
|
98
|
-
var2 = np.random.uniform(0, 1)
|
99
|
-
# apply condition
|
100
|
-
pdf_val = pdf(var, center, radius, bias_subspace_x, space_prob)
|
101
|
-
if var2 < ((1.0 / density_dif) * (max_x - min_x) ** 2) * pdf_val:
|
102
|
-
xy_coords.append(var)
|
103
|
-
return np.array(xy_coords)
|
49
|
+
from ..cells import BaseCell
|
104
50
|
|
105
51
|
|
106
52
|
def generate_points_from_cls(
|
107
|
-
pdf:
|
53
|
+
pdf: Callable,
|
108
54
|
total_points: int,
|
109
|
-
|
110
|
-
|
111
|
-
min_y: float,
|
112
|
-
max_y: float,
|
113
|
-
min_z: float,
|
114
|
-
max_z: float,
|
55
|
+
volume: float,
|
56
|
+
bounds: Tuple[float, float, float, float, float, float],
|
115
57
|
density_dif: float,
|
116
58
|
) -> np.ndarray:
|
117
59
|
"""
|
@@ -123,18 +65,21 @@ def generate_points_from_cls(
|
|
123
65
|
Probability density function to sample from.
|
124
66
|
total_points : int
|
125
67
|
Number of points to generate.
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
68
|
+
bound : list with the following
|
69
|
+
min_x : float
|
70
|
+
Minimum x value for sampling.
|
71
|
+
max_x : float
|
72
|
+
Maximum x value for sampling.
|
73
|
+
min_y : float
|
74
|
+
Minimum y value for sampling.
|
75
|
+
max_y : float
|
76
|
+
Maximum y value for sampling.
|
77
|
+
min_z : float
|
78
|
+
Minimum z value for sampling.
|
79
|
+
max_z : float
|
80
|
+
Maximum z value for sampling.
|
81
|
+
volume : float,
|
82
|
+
volume of region sampling
|
138
83
|
density_dif : float
|
139
84
|
Scaling factor for density differences.
|
140
85
|
|
@@ -143,8 +88,8 @@ def generate_points_from_cls(
|
|
143
88
|
np.ndarray
|
144
89
|
Array of generated (x, y, z) points.
|
145
90
|
"""
|
91
|
+
min_x, max_x, min_y, max_y, min_z, max_z = bounds
|
146
92
|
xyz_coords = []
|
147
|
-
area = (max_x - min_x) * (max_y - min_y) * (max_z - min_z)
|
148
93
|
while len(xyz_coords) < total_points:
|
149
94
|
# generate candidate variable
|
150
95
|
var = np.random.uniform([min_x, min_y, min_z], [max_x, max_y, max_z])
|
@@ -152,7 +97,7 @@ def generate_points_from_cls(
|
|
152
97
|
var2 = np.random.uniform(0, 1)
|
153
98
|
# apply condition
|
154
99
|
pdf_val = pdf(var)
|
155
|
-
if var2 < ((1.0 / density_dif) *
|
100
|
+
if var2 < ((1.0 / density_dif) * volume) * pdf_val:
|
156
101
|
xyz_coords.append(var)
|
157
102
|
return np.array(xyz_coords)
|
158
103
|
|
@@ -166,7 +111,7 @@ class multiple_top_hat_probability:
|
|
166
111
|
subspace_centers: np.ndarray,
|
167
112
|
subspace_radius: np.ndarray,
|
168
113
|
density_dif: float,
|
169
|
-
cell:
|
114
|
+
cell: BaseCell,
|
170
115
|
) -> None:
|
171
116
|
"""
|
172
117
|
Initialize the probability function.
|
@@ -181,7 +126,7 @@ class multiple_top_hat_probability:
|
|
181
126
|
Radius of each subspace
|
182
127
|
density_dif : float
|
183
128
|
Difference in density between subspaces and non-subspaces
|
184
|
-
cell :
|
129
|
+
cell : BaseCell
|
185
130
|
Cell object defining the boundary
|
186
131
|
"""
|
187
132
|
self.num_subspace = num_subspace
|
@@ -205,7 +150,7 @@ class multiple_top_hat_probability:
|
|
205
150
|
raise TypeError("Position must be a numpy array.")
|
206
151
|
|
207
152
|
# First check if point is within the cell
|
208
|
-
if not self.cell.contains_point(position):
|
153
|
+
if not self.cell.contains_point(*position):
|
209
154
|
return 0.0
|
210
155
|
|
211
156
|
# Then check if point is within any subspace
|
@@ -285,14 +230,12 @@ class multiple_top_hat_probability:
|
|
285
230
|
self._density_dif = value
|
286
231
|
|
287
232
|
@property
|
288
|
-
def cell(self) ->
|
233
|
+
def cell(self) -> BaseCell:
|
289
234
|
"""Returns the cell object."""
|
290
235
|
return self._cell
|
291
236
|
|
292
237
|
@cell.setter
|
293
|
-
def cell(self, value:
|
294
|
-
if not isinstance(value, CellType):
|
295
|
-
raise TypeError("Cell must be a valid cell object.")
|
238
|
+
def cell(self, value: BaseCell) -> None:
|
296
239
|
self._cell = value
|
297
240
|
|
298
241
|
@property
|
@@ -318,7 +261,7 @@ class multiple_top_hat_probability:
|
|
318
261
|
subspace_centers: np.ndarray | None = None,
|
319
262
|
subspace_radius: np.ndarray | None = None,
|
320
263
|
density_dif: float | None = None,
|
321
|
-
cell:
|
264
|
+
cell: BaseCell | None = None,
|
322
265
|
) -> None:
|
323
266
|
"""Updates the parameters of the probability function."""
|
324
267
|
if num_subspace is not None:
|
@@ -332,19 +275,9 @@ class multiple_top_hat_probability:
|
|
332
275
|
if cell is not None:
|
333
276
|
self.cell = cell
|
334
277
|
|
335
|
-
# Recalculate total volume based on cell type
|
336
|
-
if isinstance(self.cell, SphericalCell):
|
337
|
-
total_volume = (4 / 3) * np.pi * self.cell.radius**3
|
338
|
-
elif isinstance(self.cell, RodCell):
|
339
|
-
total_volume = self.cell.volume
|
340
|
-
elif isinstance(self.cell, RectangularCell):
|
341
|
-
total_volume = float(np.prod(self.cell.dimensions))
|
342
|
-
else:
|
343
|
-
raise ValueError("Unsupported cell type")
|
344
|
-
|
345
278
|
self.subspace_probability = self._calculate_subspace_probability(
|
346
|
-
|
279
|
+
self.cell.volume, self.density_dif
|
347
280
|
)
|
348
281
|
self.non_subspace_probability = self._calculate_non_subspace_probability(
|
349
|
-
|
282
|
+
self.cell.volume, self.density_dif, self.num_subspace, self.subspace_radius
|
350
283
|
)
|
AMS_BP/sample/sim_sampleplane.py
CHANGED
@@ -133,8 +133,8 @@ class SampleSpace:
|
|
133
133
|
z_min, z_max = fov.z_bounds
|
134
134
|
|
135
135
|
return (
|
136
|
-
|
137
|
-
and
|
136
|
+
x_min <= x_min <= x_max <= self.x_max
|
137
|
+
and x_min <= y_min <= y_max <= self.y_max
|
138
138
|
and self.z_min <= z_min <= z_max <= self.z_max
|
139
139
|
)
|
140
140
|
|
@@ -207,23 +207,23 @@ class SamplePlane:
|
|
207
207
|
trajectory: Optional[Dict[int, Tuple[float, float, float]]] = None,
|
208
208
|
) -> bool:
|
209
209
|
"""Add a fluorescent object to the sample plane"""
|
210
|
-
# Verify position is within sample space
|
211
|
-
if not self._space.contains_position(position):
|
212
|
-
|
213
|
-
|
214
|
-
# Verify initial position is within FOV
|
215
|
-
if not self.is_within_fov(position):
|
216
|
-
|
217
|
-
|
218
|
-
# If trajectory provided, verify all positions
|
219
|
-
if trajectory is not None:
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
210
|
+
# # Verify position is within sample space
|
211
|
+
# if not self._space.contains_position(position):
|
212
|
+
# return False
|
213
|
+
#
|
214
|
+
# # Verify initial position is within FOV
|
215
|
+
# if not self.is_within_fov(position):
|
216
|
+
# return False
|
217
|
+
|
218
|
+
# # If trajectory provided, verify all positions
|
219
|
+
# if trajectory is not None:
|
220
|
+
# if not all(
|
221
|
+
# self._space.contains_position(pos) for pos in trajectory.values()
|
222
|
+
# ):
|
223
|
+
# return False
|
224
|
+
# if not all(self.is_within_fov(pos) for pos in trajectory.values()):
|
225
|
+
# return False
|
226
|
+
#
|
227
227
|
if object_id in self._objects:
|
228
228
|
return False
|
229
229
|
|
@@ -239,11 +239,11 @@ class SamplePlane:
|
|
239
239
|
obj = FluorescentObject(object_id, position, fluorophore, trajectory)
|
240
240
|
self._objects[object_id] = obj
|
241
241
|
|
242
|
-
# Update spatial index for all time points
|
243
|
-
for t in self.time_points:
|
244
|
-
|
245
|
-
|
246
|
-
|
242
|
+
# # Update spatial index for all time points
|
243
|
+
# for t in self.time_points:
|
244
|
+
# pos = trajectory[t]
|
245
|
+
# self._update_spatial_index(object_id, pos, t)
|
246
|
+
#
|
247
247
|
return True
|
248
248
|
|
249
249
|
def get_all_objects(self) -> List[FluorescentObject]:
|
@@ -332,3 +332,34 @@ class SamplePlane:
|
|
332
332
|
) -> Tuple[Tuple[float, float], Tuple[float, float], Tuple[float, float]]:
|
333
333
|
"""Return the sample space bounds"""
|
334
334
|
return self._space.bounds
|
335
|
+
|
336
|
+
|
337
|
+
def _FOV_lims(
|
338
|
+
xyoffset: Tuple[float, float],
|
339
|
+
detector_pixelcount: Tuple[int, int],
|
340
|
+
detector_pixelsize_magnification: float,
|
341
|
+
) -> Tuple[Tuple[float, float], Tuple[float, float]]:
|
342
|
+
"""
|
343
|
+
Utility to determine the FOV (what regions in the sample space the camera can capture) -> mainly used for defining laser position callables.
|
344
|
+
|
345
|
+
Parameters:
|
346
|
+
-----------
|
347
|
+
xyoffset: Tuple[float, float]
|
348
|
+
position in the sample plane which defines the bottom left corner on the detector pixel array; in units of the sample space (um)
|
349
|
+
|
350
|
+
detector_pixelcount: Tuple[int, int]
|
351
|
+
number of pixels in the detector in the both x and y
|
352
|
+
|
353
|
+
detector_pixelsize_magnification: float
|
354
|
+
the pixel size of each pixel (of detector_pixelcount) after the magnification of the optical setup is considered. I.e what each pixel in the final image represents in the units of the sample space (um).
|
355
|
+
|
356
|
+
Returns:
|
357
|
+
--------
|
358
|
+
(x_lims, y_lims): Tuple[Tuple[float, float], Tuple[float, float]]
|
359
|
+
min < max for each lim
|
360
|
+
"""
|
361
|
+
x_min = xyoffset[0]
|
362
|
+
y_min = xyoffset[1]
|
363
|
+
x_max = x_min + detector_pixelcount[0] * detector_pixelsize_magnification
|
364
|
+
y_max = y_min + detector_pixelcount[1] * detector_pixelsize_magnification
|
365
|
+
return ((x_min, x_max), (y_min, y_max))
|
AMS_BP/sim_config.toml
CHANGED
@@ -1,26 +1,31 @@
|
|
1
|
-
version = "0.
|
1
|
+
version = "0.2"
|
2
2
|
length_unit = "um" # always um.
|
3
3
|
time_unit = "ms" # always ms
|
4
4
|
diffusion_unit = "um^2/s" # always um^2/s
|
5
5
|
|
6
6
|
[Cell_Parameters]
|
7
|
-
|
8
|
-
|
7
|
+
cell_type = "RodCell" # any of RectangularCell, SphericalCell, OvoidCell, RodCell, BuddingCell
|
8
|
+
[Cell_Parameters.params] # see docs for parameters for each cell type
|
9
|
+
center = [5, 5, 0]
|
10
|
+
direction = [1, 0, 0]
|
11
|
+
radius = 1.0
|
12
|
+
height = 4.0
|
13
|
+
# bounds = [[3, 7], [3, 9], [-1, 1]]
|
9
14
|
|
10
15
|
[Molecule_Parameters]
|
11
16
|
num_molecules = [
|
12
17
|
5000,
|
13
18
|
5000,
|
14
19
|
] # size of array tells the types of molecules (must be same as num_of_fluorophores below). All of the Molecule_Parameters are of the same first dimension as this.
|
15
|
-
track_type = ["
|
20
|
+
track_type = ["fbm", "fbm"] # "constant", "fbm"
|
16
21
|
diffusion_coefficient = [
|
17
22
|
[
|
18
|
-
0.
|
19
|
-
0.
|
23
|
+
0.2,
|
24
|
+
0.4,
|
20
25
|
],
|
21
26
|
[
|
22
|
-
0.
|
23
|
-
0.
|
27
|
+
0.2,
|
28
|
+
0.4,
|
24
29
|
],
|
25
30
|
] # um^2/s, size of each index (eg. len(...[0]) is the # of diffusion coefficients the system can explore.
|
26
31
|
|
AMS_BP/sim_microscopy.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
from dataclasses import dataclass
|
2
|
-
from typing import Callable, Dict, List, Literal, Optional, Tuple
|
2
|
+
from typing import Callable, Dict, List, Literal, Optional, Tuple, Union
|
3
3
|
|
4
4
|
import numpy as np
|
5
5
|
|
@@ -16,7 +16,7 @@ from .photophysics.photon_physics import (
|
|
16
16
|
incident_photons,
|
17
17
|
)
|
18
18
|
from .photophysics.state_kinetics import StateTransitionCalculator
|
19
|
-
from .sample.flurophores.flurophore_schema import WavelengthDependentProperty
|
19
|
+
from .sample.flurophores.flurophore_schema import StateType, WavelengthDependentProperty
|
20
20
|
from .sample.sim_sampleplane import EMPTY_STATE_HISTORY_DICT, SamplePlane
|
21
21
|
from .utils.util_functions import ms_to_seconds
|
22
22
|
|
@@ -70,10 +70,14 @@ class VirtualMicroscope:
|
|
70
70
|
"_time": self._time,
|
71
71
|
}
|
72
72
|
|
73
|
-
def _set_laser_powers(
|
73
|
+
def _set_laser_powers(
|
74
|
+
self, laser_power: Dict[str, Union[float, Callable[[float], float]]]
|
75
|
+
) -> None:
|
74
76
|
if laser_power is not None:
|
75
77
|
for laser in laser_power.keys():
|
76
|
-
if isinstance(self.lasers[laser].params.power, float)
|
78
|
+
if isinstance(self.lasers[laser].params.power, float) and isinstance(
|
79
|
+
laser_power[laser], float
|
80
|
+
):
|
77
81
|
if laser_power[laser] > self.lasers[laser].params.max_power:
|
78
82
|
raise ValueError(
|
79
83
|
"Provided laser power for laser: {} nm, is larger than the maximum power: {}".format(
|
@@ -84,7 +88,14 @@ class VirtualMicroscope:
|
|
84
88
|
self.lasers[laser].params.power = laser_power[laser]
|
85
89
|
|
86
90
|
def _set_laser_positions(
|
87
|
-
self,
|
91
|
+
self,
|
92
|
+
laser_positions: Dict[
|
93
|
+
str,
|
94
|
+
Union[
|
95
|
+
Tuple[float, float, float],
|
96
|
+
Callable[[float], Tuple[float, float, float]],
|
97
|
+
],
|
98
|
+
],
|
88
99
|
) -> None:
|
89
100
|
if laser_positions is not None:
|
90
101
|
for laser in laser_positions.keys():
|
@@ -93,15 +104,28 @@ class VirtualMicroscope:
|
|
93
104
|
def run_sim(
|
94
105
|
self,
|
95
106
|
z_val: float, # um
|
96
|
-
laser_power: Dict[
|
107
|
+
laser_power: Dict[
|
108
|
+
str, Union[float, Callable[[float], float]] # power or f(t) -> power
|
109
|
+
], # str = lasername, float = power in W
|
97
110
|
xyoffset: Tuple[
|
98
111
|
float, float
|
99
112
|
], # location of the bottom left corner of the field of view -> sample -> camera
|
100
|
-
laser_position:
|
101
|
-
|
113
|
+
laser_position: Optional[
|
114
|
+
Dict[
|
115
|
+
str, # laser name
|
116
|
+
Union[
|
117
|
+
Tuple[float, float, float], # x, y, z
|
118
|
+
Callable[[float], Tuple[float, float, float]], # f(t) -> x, y, z
|
119
|
+
],
|
120
|
+
]
|
121
|
+
] = None, # str = lasername, Tuple = x, y, z in um at the sample plane
|
102
122
|
duration_total: Optional[int] = None, # ms
|
103
123
|
exposure_time: Optional[int] = None,
|
104
124
|
interval_time: Optional[int] = None,
|
125
|
+
scanning: Optional[
|
126
|
+
bool
|
127
|
+
] = False, # True if scanning -> laser will autoposition to the xy location of the fluorophore but at the z_val of the plane being imaged and NOT the z value of the fluorophore.
|
128
|
+
# as a consequence the "effective" time spent by the laser of on the fluorophore position is not the dwell time of traditional confocal, but "always on". TODO: better fix.
|
105
129
|
) -> Tuple[np.ndarray, MetaData]:
|
106
130
|
self._set_laser_powers(laser_power=laser_power)
|
107
131
|
if laser_position is not None:
|
@@ -149,7 +173,9 @@ class VirtualMicroscope:
|
|
149
173
|
statehist = fluorObj.state_history[time]
|
150
174
|
# if not aval transitions go next
|
151
175
|
# this assumes that the bleached state is the only state from which there are no more transitions
|
152
|
-
if not statehist[2]
|
176
|
+
if (not statehist[2]) and (
|
177
|
+
statehist[0].state_type != StateType.FLUORESCENT
|
178
|
+
):
|
153
179
|
fluorObj.state_history[time + self.sample_plane.dt] = statehist
|
154
180
|
continue
|
155
181
|
|
@@ -165,6 +191,11 @@ class VirtualMicroscope:
|
|
165
191
|
) -> dict:
|
166
192
|
laser_intensities = {}
|
167
193
|
for laserID in laser_power.keys():
|
194
|
+
if scanning:
|
195
|
+
self.lasers[laserID].params.position = (
|
196
|
+
*florPos[:2],
|
197
|
+
0,
|
198
|
+
) # z value is 0 since this is the neew focus plane
|
168
199
|
laser_intensities[laserID] = {
|
169
200
|
"wavelength": self.lasers[laserID].params.wavelength,
|
170
201
|
"intensity": (
|
AMS_BP/utils/util_functions.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import json
|
2
2
|
import os
|
3
3
|
import pickle
|
4
|
+
from bisect import bisect_right
|
4
5
|
|
5
6
|
import numpy as np
|
6
7
|
import skimage as skimage
|
@@ -9,6 +10,14 @@ from PIL import Image
|
|
9
10
|
from ..utils.decorators import cache
|
10
11
|
|
11
12
|
|
13
|
+
def find_le(a, x) -> int:
|
14
|
+
"Find rightmost value less than or equal to x"
|
15
|
+
i = bisect_right(a, x)
|
16
|
+
if i:
|
17
|
+
return a[i - 1]
|
18
|
+
raise ValueError
|
19
|
+
|
20
|
+
|
12
21
|
def convert_arrays_to_lists(obj: np.ndarray | dict) -> list | dict:
|
13
22
|
"""
|
14
23
|
Recursively convert NumPy arrays to lists.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: AMS_BP
|
3
|
-
Version: 0.0
|
3
|
+
Version: 0.2.0
|
4
4
|
Summary: Advanced Microscopy Simulations developed for the Weber Lab by Baljyot Singh Parmar
|
5
5
|
Project-URL: Documentation, https://joemans3.github.io/AMS_BP/
|
6
6
|
Project-URL: Source code, https://github.com/joemans3/AMS_BP
|
@@ -8,10 +8,12 @@ Author-email: Baljyot Singh Parmar <baljyotparmar@hotmail.com>
|
|
8
8
|
Maintainer-email: Baljyot Singh Parmar <baljyotparmar@hotmail.com>
|
9
9
|
License-File: LICENSE
|
10
10
|
Keywords: SMS
|
11
|
-
Requires-Python: >=3.
|
11
|
+
Requires-Python: >=3.12
|
12
|
+
Requires-Dist: boundedfbm>=0.2.0
|
12
13
|
Requires-Dist: jsonschema>=4.23.0
|
13
14
|
Requires-Dist: numpy>=1.21.2
|
14
15
|
Requires-Dist: pydantic>=2.9.2
|
16
|
+
Requires-Dist: pyvista>=0.44.2
|
15
17
|
Requires-Dist: scikit-image>=0.18.3
|
16
18
|
Requires-Dist: scipy>=1.7.1
|
17
19
|
Requires-Dist: tomli>=2.0.2
|
@@ -79,6 +81,14 @@ run_AMS_BP runsim CONFIG_FILE
|
|
79
81
|
- `-o, --output_path PATH`: Specify the output directory for the configuration file
|
80
82
|
- `-r, --recursive_o`: Create output directory if it doesn't exist
|
81
83
|
|
84
|
+
## Overview of Simulation Workflow
|
85
|
+

|
86
|
+
*A ground truth is created, **a**, with $`f_{n}`$ fluorophore types of $`N_{f_{n}}`$ molecules each. If applicable, the motion of these molecules is modelled using a 3D bounded FBM with fluctuating generalized diffusion coefficients and Hurst parameters. Variations are modelled as a Markov Chain and require rate constants as parameters. Different fluorophores can have different motion models. The resolution of the motion models is $`\Delta t`$ and cannot be smaller than 1 ms (for computational efficiency). Given the microscope parameters specific to the experimental procedure to simulate, at every time $`t_{j}`$, the excitation intensity for each channel (**b**) is calculated at each fluorophore's location, **c**. For $`t_{j} \rightarrow t_{j+\Delta t}`$, the photophysical state trajectory of the fluorophore is simulated using the light intensity at the molecule's location as input for any light-dependent transition rates, **d**. For the duration that the shutter is open and light is emitted from the sample, emission filters for each channel are applied before the convolution with PSF models, **e**. The incident photons on the detector are then converted to photoelectrons and finally to digital units using the detector models provided, **f**.*
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
|
82
92
|
## Configuration File
|
83
93
|
|
84
94
|
The configuration file (sim_config.toml) is divided into several key sections:
|
@@ -96,7 +106,6 @@ diffusion_unit = "um^2/s" # diffusion coefficient units
|
|
96
106
|
|
97
107
|
1. **Cell Parameters**
|
98
108
|
- Define cell space dimensions
|
99
|
-
- Set cell axial radius
|
100
109
|
|
101
110
|
2. **Molecule Parameters**
|
102
111
|
- Number of molecules per type
|
@@ -124,7 +133,8 @@ diffusion_unit = "um^2/s" # diffusion coefficient units
|
|
124
133
|
|
125
134
|
## Running Experiments
|
126
135
|
|
127
|
-
AMS-BP supports two types of experiments:
|
136
|
+
AMS-BP's CLI currently supports two types of experiments:
|
137
|
+
> (however this can be extended when used as a library)
|
128
138
|
|
129
139
|
### 1. Time Series
|
130
140
|
```toml
|
@@ -171,3 +181,14 @@ frames, metadata = function_exp(microscope=microscope, config=config_exp)
|
|
171
181
|
from AMS_BP.configio.saving import save_config_frames
|
172
182
|
save_config_frames(metadata, frames, setup_config["base_config"].OutputParameters)
|
173
183
|
```
|
184
|
+
|
185
|
+
## API Reference and Docs
|
186
|
+
Find detailed API references for the library at: [joemans3/github.io/AMS_BP](https://joemans3.github.io/AMS_BP/)
|
187
|
+
> A more detailed example is provided in the jupyter notebook in the examples. For starters refer to the [VisualizingIndividualModules](examples/VisualizingIndividualModules/modules_explained.ipynb). Then head over to the [laser modulation module](examples/VisualizingIndividualModules/laser_modulation.ipynb) which will show how to change the laser power over time in the simulations. Then view an example of a complex experiment setup for [FRAP](examples/QuantitativeExperiments/FRAP_methods.ipynb) which is possible by the use of compositions of modules in this simulation library.
|
188
|
+
|
189
|
+
## High Priority Features
|
190
|
+
1. Irregular cell shapes with motion models
|
191
|
+
2. Stimulated Emission models
|
192
|
+
3. STORM workflow examples
|
193
|
+
4. CTRW motion models
|
194
|
+
5. Simpler configurations
|
@@ -1,25 +1,24 @@
|
|
1
|
-
AMS_BP/__init__.py,sha256=
|
1
|
+
AMS_BP/__init__.py,sha256=pj8JaDmWwnqBAxuQAgDPFFVkI2FOkCRpIN4GlyKBTQw,326
|
2
2
|
AMS_BP/run_cell_simulation.py,sha256=7InopFikjo0HfaLO2siXskBIbyCIte9avG4YXjjaWCI,7420
|
3
|
-
AMS_BP/sim_config.toml,sha256=
|
4
|
-
AMS_BP/sim_microscopy.py,sha256=
|
5
|
-
AMS_BP/cells/__init__.py,sha256=
|
6
|
-
AMS_BP/cells/
|
7
|
-
AMS_BP/cells/
|
8
|
-
AMS_BP/cells/rod_cell.py,sha256=jQ1kLEk74Pv2rcXPRJ6-QJJhux-mYiDSytzqlxCNWfA,3181
|
9
|
-
AMS_BP/cells/spherical_cell.py,sha256=n3ou3tW0nCxXIwv6uLkVKHkYCfgoNn8VI6CVTLBIll0,2140
|
3
|
+
AMS_BP/sim_config.toml,sha256=G0wW9qsxciZA1Y0Zm6YgZ00ZDBEBBLw_XXq4gsVRjSY,11778
|
4
|
+
AMS_BP/sim_microscopy.py,sha256=Vsga9lTWqP0pjEnfFj0qKaSz7YZ_F4E3TqsaErwhi3E,19991
|
5
|
+
AMS_BP/cells/__init__.py,sha256=Rd2gpWWUZJxW2u_piI2ZcIqLtYkzVOr_MjU3upiUv8Q,866
|
6
|
+
AMS_BP/cells/budding_yeast_cell.py,sha256=BiZ_rML5xjcS8NMP785VzUPVxo41yhihsbvbwSYLQvM,9440
|
7
|
+
AMS_BP/cells/cell_factory.py,sha256=Mhk-0KzLVfaub81Asj5PibOcps0s8I24iC4qZs0VVK4,4435
|
10
8
|
AMS_BP/configio/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
-
AMS_BP/configio/configmodels.py,sha256=
|
12
|
-
AMS_BP/configio/convertconfig.py,sha256=
|
9
|
+
AMS_BP/configio/configmodels.py,sha256=9rPXIYh228fEEf4tDGcE0kSC_RB97VocBaIobhCeuBQ,2998
|
10
|
+
AMS_BP/configio/convertconfig.py,sha256=Np2xKMnAKMkqPip_uqGYOUmp7_5BWn1ZnUBesfkyvis,34588
|
13
11
|
AMS_BP/configio/experiments.py,sha256=HdfaSi0gPPJ_wLF87XcW5ICja19Uezx7-ygFEwNzi30,3995
|
14
12
|
AMS_BP/configio/saving.py,sha256=596QgAadV32rzsN4B2FngGFcBWCzCDnLFN-qtQsv3bM,857
|
13
|
+
AMS_BP/groundtruth_generators/__init__.py,sha256=UPVmhiB81OfyqAes5LoN-n6XgQuBCYCqRPAGd2jpMfc,99
|
14
|
+
AMS_BP/groundtruth_generators/nuclearporecomplexes.py,sha256=1aBcWltsKo0OGd7A9GfuEZ3azQBx5SzpjrSLLMXuYn8,2518
|
15
15
|
AMS_BP/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
16
|
AMS_BP/metadata/metadata.py,sha256=YDumjc5sI3lY_UZx8f0ZhMqbG2qKQkysXwl7CY4ZtnY,2927
|
17
17
|
AMS_BP/motion/__init__.py,sha256=cy3W-wCRjjlN1DrTqYc-JltYwcE8SZCXMVPJ2o6q_BQ,178
|
18
|
-
AMS_BP/motion/condensate_movement.py,sha256=
|
19
|
-
AMS_BP/motion/track_gen.py,sha256=
|
20
|
-
AMS_BP/motion/movement/__init__.py,sha256=
|
21
|
-
AMS_BP/motion/movement/boundary_conditions.py,sha256=
|
22
|
-
AMS_BP/motion/movement/fbm_BP.py,sha256=dH-JZiAInnIaZXH1wAAo8dOIX9zafclqnZ4dOhKtnO0,9327
|
18
|
+
AMS_BP/motion/condensate_movement.py,sha256=TXSsX1UiCfJJhyWnnK0nOgYkg06LTrhCXiBV7u6KjA0,11478
|
19
|
+
AMS_BP/motion/track_gen.py,sha256=V3bFDxDajObRhPWiOzjWiW_VA9aJEWFwDjxMqqlVRXs,17543
|
20
|
+
AMS_BP/motion/movement/__init__.py,sha256=tBNb9UVDPAAnjENRtvI35YF2BdKKBqBkgWJMZSENL8U,59
|
21
|
+
AMS_BP/motion/movement/boundary_conditions.py,sha256=AxBpvR2zredg6uaZoI1fypxkaRd0IZP8MBbkfMh5sKk,2546
|
23
22
|
AMS_BP/optics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
24
23
|
AMS_BP/optics/camera/__init__.py,sha256=eCoDUFHcoCWgbgYdLn8EH7AULM53A3XWTXNZnV8QxeY,182
|
25
24
|
AMS_BP/optics/camera/detectors.py,sha256=_815Ovo7Aj375OZh5Xim8pFuZEEcSVtSdnLRYFqb3_8,10355
|
@@ -29,17 +28,18 @@ AMS_BP/optics/filters/filters.py,sha256=-iw7eqmDO77SEqlFTv5jJNVwpA8y93TLsjy5hhsA
|
|
29
28
|
AMS_BP/optics/filters/channels/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
30
29
|
AMS_BP/optics/filters/channels/channelschema.py,sha256=SConyA5yVdfnI_8sgcxVC8SV7S8tGUJYPPC6jn7lglU,906
|
31
30
|
AMS_BP/optics/lasers/__init__.py,sha256=T7dHohhyLf_pBw4TidarYHWmiwxVXGE71-Bf1aeBbuc,564
|
32
|
-
AMS_BP/optics/lasers/laser_profiles.py,sha256=
|
31
|
+
AMS_BP/optics/lasers/laser_profiles.py,sha256=_h3g_TjolJI5NTg7T_m_ntyNpSFTJvxW0AeXf0svm-I,17284
|
32
|
+
AMS_BP/optics/lasers/scanning_patterns.py,sha256=Xen96e5BlYI892HzZDXdwm80id6TbyNCNj-qvnRnSnI,3393
|
33
33
|
AMS_BP/optics/psf/__init__.py,sha256=ezrKPgpTeR4gTHOvF0mhF6u2zMMTd8Bgp8PGeOf11fA,121
|
34
|
-
AMS_BP/optics/psf/psf_engine.py,sha256=
|
34
|
+
AMS_BP/optics/psf/psf_engine.py,sha256=FbR4VHQ-VgCWrrDj8AHPPnVgwVUGs-OP19w_TjcbMcU,10215
|
35
35
|
AMS_BP/photophysics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
36
|
-
AMS_BP/photophysics/photon_physics.py,sha256=
|
37
|
-
AMS_BP/photophysics/state_kinetics.py,sha256=
|
36
|
+
AMS_BP/photophysics/photon_physics.py,sha256=9FWBXaxuSRaSxW8bY0x1d5R5buooibZbRdYTuQcMXhQ,6624
|
37
|
+
AMS_BP/photophysics/state_kinetics.py,sha256=hDb1VqoeEkbYcse-N-S7BzyE4hIt4KLMju7ZKOIJDYc,6980
|
38
38
|
AMS_BP/probabilityfuncs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
39
39
|
AMS_BP/probabilityfuncs/markov_chain.py,sha256=LV6KGr8Lv4NIvBPJqsR0CEynssa_mPH30qLaK85GObA,4339
|
40
|
-
AMS_BP/probabilityfuncs/probability_functions.py,sha256=
|
40
|
+
AMS_BP/probabilityfuncs/probability_functions.py,sha256=sYLhR61x-w322hxk368jUStH11Wq-KbqOU9zArZlatg,9662
|
41
41
|
AMS_BP/sample/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
42
|
-
AMS_BP/sample/sim_sampleplane.py,sha256=
|
42
|
+
AMS_BP/sample/sim_sampleplane.py,sha256=szr0Y9zFsaJy0aY_Gm5AAVBbY8UsRwehxowUGfaK_2Q,12889
|
43
43
|
AMS_BP/sample/flurophores/__init__.py,sha256=arLVUx1-yh5T41fH9Mr6RNY8Ao3ZioFQUtsfEZlzQkU,250
|
44
44
|
AMS_BP/sample/flurophores/flurophore_schema.py,sha256=j8jnr4w4ltuhXUkjd74IoyyuotyH52mn8FWkgahX5Vw,10886
|
45
45
|
AMS_BP/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -47,9 +47,9 @@ AMS_BP/utils/constants.py,sha256=-r3cnEiuxb-XzRgGhpOuJshYYhKnDu_hv0YSffkxAfc,273
|
|
47
47
|
AMS_BP/utils/decorators.py,sha256=4qFdvzPJne0dhkhD1znPxRln1Rfr5NX8rdcCDcbATRU,6224
|
48
48
|
AMS_BP/utils/errors.py,sha256=7BOd-L4_YeKmWn3Q4EOdTnNF3Bj_exDa3eg5X0yCZrc,759
|
49
49
|
AMS_BP/utils/maskMaker.py,sha256=2ca3n2nc8rFtUh1LurKXOJJsUmhrOpWbRnVX7fjRVvs,335
|
50
|
-
AMS_BP/utils/util_functions.py,sha256=
|
51
|
-
ams_bp-0.0.
|
52
|
-
ams_bp-0.0.
|
53
|
-
ams_bp-0.0.
|
54
|
-
ams_bp-0.0.
|
55
|
-
ams_bp-0.0.
|
50
|
+
AMS_BP/utils/util_functions.py,sha256=9Qlr4kjY04fObktR8TrzB0IgoG1yXtcmxPRX9AN34mM,9671
|
51
|
+
ams_bp-0.2.0.dist-info/METADATA,sha256=GJLdow0hQ3y6LLNubb0q0xfzw00oSeftbRgfnr_K4u8,7658
|
52
|
+
ams_bp-0.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
53
|
+
ams_bp-0.2.0.dist-info/entry_points.txt,sha256=MFUK9bZWW61djfsavqopMqiVPVn4lJtt6v8qzyEFyNM,76
|
54
|
+
ams_bp-0.2.0.dist-info/licenses/LICENSE,sha256=k_-JV1DQKvO0FR8WjvOisqdTl0kp6VJ7RFM3YZhao0c,1071
|
55
|
+
ams_bp-0.2.0.dist-info/RECORD,,
|