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.
13 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
└── ...
51 # download the data
52 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.
65 # load the relaxed and the contracted stack
66 # {z} is the placeholder for the z stack
67 # {c} is the placeholder for the channels
68 # {t} is the placeholder for the time points
69 results = saenopy.get_stacks(
70 '1_ClassicSingleCellTFM/Deformed/Mark_and_Find_001/Pos*_S001_z{z}_ch{c:00}.tif',
71 reference_stack='1_ClassicSingleCellTFM/Relaxed/Mark_and_Find_001/Pos*_S001_z{z}_ch{c:00}.tif',
72 output_path='1_ClassicSingleCellTFM/example_output',
73 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 |
95 # define the parameters for the piv deformation detection
96 piv_parameters = {'element_size': 14.0, 'window_size': 35.0, 'signal_to_noise': 1.3, 'drift_correction': True}
97
98 # iterate over all the results objects
99 for result in results:
100 # set the parameters
101 result.piv_parameters = piv_parameters
102 # get count
103 count = len(result.stacks)
104 if result.stack_reference is None:
105 count -= 1
106 # iterate over all stack pairs
107 for i in range(count):
108 # get two consecutive stacks
109 if result.stack_reference is None:
110 stack1, stack2 = result.stacks[i], result.stacks[i + 1]
111 # or reference stack and one from the list
112 else:
113 stack1, stack2 = result.stack_reference, result.stacks[i]
114 # and calculate the displacement between them
115 result.mesh_piv[i] = saenopy.get_displacements_from_stacks(stack1, stack2,
116 piv_parameters["window_size"],
117 piv_parameters["element_size"],
118 piv_parameters["signal_to_noise"],
119 piv_parameters["drift_correction"])
120 # save the displacements
121 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’ |
140 # define the parameters to generate the solver mesh and interpolate the piv mesh onto it
141 mesh_parameters = {'reference_stack': 'first', 'element_size': 14.0, 'mesh_size': 'piv'}
142
143
144 # iterate over all the results objects
145 for result in results:
146 # correct for the reference state
147 displacement_list = saenopy.subtract_reference_state(result.mesh_piv, mesh_parameters["reference_stack"])
148 # set the parameters
149 result.mesh_parameters = mesh_parameters
150 # iterate over all stack pairs
151 for i in range(len(result.mesh_piv)):
152 # and create the interpolated solver mesh
153 result.solvers[i] = saenopy.interpolate_mesh(result.mesh_piv[i], displacement_list[i], mesh_parameters)
154 # save the meshes
155 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 |
187 # define the parameters to generate the solver mesh and interpolate the piv mesh onto it
188 material_parameters = {'k': 6062.0, 'd_0': 0.0025, 'lambda_s': 0.0804, 'd_s': 0.03}
189 solve_parameters = {'alpha': 10**10, 'step_size': 0.33, 'max_iterations': 400, 'rel_conv_crit': 0.009}
190
191 # iterate over all the results objects
192 for result in results:
193 result.material_parameters = material_parameters
194 result.solve_parameters = solve_parameters
195 for M in result.solvers:
196 # set the material model
197 M.set_material_model(saenopy.materials.SemiAffineFiberMaterial(
198 material_parameters["k"],
199 material_parameters["d_0"],
200 material_parameters["lambda_s"],
201 material_parameters["d_s"],
202 ))
203 # find the regularized force solution
204 M.solve_regularized(alpha=solve_parameters["alpha"], step_size=solve_parameters["step_size"],
205 max_iterations=solve_parameters["max_iterations"],
206 rel_conv_crit=solve_parameters["rel_conv_crit"], verbose=True)
207 # save the forces
208 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.