Note
Go to the end to download the full example code
Classic TFM (liver fibroblasts)¶
This example evaluates three hepatic stellate cells in 1.2mg/ml collagen with relaxed and deformed stacks. The relaxed stacks were recorded with cytochalasin D treatment of the cells. This example can also be evaluated with the graphical user interface.
15 import saenopy
Downloading the example data files¶
The folder structure is as follows. There are three cells recorded at different positions in the gel (Pos004, Pos007, Pos008) and three channels (ch00, ch01, ch02). The stack has 376 z positions (z000-z375). All positions are recorded once in the active state (“Deformed”) and once after relaxation with Cyto D as the reference state (“Relaxed”).
1_ClassicSingleCellTFM
├── Deformed
│ └── Mark_and_Find_001
│ ├── Pos004_S001_z000_ch00.tif
│ ├── Pos004_S001_z000_ch01.tif
│ ├── Pos004_S001_z000_ch02.tif
│ ├── Pos004_S001_z001_ch02.tif
│ ├── ...
│ ├── Pos007_S001_z001_ch00.tif
│ ├── ...
│ ├── Pos008_S001_z001_ch02.tif
│ └── ...
└── Relaxed
└── Mark_and_Find_001
├── Pos004_S001_z000_ch00.tif
├── Pos004_S001_z000_ch01.tif
├── Pos004_S001_z000_ch02.tif
├── Pos004_S001_z001_ch02.tif
├── ...
├── Pos007_S001_z001_ch00.tif
├── ...
├── Pos008_S001_z001_ch02.tif
└── ...
53 # download the data
54 saenopy.load_example("ClassicSingleCellTFM")
Loading the Stacks¶
Saenopy is very flexible in loading stacks from any filename structure. Here we replace the number in the position “Pos004” with an asterisk “Pos*” to batch process all positions. 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 do the same for the deformed state and for the reference stack.
67 # load the relaxed and the contracted stack
68 # {z} is the placeholder for the z stack
69 # {c} is the placeholder for the channels
70 # {t} is the placeholder for the time points
71 results = saenopy.get_stacks(
72 '1_ClassicSingleCellTFM/Deformed/Mark_and_Find_001/Pos*_S001_z{z}_ch{c:00}.tif',
73 reference_stack='1_ClassicSingleCellTFM/Relaxed/Mark_and_Find_001/Pos*_S001_z{z}_ch{c:00}.tif',
74 output_path='1_ClassicSingleCellTFM/example_output',
75 voxel_size=[0.7211, 0.7211, 0.988])
Detecting the Deformations¶
Saenopy uses 3D Particle Image Velocimetry (PIV) with the following parameters to calculate matrix deformations between a deformed and relaxed state for three example cells.
Piv Parameter |
Value |
|---|---|
element_size |
14 |
window_size |
35 |
signal_to_noise |
1.3 |
drift_correction |
True |
97 # define the parameters for the piv deformation detection
98 piv_parameters = {'element_size': 14.0, 'window_size': 35.0, 'signal_to_noise': 1.3, 'drift_correction': True}
99
100 # iterate over all the results objects
101 for result in results:
102 # set the parameters
103 result.piv_parameters = piv_parameters
104 # get count
105 count = len(result.stacks)
106 if result.stack_reference is None:
107 count -= 1
108 # iterate over all stack pairs
109 for i in range(count):
110 # get two consecutive stacks
111 if result.stack_reference is None:
112 stack1, stack2 = result.stacks[i], result.stacks[i + 1]
113 # or reference stack and one from the list
114 else:
115 stack1, stack2 = result.stack_reference, result.stacks[i]
116 # and calculate the displacement between them
117 result.mesh_piv[i] = saenopy.get_displacements_from_stacks(stack1, stack2,
118 piv_parameters["window_size"],
119 piv_parameters["element_size"],
120 piv_parameters["signal_to_noise"],
121 piv_parameters["drift_correction"])
122 # save the displacements
123 result.save()
Generating the Finite Element Mesh¶
Interpolate the found deformations onto a new mesh which will be used for the regularisation. We use identical element size of deformation detection mesh here and keep the overall mesh size the same.
Mesh Parameter |
Value |
|---|---|
element_size |
14 |
mesh_size |
‘piv’ |
reference_stack |
‘first’ |
142 # define the parameters to generate the solver mesh and interpolate the piv mesh onto it
143 mesh_parameters = {'reference_stack': 'first', 'element_size': 14.0, 'mesh_size': 'piv'}
144
145
146 # iterate over all the results objects
147 for result in results:
148 # correct for the reference state
149 displacement_list = saenopy.subtract_reference_state(result.mesh_piv, mesh_parameters["reference_stack"])
150 # set the parameters
151 result.mesh_parameters = mesh_parameters
152 # iterate over all stack pairs
153 for i in range(len(result.mesh_piv)):
154 # and create the interpolated solver mesh
155 result.solvers[i] = saenopy.interpolate_mesh(result.mesh_piv[i], displacement_list[i], mesh_parameters)
156 # save the meshes
157 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 |
6062 |
d_0 |
0.0025 |
lambda_s |
0.0804 |
d_s |
0.034 |
Regularisation Parameter |
Value |
|---|---|
alpha |
10**10 |
step_size |
0.33 |
max_iterations |
400 |
rel_conv_crit |
0.009 |
189 # define the parameters to generate the solver mesh and interpolate the piv mesh onto it
190 material_parameters = {'k': 6062.0, 'd_0': 0.0025, 'lambda_s': 0.0804, 'd_s': 0.03}
191 solve_parameters = {'alpha': 10**10, 'step_size': 0.33, 'max_iterations': 400, 'rel_conv_crit': 0.009}
192
193 # iterate over all the results objects
194 for result in results:
195 result.material_parameters = material_parameters
196 result.solve_parameters = solve_parameters
197 for M in result.solvers:
198 # set the material model
199 M.set_material_model(saenopy.materials.SemiAffineFiberMaterial(
200 material_parameters["k"],
201 material_parameters["d_0"],
202 material_parameters["lambda_s"],
203 material_parameters["d_s"],
204 ))
205 # find the regularized force solution
206 M.solve_regularized(alpha=solve_parameters["alpha"], step_size=solve_parameters["step_size"],
207 max_iterations=solve_parameters["max_iterations"],
208 rel_conv_crit=solve_parameters["rel_conv_crit"], verbose=True)
209 # save the forces
210 result.save()
Display Results¶
The reconstructed force field (right) generates a reconstructed deformation field (middle) that recapitulates the measured matrix deformation field (left). The overall cell contractility is calculated as all forcecomponents pointing to the force epicenter.