Dynamic TFM (immune cells)

This example evaluates a single natural killer cell that migrated through 1.2mg/ml collagen, recorded for 24min.

../_images/Gif_nk_dynamic_example.gif

This example can also be evaluated with the graphical user interface.

21 import saenopy

Downloading the example data files

The folder structure is as follows. There is one position recorded in the gel (Pos002) and two channels (ch00, ch01). The stack has 162 z positions (z000-z161). The position is recorded for 24 time steps (t00-t23).

2_DynamicalSingleCellTFM
└── data
    ├── Pos002_S001_t00_z000_ch00.tif
    ├── Pos002_S001_t00_z000_ch01.tif
    ├── Pos002_S001_t00_z001_ch00.tif
    ├── Pos002_S001_t00_z001_ch01.tif
    ├── Pos002_S001_t00_z002_ch00.tif
    ├── ...
    ├── Pos002_S001_t01_z000_ch00.tif
    ├── Pos002_S001_t01_z000_ch01.tif
    ├── Pos002_S001_t01_z001_ch00.tif
    └── ...
47 # download the data
48 saenopy.load_example("DynamicalSingleCellTFM")

Loading the Stacks

Saenopy is very flexible in loading stacks from any filename structure. Here we do not have multiple positions, so we do not need to use and asterisk * for batch processing. We replace the number of the channels “ch00” with a channel placeholder “ch{c:00}” to indicate that this refers to the channels and which channel to use as the first channel where the deformations should be detected. We replace the number of the z slice “z000” with a z placeholder “z{z}” to indicate that this number refers to the z slice. We replace the number of the time step “t00” with a time placeholder “t{t}” to indicate that this number refers to the time step. Due to technical reasons and the soft nature of collagen hydrogels, acquiring fast image stacks with our galvo stage (within 10 seconds) can cause external motion in the upper and lower region the image stack, as the stage accelerates and decelerates here. Therefore, we always acquire a larger stack in z-direction and then discard the upper and lower regions (20 images here).

69 # load the relaxed and the contracted stack
70 # {z} is the placeholder for the z stack
71 # {c} is the placeholder for the channels
72 # {t} is the placeholder for the time points
73
74 results = saenopy.get_stacks(r'2_DynamicalSingleCellTFM\data\Pos*_S001_t{t}_z{z}_ch{c:00}.tif',
75                              r'2_DynamicalSingleCellTFM\example_output',
76                              voxel_size=[0.2407, 0.2407, 1.0071],
77                              time_delta=60,
78                              crop={"z": (20, -20)}
79                              )

Detecting the Deformations

../_images/nk_dynamic_stacks.png

Saenopy uses 3D Particle Image Velocimetry (PIV) to calculate the collagen matrix deformations generated by the natural killer cell at different times. For this, we use the following parameters.

Piv Parameter

Value

element_size

4

window_size

12

signal_to_noise

1.3

drift_correction

True

104 # define the parameters for the piv deformation detection
105 piv_parameters = {'element_size': 4.0, 'window_size': 12.0, 'signal_to_noise': 1.3, 'drift_correction': True}
106
107
108 # iterate over all the results objects
109 for result in results:
110     # set the parameters
111     result.piv_parameters = piv_parameters
112     # get count
113     count = len(result.stacks)
114     if result.stack_reference is None:
115         count -= 1
116     # iterate over all stack pairs
117     for i in range(count):
118         # get two consecutive stacks
119         if result.stack_reference is None:
120             stack1, stack2 = result.stacks[i], result.stacks[i + 1]
121         # or reference stack and one from the list
122         else:
123             stack1, stack2 = result.stack_reference, result.stacks[i]
124
125         # due to the acceleration of the galvo stage there can be shaking in the
126         # lower or upper part of the stack. Therefore, we recorded larger
127         # z-regions and then discard the upper or lower parts
128
129         # and calculate the displacement between them
130         result.mesh_piv[i] = saenopy.get_displacements_from_stacks(stack1, stack2,
131                                                                     piv_parameters["window_size"],
132                                                                     piv_parameters["element_size"],
133                                                                     piv_parameters["signal_to_noise"],
134                                                                     piv_parameters["drift_correction"])
135     # save the displacements
136     result.save()

Visualizing Results

You can save the resulting 3D fields by simply using the export image dialog. Here we underlay a bright field image of the cell for a better overview and export a .gif file

../_images/nk_dynamic_piv_export_4fps.gif

Generating the Finite Element Mesh

Interpolate the found deformations onto a new mesh which will be used for the regularisation. We use the same element size of deformation detection mesh here and we also keep the overall mesh size the same. We define that as an undeformed reference we want to use the median of all stacks.

Mesh Parameter

Value

reference_stack

median

element_size

4

mesh_size

“piv”

170 # define the parameters to generate the solver mesh and interpolate the piv mesh onto it
171 mesh_parameters = {'reference_stack': 'median', 'element_size': 4.0, 'mesh_size': "piv"}
172
173 # iterate over all the results objects
174 for result in results:
175     # correct for the reference state
176     displacement_list = saenopy.subtract_reference_state(result.mesh_piv, mesh_parameters["reference_stack"])
177     # set the parameters
178     result.mesh_parameters = mesh_parameters
179     # iterate over all stack pairs
180     for i in range(len(result.mesh_piv)):
181         # and create the interpolated solver mesh
182         result.solvers[i] = saenopy.interpolate_mesh(result.mesh_piv[i], displacement_list[i], mesh_parameters)
183     # save the meshes
184     result.save()

Calculating the Forces

Define the material model and run the regularisation to fit the measured deformations and get the forces.

Material Parameter

Value

k

1449

d_0

0.0022

lambda_s

0.032

d_s

0.055

Regularisation Parameter

Value

alpha

10**10

step_size

0.33

max_iterations

100

214 # define the parameters to generate the solver mesh and interpolate the piv mesh onto it
215 material_parameters = {'k': 1449.0, 'd_0': 0.0022, 'lambda_s': 0.032, 'd_s': 0.055}
216 solve_parameters = {'alpha':  10**10, 'step_size': 0.33, 'max_iterations': 100}
217
218
219 # iterate over all the results objects
220 for result in results:
221     result.material_parameters = material_parameters
222     result.solve_parameters = solve_parameters
223     for M in result.solvers:
224         # set the material model
225         M.set_material_model(saenopy.materials.SemiAffineFiberMaterial(
226             material_parameters["k"],
227             material_parameters["d_0"],
228             material_parameters["lambda_s"],
229             material_parameters["d_s"],
230         ))
231         # find the regularized force solution
232         M.solve_regularized(alpha=solve_parameters["alpha"], step_size=solve_parameters["step_size"],
233                             max_iterations=solve_parameters["max_iterations"], verbose=True)
234     # save the forces
235     result.save()

Gallery generated by Sphinx-Gallery