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 CHANGED
@@ -10,4 +10,4 @@ Last updated: 2024-12-16
10
10
 
11
11
  """
12
12
 
13
- __version__ = "0.0.231"
13
+ __version__ = "0.2.0"
AMS_BP/cells/__init__.py CHANGED
@@ -1,5 +1,31 @@
1
- from .spherical_cell import SphericalCell
2
- from .rectangular_cell import RectangularCell
3
- from .rod_cell import RodCell
1
+ from boundedfbm.cells.base_cell import BaseCell
2
+ from boundedfbm.cells.ovoid_cell import OvoidCell, make_OvoidCell
3
+ from boundedfbm.cells.rectangular_cell import RectangularCell, make_RectangularCell
4
+ from boundedfbm.cells.rod_cell import RodCell, make_RodCell
5
+ from boundedfbm.cells.spherical_cell import SphericalCell, make_SphericalCell
6
+ from boundedfbm.cells.typedefs import Vector3D
4
7
 
5
- __all__ = ["SphericalCell", "RectangularCell", "RodCell"]
8
+ from .budding_yeast_cell import BuddingCell, make_BuddingCell
9
+ from .cell_factory import (
10
+ CellType,
11
+ create_cell,
12
+ validate_cell_parameters,
13
+ )
14
+
15
+ __all__ = [
16
+ "SphericalCell",
17
+ "RectangularCell",
18
+ "RodCell",
19
+ "OvoidCell",
20
+ "BuddingCell",
21
+ "make_SphericalCell",
22
+ "make_RodCell",
23
+ "make_RectangularCell",
24
+ "make_BuddingCell",
25
+ "make_OvoidCell",
26
+ "create_cell",
27
+ "CellType",
28
+ "validate_cell_parameters",
29
+ "BaseCell",
30
+ "Vector3D",
31
+ ]
@@ -0,0 +1,274 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Tuple
3
+
4
+ import numpy as np
5
+ import pyvista as pv
6
+ from boundedfbm.cells.base_cell import BaseCell
7
+ from boundedfbm.cells.typedefs import Vector3D
8
+
9
+
10
+ @dataclass
11
+ class BuddingCell(BaseCell):
12
+ """
13
+ Represents a budding yeast cell composed of two connected ovoids (mother and bud).
14
+ The cells are connected at a "neck" region, with the bud growing from the mother cell.
15
+
16
+ Attributes:
17
+ center (np.ndarray): The (x, y, z) coordinates of the mother cell's center in XYZ plane
18
+ mother_radius_x (float): Mother cell radius along X axis
19
+ mother_radius_y (float): Mother cell radius along Y axis
20
+ mother_radius_z (float): Mother cell radius along Z axis
21
+ bud_radius_x (float): Bud radius along X axis
22
+ bud_radius_y (float): Bud radius along Y axis
23
+ bud_radius_z (float): Bud radius along Z axis
24
+ bud_angle (float): Angle in radians from x-axis where bud emerges
25
+ bud_distance (float): Distance between mother and bud centers
26
+ neck_radius (float): Radius of the connecting neck region
27
+ """
28
+
29
+ center: np.ndarray | List[float] | Tuple
30
+ mother_radius_x: float
31
+ mother_radius_y: float
32
+ mother_radius_z: float
33
+ bud_radius_x: float
34
+ bud_radius_y: float
35
+ bud_radius_z: float
36
+ bud_angle: float
37
+ bud_distance: float
38
+ neck_radius: float
39
+
40
+ def is_point_inside(
41
+ self, x: float, y: float, z: float, tolerance: float = 1e-3
42
+ ) -> bool:
43
+ """
44
+ Determines if a given point is inside the BuddingCell.
45
+ A point is inside if it's within the mother cell, the bud, or the neck region.
46
+
47
+ Args:
48
+ point (np.ndarray | List[float] | Tuple): The (x, y, z) coordinates of the point to check
49
+
50
+ Returns:
51
+ bool: True if the point is inside the cell, False otherwise
52
+ """
53
+ # Ensure point is a numpy array for vector operations
54
+ point = np.array([x, y, z])
55
+ mother_center = np.array(self.center)
56
+
57
+ # Calculate bud center based on angle and distance
58
+ bud_x = mother_center[0] + self.bud_distance * np.cos(self.bud_angle)
59
+ bud_y = mother_center[1] + self.bud_distance * np.sin(self.bud_angle)
60
+ bud_center = np.array([bud_x, bud_y, mother_center[2]])
61
+
62
+ # Check if point is inside the mother cell (scaled ellipsoid)
63
+ x, y, z = point - mother_center
64
+ mother_distance_squared = (
65
+ (x / self.mother_radius_x) ** 2
66
+ + (y / self.mother_radius_y) ** 2
67
+ + (z / self.mother_radius_z) ** 2
68
+ )
69
+ if mother_distance_squared <= 1:
70
+ return True
71
+
72
+ # Check if point is inside the bud (scaled ellipsoid)
73
+ x, y, z = point - bud_center
74
+ bud_distance_squared = (
75
+ (x / self.bud_radius_x) ** 2
76
+ + (y / self.bud_radius_y) ** 2
77
+ + (z / self.bud_radius_z) ** 2
78
+ )
79
+ if bud_distance_squared <= 1:
80
+ return True
81
+
82
+ # Check if point is inside the neck region
83
+ # First, project the point onto the line between mother and bud centers
84
+ mother_to_bud_vec = bud_center - mother_center
85
+ mother_to_bud_length = np.linalg.norm(mother_to_bud_vec)
86
+ mother_to_bud_unit = mother_to_bud_vec / mother_to_bud_length
87
+
88
+ mother_to_point_vec = point - mother_center
89
+ projection_length = np.dot(mother_to_point_vec, mother_to_bud_unit)
90
+
91
+ # Calculate minimum distance from point to the center line
92
+ if 0 <= projection_length <= mother_to_bud_length:
93
+ projection_point = mother_center + projection_length * mother_to_bud_unit
94
+ distance_to_line = np.linalg.norm(point - projection_point)
95
+
96
+ # The neck is modeled as a truncated cone
97
+ # Interpolate the radius at this point along the neck
98
+ if projection_length <= self.mother_radius_x:
99
+ # Within mother cell radius from the center
100
+ local_radius = self.neck_radius
101
+ elif projection_length >= mother_to_bud_length - self.bud_radius_x:
102
+ # Within bud cell radius from the bud center
103
+ local_radius = self.neck_radius
104
+ else:
105
+ local_radius = self.neck_radius
106
+
107
+ return distance_to_line <= local_radius
108
+
109
+ return False
110
+
111
+
112
+ def make_BuddingCell(
113
+ center: np.ndarray | List[float] | Tuple,
114
+ mother_radius_x: float,
115
+ mother_radius_y: float,
116
+ mother_radius_z: float,
117
+ bud_radius_x: float,
118
+ bud_radius_y: float,
119
+ bud_radius_z: float,
120
+ bud_angle: float,
121
+ bud_distance: float,
122
+ neck_radius: float,
123
+ ) -> BuddingCell:
124
+ """
125
+ Create a budding yeast cell using PyVista meshes.
126
+
127
+ Args:
128
+ center: Center point of the mother cell
129
+ mother_radius_x/y/z: Radii of the mother cell along each axis
130
+ bud_radius_x/y/z: Radii of the bud cell along each axis
131
+ bud_angle: Angle in radians from x-axis where bud emerges
132
+ bud_distance: Distance between mother and bud centers
133
+ neck_radius: Radius of the connecting neck region
134
+
135
+ Returns:
136
+ BuddingCell: Instance with PyVista mesh
137
+ """
138
+ # Validate inputs
139
+ center = np.array(center)
140
+ if center.shape != (3,):
141
+ raise ValueError("Center must be a 3D point")
142
+
143
+ # Calculate bud center
144
+ bud_center = np.array(
145
+ [
146
+ center[0] + bud_distance * np.cos(bud_angle),
147
+ center[1] + bud_distance * np.sin(bud_angle),
148
+ center[2],
149
+ ]
150
+ )
151
+
152
+ # Create mother cell ellipsoid
153
+ mother = pv.ParametricEllipsoid(
154
+ xradius=mother_radius_x,
155
+ yradius=mother_radius_y,
156
+ zradius=mother_radius_z,
157
+ center=center,
158
+ )
159
+
160
+ # Create bud cell ellipsoid
161
+ bud = pv.ParametricEllipsoid(
162
+ xradius=bud_radius_x,
163
+ yradius=bud_radius_y,
164
+ zradius=bud_radius_z,
165
+ center=bud_center,
166
+ )
167
+
168
+ # Create neck region (cylinder)
169
+ # Calculate direction vector from mother to bud
170
+ direction = bud_center - center
171
+ direction = direction / np.linalg.norm(direction)
172
+
173
+ # Create cylinder for neck
174
+ cylinder = pv.Cylinder(
175
+ center=(center + bud_center) / 2, # Midpoint
176
+ direction=direction,
177
+ radius=neck_radius,
178
+ height=bud_distance,
179
+ )
180
+
181
+ # Combine shapes using boolean operations
182
+ # First combine mother and neck
183
+ mother_and_neck = mother.boolean_union(cylinder)
184
+
185
+ # Then add the bud
186
+ complete_cell = mother_and_neck.boolean_union(bud)
187
+
188
+ # Clean up the mesh
189
+ complete_cell = complete_cell.clean()
190
+ complete_cell = complete_cell.fill_holes(1)
191
+
192
+ # Verify mesh integrity
193
+ edges = complete_cell.extract_feature_edges(
194
+ feature_edges=False, manifold_edges=False
195
+ )
196
+ assert edges.n_cells == 0, "Mesh has non-manifold edges"
197
+
198
+ return BuddingCell(
199
+ mesh=complete_cell,
200
+ center=center,
201
+ mother_radius_x=mother_radius_x,
202
+ mother_radius_y=mother_radius_y,
203
+ mother_radius_z=mother_radius_z,
204
+ bud_radius_x=bud_radius_x,
205
+ bud_radius_y=bud_radius_y,
206
+ bud_radius_z=bud_radius_z,
207
+ bud_angle=bud_angle,
208
+ bud_distance=bud_distance,
209
+ neck_radius=neck_radius,
210
+ )
211
+
212
+
213
+ @dataclass
214
+ class BuddingCellParams:
215
+ center: Vector3D
216
+ mother_radius_x: float
217
+ mother_radius_y: float
218
+ mother_radius_z: float
219
+ bud_radius_x: float
220
+ bud_radius_y: float
221
+ bud_radius_z: float
222
+ bud_angle: float
223
+ bud_distance: float
224
+ neck_radius: float
225
+
226
+ @classmethod
227
+ def validate_center(cls, value):
228
+ if not isinstance(value, (list, tuple, np.ndarray)) or len(value) != 3:
229
+ raise ValueError("center must be a 3D vector")
230
+
231
+ @classmethod
232
+ def validate_mother_radius_x(cls, value):
233
+ if not isinstance(value, (int, float)) or value <= 0:
234
+ raise ValueError("mother_radius_x must be a positive number")
235
+
236
+ @classmethod
237
+ def validate_mother_radius_y(cls, value):
238
+ if not isinstance(value, (int, float)) or value <= 0:
239
+ raise ValueError("mother_radius_y must be a positive number")
240
+
241
+ @classmethod
242
+ def validate_mother_radius_z(cls, value):
243
+ if not isinstance(value, (int, float)) or value <= 0:
244
+ raise ValueError("mother_radius_z must be a positive number")
245
+
246
+ @classmethod
247
+ def validate_bud_radius_x(cls, value):
248
+ if not isinstance(value, (int, float)) or value <= 0:
249
+ raise ValueError("bud_radius_x must be a positive number")
250
+
251
+ @classmethod
252
+ def validate_bud_radius_y(cls, value):
253
+ if not isinstance(value, (int, float)) or value <= 0:
254
+ raise ValueError("bud_radius_y must be a positive number")
255
+
256
+ @classmethod
257
+ def validate_bud_radius_z(cls, value):
258
+ if not isinstance(value, (int, float)) or value <= 0:
259
+ raise ValueError("bud_radius_z must be a positive number")
260
+
261
+ @classmethod
262
+ def validate_bud_angle(cls, value):
263
+ if not isinstance(value, (int, float)):
264
+ raise ValueError("bud_angle must be a number")
265
+
266
+ @classmethod
267
+ def validate_bud_distance(cls, value):
268
+ if not isinstance(value, (int, float)) or value <= 0:
269
+ raise ValueError("bud_distance must be a positive number")
270
+
271
+ @classmethod
272
+ def validate_neck_radius(cls, value):
273
+ if not isinstance(value, (int, float)) or value <= 0:
274
+ raise ValueError("neck_radius must be a positive number")
@@ -0,0 +1,148 @@
1
+ import inspect
2
+ from enum import Enum
3
+ from typing import Any, Callable, Dict, List, Tuple, Union
4
+
5
+ from boundedfbm.cells.base_cell import BaseCell
6
+
7
+ # Import cell creation functions and parameter classes
8
+ from boundedfbm.cells.ovoid_cell import OvoidCellParams, make_OvoidCell
9
+ from boundedfbm.cells.rectangular_cell import (
10
+ RectangularCellParams,
11
+ make_RectangularCell,
12
+ )
13
+ from boundedfbm.cells.rod_cell import RodCellParams, make_RodCell
14
+ from boundedfbm.cells.spherical_cell import SphericalCellParams, make_SphericalCell
15
+
16
+ from .budding_yeast_cell import BuddingCellParams, make_BuddingCell
17
+
18
+
19
+ # ===== Exposed Enum =====
20
+ class CellType(str, Enum):
21
+ SPHERICAL = "SphericalCell"
22
+ ROD = "RodCell"
23
+ RECTANGULAR = "RectangularCell"
24
+ OVOID = "OvoidCell"
25
+ BUDDINGYEAST = "BuddingCell"
26
+
27
+
28
+ # ===== Internal Mappings =====
29
+ _CELL_PARAM_CLASSES: Dict[CellType, Any] = {
30
+ CellType.SPHERICAL: SphericalCellParams,
31
+ CellType.ROD: RodCellParams,
32
+ CellType.RECTANGULAR: RectangularCellParams,
33
+ CellType.OVOID: OvoidCellParams,
34
+ CellType.BUDDINGYEAST: BuddingCellParams,
35
+ }
36
+
37
+ _CELL_CREATION_MAP: Dict[CellType, Tuple[Callable, List[str]]] = {
38
+ CellType.SPHERICAL: (make_SphericalCell, ["center", "radius"]),
39
+ CellType.ROD: (make_RodCell, ["center", "direction", "height", "radius"]),
40
+ CellType.RECTANGULAR: (make_RectangularCell, ["bounds"]),
41
+ CellType.OVOID: (
42
+ make_OvoidCell,
43
+ ["center", "direction", "xradius", "yradius", "zradius"],
44
+ ),
45
+ CellType.BUDDINGYEAST: (
46
+ make_BuddingCell,
47
+ [
48
+ "center",
49
+ "mother_radius_x",
50
+ "mother_radius_y",
51
+ "mother_radius_z",
52
+ "bud_radius_x",
53
+ "bud_radius_y",
54
+ "bud_radius_z",
55
+ "bud_angle",
56
+ "bud_distance",
57
+ "neck_radius",
58
+ ],
59
+ ),
60
+ }
61
+
62
+
63
+ # ===== Internal Validator =====
64
+ def _validate_parameters(
65
+ cell_type: CellType, params: Dict[str, Any]
66
+ ) -> Tuple[bool, List[str]]:
67
+ """Internal function to validate cell parameters against the expected schema."""
68
+ param_class = _CELL_PARAM_CLASSES[cell_type]
69
+
70
+ # Validate against expected parameters
71
+ expected_params = {
72
+ name for name in inspect.signature(param_class).parameters if name != "self"
73
+ }
74
+ unexpected = set(params.keys()) - expected_params
75
+ missing = expected_params - set(params.keys())
76
+
77
+ errors = []
78
+ if unexpected:
79
+ errors.append(f"Unexpected parameter(s): {', '.join(unexpected)}")
80
+ if missing:
81
+ errors.append(f"Missing parameter(s): {', '.join(missing)}")
82
+
83
+ if errors:
84
+ return False, errors
85
+
86
+ try:
87
+ param_class(**params)
88
+ return True, []
89
+ except ValueError as e:
90
+ return False, str(e).split("\n")
91
+
92
+
93
+ # ===== Exposed Validation Function =====
94
+ def validate_cell_parameters(
95
+ cell_type: Union[str, CellType], params: Dict[str, Any]
96
+ ) -> Tuple[bool, List[str]]:
97
+ """
98
+ Validate parameters for a given cell type.
99
+
100
+ Args:
101
+ cell_type: The cell type (string or enum)
102
+ params: Dictionary of parameters
103
+
104
+ Returns:
105
+ Tuple of (is_valid, error_messages)
106
+ """
107
+ if isinstance(cell_type, str):
108
+ try:
109
+ cell_type = CellType(cell_type)
110
+ except ValueError:
111
+ return False, [f"Unknown cell type: {cell_type}"]
112
+
113
+ if cell_type not in _CELL_PARAM_CLASSES:
114
+ return False, [f"Unknown cell type: {cell_type}"]
115
+
116
+ return _validate_parameters(cell_type, params)
117
+
118
+
119
+ # ===== Exposed Factory Function =====
120
+ def create_cell(cell_type: Union[str, CellType], params: Dict[str, Any]) -> BaseCell:
121
+ """
122
+ Create a validated cell instance.
123
+
124
+ Args:
125
+ cell_type: Cell type (string or enum)
126
+ params: Dictionary of cell parameters.
127
+
128
+ Returns:
129
+ BaseCell instance.
130
+
131
+ Raises:
132
+ ValueError: If validation fails.
133
+ """
134
+ if isinstance(cell_type, str):
135
+ try:
136
+ cell_type = CellType(cell_type)
137
+ except ValueError:
138
+ raise ValueError(f"Unknown cell type: {cell_type}")
139
+
140
+ if cell_type not in _CELL_CREATION_MAP:
141
+ raise ValueError(f"Unknown cell type: {cell_type}")
142
+
143
+ is_valid, errors = validate_cell_parameters(cell_type, params)
144
+ if not is_valid:
145
+ raise ValueError(f"Invalid {cell_type} configuration: {'; '.join(errors)}")
146
+
147
+ func, param_keys = _CELL_CREATION_MAP[cell_type]
148
+ return func(**{key: params[key] for key in param_keys})
@@ -1,16 +1,19 @@
1
- from typing import List, Literal
1
+ from typing import Any, Dict, List, Literal, Union
2
2
 
3
3
  import numpy as np
4
4
  from pydantic import BaseModel, Field, field_validator
5
5
 
6
+ from ..cells import CellType, validate_cell_parameters
7
+
6
8
 
7
9
  class CellParameters(BaseModel):
8
- cell_space: List[List[float]] = Field(description="Cell space dimensions in um")
9
- cell_axial_radius: float = Field(description="Axial radius in um")
10
+ cell_type: Union[str, CellType]
11
+ params: Dict[str, Any]
10
12
 
11
- @field_validator("cell_space")
12
- def convert_cell_space(cls, v):
13
- return np.array(v)
13
+ def model_post_init(self, __context):
14
+ is_valid = validate_cell_parameters(self.cell_type, self.params)
15
+ if not is_valid:
16
+ raise ValueError(f"Cell model creation unsuccessful: {is_valid[1]}")
14
17
 
15
18
 
16
19
  class MoleculeParameters(BaseModel):
@@ -5,8 +5,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
5
5
  import tomli
6
6
  from pydantic import BaseModel
7
7
 
8
- from ..cells import RectangularCell
9
- from ..cells.base_cell import BaseCell
8
+ from ..cells import BaseCell, create_cell
10
9
  from ..motion import Track_generator, create_condensate_dict
11
10
  from ..motion.track_gen import (
12
11
  _convert_tracks_to_trajectory,
@@ -672,7 +671,7 @@ class ConfigLoader:
672
671
  # make initial sample plane
673
672
  sample_plane = make_sample(
674
673
  global_params=base_config.GlobalParameters,
675
- cell_params=base_config.CellParameters,
674
+ cell=cell,
676
675
  )
677
676
 
678
677
  # make condensates_dict
@@ -739,23 +738,19 @@ class ConfigLoader:
739
738
 
740
739
  def make_cell(cell_params) -> BaseCell:
741
740
  # make cell
742
- cell_origin = (cell_params.cell_space[0][0], cell_params.cell_space[1][0])
743
- cell_dimensions = (
744
- cell_params.cell_space[0][1] - cell_params.cell_space[0][0],
745
- cell_params.cell_space[1][1] - cell_params.cell_space[1][0],
746
- cell_params.cell_axial_radius * 2,
747
- )
748
- cell = RectangularCell(origin=cell_origin, dimensions=cell_dimensions)
741
+
742
+ cell = create_cell(cell_params.cell_type, cell_params.params)
749
743
 
750
744
  return cell
751
745
 
752
746
 
753
- def make_sample(global_params, cell_params) -> SamplePlane:
747
+ def make_sample(global_params: GlobalParameters, cell: BaseCell) -> SamplePlane:
748
+ bounds = cell.boundingbox
754
749
  sample_space = SampleSpace(
755
750
  x_max=global_params.sample_plane_dim[0],
756
751
  y_max=global_params.sample_plane_dim[1],
757
- z_max=cell_params.cell_axial_radius,
758
- z_min=-cell_params.cell_axial_radius,
752
+ z_max=bounds[-1],
753
+ z_min=bounds[-2],
759
754
  )
760
755
 
761
756
  # total time
@@ -769,15 +764,17 @@ def make_sample(global_params, cell_params) -> SamplePlane:
769
764
  fov=(
770
765
  (0, global_params.sample_plane_dim[0]),
771
766
  (0, global_params.sample_plane_dim[1]),
772
- (-cell_params.cell_axial_radius, cell_params.cell_axial_radius),
773
- ),
767
+ (bounds[-2], bounds[-1]),
768
+ ), # simulates the whole simulation space to avoid the issue of PSF bleeding into FOV if the molecule's location is technically outside of the FOV dictated by the camera detector size and objective magnification.
774
769
  oversample_motion_time=global_params.oversample_motion_time,
775
770
  t_end=totaltime,
776
771
  )
777
772
  return sample_plane
778
773
 
779
774
 
780
- def make_condensatedict(condensate_params, cell) -> List[dict]:
775
+ def make_condensatedict(
776
+ condensate_params: CondensateParameters, cell: BaseCell
777
+ ) -> List[dict]:
781
778
  condensates_dict = []
782
779
  for i in range(len(condensate_params.initial_centers)):
783
780
  condensates_dict.append(
@@ -807,26 +804,29 @@ def make_samplingfunction(condensate_params, cell) -> List[Callable]:
807
804
  return sampling_functions
808
805
 
809
806
 
810
- def gen_initial_positions(molecule_params, cell, condensate_params, sampling_functions):
807
+ def gen_initial_positions(
808
+ molecule_params: MoleculeParameters,
809
+ cell: BaseCell,
810
+ condensate_params: CondensateParameters,
811
+ sampling_functions: List[Callable],
812
+ ) -> List:
811
813
  initials = []
812
814
  for i in range(len(molecule_params.num_molecules)):
813
815
  num_molecules = molecule_params.num_molecules[i]
814
816
  initial_positions = gen_points(
815
817
  pdf=sampling_functions[i],
816
818
  total_points=num_molecules,
817
- min_x=cell.origin[0],
818
- max_x=cell.origin[0] + cell.dimensions[0],
819
- min_y=cell.origin[1],
820
- max_y=cell.origin[1] + cell.dimensions[1],
821
- min_z=-cell.dimensions[2] / 2,
822
- max_z=cell.dimensions[2] / 2,
819
+ volume=cell.volume,
820
+ bounds=cell.boundingbox,
823
821
  density_dif=condensate_params.density_dif[i],
824
822
  )
825
823
  initials.append(initial_positions)
826
824
  return initials
827
825
 
828
826
 
829
- def create_track_generator(global_params, cell):
827
+ def create_track_generator(
828
+ global_params: GlobalParameters, cell: BaseCell
829
+ ) -> Track_generator:
830
830
  totaltime = int(
831
831
  global_params.cycle_count
832
832
  * (global_params.exposure_time + global_params.interval_time)
@@ -834,15 +834,18 @@ def create_track_generator(global_params, cell):
834
834
  # make track generator
835
835
  track_generator = Track_generator(
836
836
  cell=cell,
837
- cycle_count=totaltime / global_params.oversample_motion_time,
838
- exposure_time=global_params.exposure_time,
839
- interval_time=global_params.interval_time,
837
+ total_time=totaltime,
840
838
  oversample_motion_time=global_params.oversample_motion_time,
841
839
  )
842
840
  return track_generator
843
841
 
844
842
 
845
- def get_tracks(molecule_params, global_params, initial_positions, track_generator):
843
+ def get_tracks(
844
+ molecule_params: MoleculeParameters,
845
+ global_params: GlobalParameters,
846
+ initial_positions: List,
847
+ track_generator: Track_generator,
848
+ ) -> Tuple[List, List]:
846
849
  totaltime = int(
847
850
  global_params.cycle_count
848
851
  * (global_params.exposure_time + global_params.interval_time)
@@ -897,7 +900,12 @@ def get_tracks(molecule_params, global_params, initial_positions, track_generato
897
900
  return tracks_collection, points_per_time_collection
898
901
 
899
902
 
900
- def add_tracks_to_sample(tracks, sample_plane, fluorophore, ID_counter=0):
903
+ def add_tracks_to_sample(
904
+ tracks: List,
905
+ sample_plane: SamplePlane,
906
+ fluorophore: List[Fluorophore],
907
+ ID_counter=0,
908
+ ) -> SamplePlane:
901
909
  counter = ID_counter
902
910
  for track_type in range(len(tracks)):
903
911
  for j in tracks[track_type].values():
@@ -0,0 +1,3 @@
1
+ from .nuclearporecomplexes import generate_nup96_positions
2
+
3
+ __all__ = ["generate_nup96_positions"]