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
@@ -0,0 +1,68 @@
|
|
1
|
+
import numpy as np
|
2
|
+
|
3
|
+
|
4
|
+
def generate_nup96_positions(
|
5
|
+
ring_diameter: float = 107.0,
|
6
|
+
molecule_spacing: float = 12.0,
|
7
|
+
ring_spacing: float = 50.0,
|
8
|
+
) -> np.ndarray:
|
9
|
+
"""
|
10
|
+
Generate the 3D coordinates of Nup96 proteins in the nuclear pore complex.
|
11
|
+
|
12
|
+
Parameters:
|
13
|
+
-----------
|
14
|
+
ring_diameter : float
|
15
|
+
Diameter of the main ring in nanometers (default: 107.0 nm)
|
16
|
+
molecule_spacing : float
|
17
|
+
Distance between two Nup96 molecules within same section (default: 12.0 nm)
|
18
|
+
ring_spacing : float
|
19
|
+
Distance between nuclear and cytoplasmic rings in z-direction (default: 50.0 nm)
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
--------
|
23
|
+
numpy.ndarray
|
24
|
+
Array of shape (32, 3) containing x, y, z coordinates for all Nup96 proteins in um
|
25
|
+
First 32 coordinates are the main structural Nup96 (16 nuclear, 16 cytoplasmic)
|
26
|
+
"""
|
27
|
+
|
28
|
+
# Initialize array to store coordinates
|
29
|
+
coordinates = np.zeros((32, 3))
|
30
|
+
ring_radius = ring_diameter / 2
|
31
|
+
|
32
|
+
# Generate positions for both main rings (nuclear and cytoplasmic)
|
33
|
+
for ring in range(2): # 0 = nuclear side, 1 = cytoplasmic side
|
34
|
+
z = ring_spacing / 2 if ring == 0 else -ring_spacing / 2
|
35
|
+
|
36
|
+
for octant in range(8):
|
37
|
+
# Calculate base angle for this octant
|
38
|
+
base_angle = octant * 2 * np.pi / 8
|
39
|
+
|
40
|
+
# Calculate the center position of this octamer
|
41
|
+
center_x = ring_radius * np.cos(base_angle)
|
42
|
+
center_y = ring_radius * np.sin(base_angle)
|
43
|
+
|
44
|
+
# Place two Nup96 molecules in each octant section
|
45
|
+
for molecule in range(2):
|
46
|
+
# Calculate the offset direction perpendicular to the radius
|
47
|
+
perpendicular_angle = (
|
48
|
+
base_angle
|
49
|
+
+ np.pi / 2
|
50
|
+
+ molecule_spacing / 3 * (1 if molecule == 0 else -1)
|
51
|
+
)
|
52
|
+
|
53
|
+
# Offset from center position
|
54
|
+
offset = (molecule_spacing / 3) * (-1 if molecule == 0 else 1) + (
|
55
|
+
molecule_spacing / 5
|
56
|
+
) * (-1 if ring == 0 else 1)
|
57
|
+
|
58
|
+
# Calculate final x and y coordinates
|
59
|
+
x = center_x + offset * np.cos(perpendicular_angle)
|
60
|
+
y = center_y + offset * np.sin(perpendicular_angle)
|
61
|
+
|
62
|
+
# Store coordinates
|
63
|
+
idx = ring * 16 + octant * 2 + molecule
|
64
|
+
coordinates[idx] = [x, y, z]
|
65
|
+
# add 1 nm gitter
|
66
|
+
coordinates[idx] += np.random.normal(0, 1, 3)
|
67
|
+
|
68
|
+
return coordinates / 1000.0
|
@@ -15,16 +15,19 @@ Usage:
|
|
15
15
|
"units_position":'um',
|
16
16
|
"condensate_id":0,
|
17
17
|
"initial_scale":0,
|
18
|
+
"oversample_motion_time":20,
|
18
19
|
})
|
19
20
|
Call the class object as follows to get the position and scale of the condensate at a given time:
|
20
21
|
condensate(times, time_unit) -> dict{"Position":np.ndarray, "Scale":float}
|
21
22
|
"""
|
22
23
|
|
24
|
+
from typing import Optional
|
25
|
+
|
23
26
|
import numpy as np
|
24
27
|
|
25
|
-
from ..cells
|
28
|
+
from ..cells import BaseCell
|
26
29
|
from ..utils.decorators import cache
|
27
|
-
from .track_gen import Track_generator
|
30
|
+
from .track_gen import Track_generator
|
28
31
|
|
29
32
|
|
30
33
|
def create_condensate_dict(
|
@@ -32,7 +35,7 @@ def create_condensate_dict(
|
|
32
35
|
initial_scale: np.ndarray,
|
33
36
|
diffusion_coefficient: np.ndarray,
|
34
37
|
hurst_exponent: np.ndarray,
|
35
|
-
cell:
|
38
|
+
cell: BaseCell,
|
36
39
|
**kwargs,
|
37
40
|
) -> dict:
|
38
41
|
"""
|
@@ -48,11 +51,14 @@ def create_condensate_dict(
|
|
48
51
|
Array of shape (num_condensates, 2) representing the diffusion coefficients of the condensates.
|
49
52
|
hurst_exponent : np.ndarray
|
50
53
|
Array of shape (num_condensates, 2) representing the Hurst exponents of the condensates.
|
51
|
-
cell :
|
52
|
-
The
|
54
|
+
cell : BaseCell
|
55
|
+
The cell that contains the condensates.
|
53
56
|
**kwargs : dict
|
54
57
|
Additional arguments passed to `Condensate` class.
|
55
58
|
|
59
|
+
oversample_motion_time : int
|
60
|
+
smallest time unit for motion (time resolution for motion) (ms)
|
61
|
+
|
56
62
|
Returns:
|
57
63
|
--------
|
58
64
|
dict
|
@@ -99,8 +105,10 @@ class Condensate:
|
|
99
105
|
ID of the condensate.
|
100
106
|
initial_scale: float = 0
|
101
107
|
Initial scale of the condensate.
|
102
|
-
cell:
|
103
|
-
The
|
108
|
+
cell: BaseCell = None
|
109
|
+
The cell that contains the condensates.
|
110
|
+
oversample_motion_time: int = None
|
111
|
+
motion resolution
|
104
112
|
|
105
113
|
"""
|
106
114
|
|
@@ -114,7 +122,8 @@ class Condensate:
|
|
114
122
|
units_position: str = "um",
|
115
123
|
condensate_id: int = 0,
|
116
124
|
initial_scale: float = 0,
|
117
|
-
cell:
|
125
|
+
cell: Optional[BaseCell] = None,
|
126
|
+
oversample_motion_time: Optional[int] = None,
|
118
127
|
):
|
119
128
|
self.initial_position = (
|
120
129
|
np.array(initial_position)
|
@@ -138,13 +147,11 @@ class Condensate:
|
|
138
147
|
self.units_position = units_position
|
139
148
|
self.condensate_id = condensate_id
|
140
149
|
self.initial_scale = initial_scale
|
141
|
-
|
142
|
-
cell = RectangularCell(
|
143
|
-
origin=np.array([0, 0]), dimensions=np.array([0, 0, 0])
|
144
|
-
)
|
150
|
+
|
145
151
|
self.cell = cell
|
146
152
|
self.dim = self.initial_position.shape[0]
|
147
153
|
|
154
|
+
self.oversample_motion_time = oversample_motion_time
|
148
155
|
# initialize the properties of the condensate
|
149
156
|
self._initialize_properties()
|
150
157
|
|
@@ -261,28 +268,20 @@ class Condensate:
|
|
261
268
|
# find the time difference
|
262
269
|
time_difference = time - self.times[-1]
|
263
270
|
# make a time array starting from the last time +1 and goin to the time inclusive
|
264
|
-
time_array = np.arange(
|
265
|
-
|
266
|
-
|
267
|
-
cell_space = np.array(
|
268
|
-
[
|
269
|
-
[min_bound[0], max_bound[0]], # x bounds
|
270
|
-
[min_bound[1], max_bound[1]], # y bounds
|
271
|
-
]
|
271
|
+
time_array = np.arange(
|
272
|
+
self.times[-1] + self.oversample_motion_time,
|
273
|
+
time + self.oversample_motion_time,
|
272
274
|
)
|
273
|
-
|
274
|
-
track_generator =
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
exposure_time=20,
|
279
|
-
interval_time=0,
|
280
|
-
oversample_motion_time=20,
|
275
|
+
|
276
|
+
track_generator = Track_generator(
|
277
|
+
cell=self.cell,
|
278
|
+
total_time=time,
|
279
|
+
oversample_motion_time=self.oversample_motion_time,
|
281
280
|
)
|
282
281
|
track = track_generator.track_generation_no_transition(
|
283
282
|
diffusion_coefficient=self.diffusion_coefficient,
|
284
283
|
hurst_exponent=self.hurst_exponent,
|
285
|
-
track_length=time_difference,
|
284
|
+
track_length=int(time_difference / self.oversample_motion_time),
|
286
285
|
initials=self.condensate_positions[-1],
|
287
286
|
start_time=self.times[-1],
|
288
287
|
)
|
@@ -1,10 +1,5 @@
|
|
1
|
-
from
|
2
|
-
from .boundary_conditions import _refecting_boundary, _absorbing_boundary
|
3
|
-
from ...probabilityfuncs.markov_chain import MCMC_state_selection
|
1
|
+
from boundedfbm import FBM_BP
|
4
2
|
|
5
3
|
__all__ = [
|
6
4
|
"FBM_BP",
|
7
|
-
"_refecting_boundary",
|
8
|
-
"_absorbing_boundary",
|
9
|
-
"MCMC_state_selection",
|
10
5
|
]
|
@@ -1,11 +1,19 @@
|
|
1
|
+
"""
|
2
|
+
Deprecated module due to switching to the Pyvista model for 3D cell shapes.
|
3
|
+
Removal Time: NDY (not determined yet)
|
4
|
+
"""
|
5
|
+
|
1
6
|
import numpy as np
|
2
7
|
|
3
|
-
from ...utils.decorators import _catch_recursion_error
|
8
|
+
from ...utils.decorators import _catch_recursion_error, deprecated
|
4
9
|
|
5
10
|
# Reflecting boundary condition which is a recursive function so that even if the first candidate
|
6
11
|
# is out of the space limit, the function will keep calling itself until the candidate is within the space limit
|
7
12
|
|
8
13
|
|
14
|
+
@deprecated(
|
15
|
+
reason="Not used explicitly due to the use of Pyvista mesh objects to define shapes."
|
16
|
+
)
|
9
17
|
@_catch_recursion_error
|
10
18
|
def _refecting_boundary(
|
11
19
|
fbm_store_last: float, fbm_candidate: float, space_lim: np.ndarray
|
@@ -47,6 +55,9 @@ def _refecting_boundary(
|
|
47
55
|
# Boundary condition where the step is set at the boundary limit if the candidate is out of the space limit
|
48
56
|
|
49
57
|
|
58
|
+
@deprecated(
|
59
|
+
reason="Not used explicitly due to the use of Pyvista mesh objects to define shapes."
|
60
|
+
)
|
50
61
|
@_catch_recursion_error
|
51
62
|
def _absorbing_boundary(
|
52
63
|
fbm_store_last: float, fbm_candidate: float, space_lim: np.ndarray
|
AMS_BP/motion/track_gen.py
CHANGED
@@ -11,16 +11,12 @@ Classes:
|
|
11
11
|
"""
|
12
12
|
|
13
13
|
import random
|
14
|
-
from typing import
|
14
|
+
from typing import overload
|
15
15
|
|
16
16
|
import numpy as np
|
17
|
+
from boundedfbm.motion.FBM import FBM_BP
|
17
18
|
|
18
|
-
from ..cells
|
19
|
-
from ..cells.rod_cell import RodCell
|
20
|
-
from ..cells.spherical_cell import SphericalCell
|
21
|
-
from .movement.fbm_BP import FBM_BP
|
22
|
-
|
23
|
-
CellType = Union[SphericalCell, RodCell, RectangularCell]
|
19
|
+
from ..cells import BaseCell
|
24
20
|
|
25
21
|
|
26
22
|
class Track_generator:
|
@@ -29,60 +25,33 @@ class Track_generator:
|
|
29
25
|
|
30
26
|
Parameters:
|
31
27
|
-----------
|
32
|
-
cell :
|
28
|
+
cell : BaseCell
|
33
29
|
Cell object defining the space for track generation
|
34
|
-
cycle_count : int
|
35
|
-
The number of frames for the simulation.
|
36
|
-
exposure_time : int | float
|
37
|
-
Exposure time in milliseconds.
|
38
|
-
interval_time : int | float
|
39
|
-
Interval time between frames in milliseconds.
|
40
30
|
oversample_motion_time : int | float
|
41
31
|
Time for oversampling motion in milliseconds.
|
42
32
|
"""
|
43
33
|
|
44
34
|
def __init__(
|
45
35
|
self,
|
46
|
-
cell:
|
47
|
-
|
48
|
-
exposure_time: int | float,
|
49
|
-
interval_time: int | float,
|
36
|
+
cell: BaseCell,
|
37
|
+
total_time: int | float,
|
50
38
|
oversample_motion_time: int | float,
|
51
39
|
) -> None:
|
52
40
|
self.cell = cell
|
53
41
|
self._allowable_cell_types()
|
54
|
-
min_point, max_point = self.cell.get_bounds()
|
55
|
-
|
56
|
-
# Extract space limits from cell bounds
|
57
|
-
self.min_x = min_point[0]
|
58
|
-
self.max_x = max_point[0]
|
59
|
-
self.min_y = min_point[1]
|
60
|
-
self.max_y = max_point[1]
|
61
|
-
self.min_z = min_point[2]
|
62
|
-
self.max_z = max_point[2]
|
63
|
-
|
64
|
-
self.space_lim = np.array(
|
65
|
-
[
|
66
|
-
[self.min_x, self.max_x],
|
67
|
-
[self.min_y, self.max_y],
|
68
|
-
[self.min_z, self.max_z],
|
69
|
-
]
|
70
|
-
)
|
71
42
|
|
72
|
-
self.cycle_count = cycle_count # count of frames
|
73
|
-
self.exposure_time = exposure_time # in ms
|
74
|
-
self.interval_time = interval_time # in ms
|
75
43
|
self.oversample_motion_time = oversample_motion_time # in ms
|
76
44
|
# total time in ms is the exposure time + interval time * (cycle_count) / oversample_motion_time
|
77
45
|
# in ms
|
78
|
-
self.total_time =
|
46
|
+
self.total_time = total_time
|
79
47
|
|
80
48
|
def _allowable_cell_types(self):
|
81
49
|
# only allow rectangular cells for now
|
82
|
-
if not isinstance(self.cell, RectangularCell):
|
83
|
-
|
84
|
-
|
85
|
-
|
50
|
+
# if not isinstance(self.cell, RectangularCell):
|
51
|
+
# raise ValueError(
|
52
|
+
# "Only rectangular cells are supported for track generation"
|
53
|
+
# )
|
54
|
+
pass
|
86
55
|
|
87
56
|
def track_generation_no_transition(
|
88
57
|
self,
|
@@ -118,42 +87,30 @@ class Track_generator:
|
|
118
87
|
if np.shape(initials) == (2,):
|
119
88
|
# change the shape to (3,)
|
120
89
|
initials = np.array([initials[0], initials[1], 0])
|
121
|
-
# subtract each element of the first dimension of self.space_lim by the first element of initials
|
122
|
-
rel_space_lim = np.zeros((3, 2))
|
123
|
-
for i in range(3):
|
124
|
-
rel_space_lim[i] = self.space_lim[i] - initials[i]
|
125
|
-
|
126
90
|
# convert the diffusion_coefficients
|
127
|
-
diffusion_coefficient = self._convert_diffcoef_um2s_um2xms(
|
128
|
-
|
129
|
-
)
|
91
|
+
# diffusion_coefficient = self._convert_diffcoef_um2s_um2xms(
|
92
|
+
# diffusion_coefficient
|
93
|
+
# )
|
130
94
|
fbm = FBM_BP(
|
131
95
|
n=track_length,
|
132
|
-
dt=
|
96
|
+
dt=self.oversample_motion_time / 1000.0,
|
133
97
|
hurst_parameters=[hurst_exponent],
|
134
98
|
diffusion_parameters=[diffusion_coefficient],
|
135
99
|
diffusion_parameter_transition_matrix=[1],
|
136
100
|
hurst_parameter_transition_matrix=[1],
|
137
101
|
state_probability_diffusion=[1],
|
138
102
|
state_probability_hurst=[1],
|
139
|
-
|
103
|
+
cell=self.cell,
|
104
|
+
initial_position=initials,
|
140
105
|
)
|
141
|
-
|
142
|
-
# repeat for y,z
|
143
|
-
fbm.space_lim = rel_space_lim[1]
|
144
|
-
y = fbm.fbm()
|
145
|
-
fbm.space_lim = rel_space_lim[2]
|
146
|
-
z = fbm.fbm()
|
147
|
-
# convert to format [[x1,y1,z1],[x2,y2,z2],...]
|
148
|
-
xyz = np.stack((x, y, z), axis=-1)
|
106
|
+
xyz = fbm.fbm(dims=3)
|
149
107
|
# make the times starting from the starting time
|
150
108
|
track_times = np.arange(
|
151
109
|
start_time,
|
152
110
|
(track_length) * self.oversample_motion_time,
|
153
111
|
self.oversample_motion_time,
|
154
112
|
)
|
155
|
-
|
156
|
-
track_xyz = xyz + initials
|
113
|
+
track_xyz = xyz
|
157
114
|
# create the dict
|
158
115
|
track_data = {
|
159
116
|
"xy": track_xyz,
|
@@ -212,39 +169,30 @@ class Track_generator:
|
|
212
169
|
# change the shape to (3,)
|
213
170
|
initials = np.array([initials[0], initials[1], 0])
|
214
171
|
# subtract each element of the first dimension of self.space_lim by the first element of initials
|
215
|
-
|
216
|
-
for i in range(3):
|
217
|
-
rel_space_lim[i] = self.space_lim[i] - initials[i]
|
172
|
+
|
218
173
|
# convert the diffusion_coefficients
|
219
|
-
diffusion_parameters = self._convert_diffcoef_um2s_um2xms(diffusion_parameters)
|
174
|
+
# diffusion_parameters = self._convert_diffcoef_um2s_um2xms(diffusion_parameters)
|
220
175
|
# initialize the fbm class
|
221
176
|
fbm = FBM_BP(
|
222
177
|
n=track_length,
|
223
|
-
dt=
|
178
|
+
dt=self.oversample_motion_time / 1000.0,
|
224
179
|
hurst_parameters=hurst_parameters,
|
225
180
|
diffusion_parameters=diffusion_parameters,
|
226
181
|
diffusion_parameter_transition_matrix=diffusion_transition_matrix,
|
227
182
|
hurst_parameter_transition_matrix=hurst_transition_matrix,
|
228
183
|
state_probability_diffusion=diffusion_state_probability,
|
229
184
|
state_probability_hurst=hurst_state_probability,
|
230
|
-
|
185
|
+
cell=self.cell,
|
186
|
+
initial_position=initials,
|
231
187
|
)
|
232
|
-
|
233
|
-
# repeat for y,z
|
234
|
-
fbm.space_lim = rel_space_lim[1]
|
235
|
-
y = fbm.fbm()
|
236
|
-
fbm.space_lim = rel_space_lim[2]
|
237
|
-
z = fbm.fbm()
|
238
|
-
# convert to format [[x1,y1,z1],[x2,y2,z2],...]
|
239
|
-
xyz = np.stack((x, y, z), axis=-1)
|
188
|
+
xyz = fbm.fbm(dims=3)
|
240
189
|
# make the times starting from the starting time
|
241
190
|
track_times = np.arange(
|
242
191
|
start_time,
|
243
192
|
track_length * self.oversample_motion_time,
|
244
193
|
self.oversample_motion_time,
|
245
194
|
)
|
246
|
-
|
247
|
-
track_xyz = xyz + initials
|
195
|
+
track_xyz = xyz
|
248
196
|
# create the dict
|
249
197
|
track_data = {
|
250
198
|
"xy": track_xyz,
|
@@ -321,7 +269,9 @@ class Track_generator:
|
|
321
269
|
else:
|
322
270
|
raise TypeError(f"Unsupported type: {type(diffusion_coefficient)}")
|
323
271
|
|
324
|
-
def _convert_time_to_frame(
|
272
|
+
def _convert_time_to_frame(
|
273
|
+
self, time: int, exposure_time: int, interval_time: int
|
274
|
+
) -> int:
|
325
275
|
"""
|
326
276
|
Parameters:
|
327
277
|
-----------
|
@@ -333,11 +283,12 @@ class Track_generator:
|
|
333
283
|
int: frame number
|
334
284
|
"""
|
335
285
|
return int(
|
336
|
-
(time * self.oversample_motion_time)
|
337
|
-
/ (self.exposure_time + self.interval_time)
|
286
|
+
(time * self.oversample_motion_time) / (exposure_time + interval_time)
|
338
287
|
)
|
339
288
|
|
340
|
-
def _convert_frame_to_time(
|
289
|
+
def _convert_frame_to_time(
|
290
|
+
self, frame: int, exposure_time: int, interval_time: int
|
291
|
+
) -> int:
|
341
292
|
"""
|
342
293
|
Parameters:
|
343
294
|
-----------
|
@@ -348,7 +299,7 @@ class Track_generator:
|
|
348
299
|
--------
|
349
300
|
int: time in ms
|
350
301
|
"""
|
351
|
-
return int((frame * (
|
302
|
+
return int((frame * (exposure_time + interval_time)))
|
352
303
|
|
353
304
|
|
354
305
|
def _initialize_points_per_time(total_time: int, oversample_motion_time: int) -> dict:
|