ForSys: non-invasive stress inference from time-lapse microscopy

Augusto Borges 1, 2, Jerónimo R. Miranda-Rodríguez 1, 3, Alberto Sebastián Ceccarelli 4, Guilherme Ventura5, Jakub Sedzinski 5, Hernán López-Schier 1,2,6 & Osvaldo Chara 7, 8, 9

  1. Unit Sensory Biology, Helmholtz Zentrum München, Munich, Germany

  2. Graduate School of Quantitative Biosciences (QBM), Munich, Germany

  3. Instituto de Neurobiología, Universidad Nacional Autónoma de México (UNAM), Boulevard Juriquilla 3001, Juriquilla, México

  4. Systems Biology Group (SysBio), Institute of Physics of Liquids and Biological Systems (IFLySIB), National Scientific and Technical Research Council (CONICET), University of La Plata, La Plata, Argentina

  5. The Novo Nordisk Foundation Center for Stem Cell Medicine (reNEW), University of Copenhagen, Blegdamsvej 3B, 2200, Copenhagen, Denmark

  6. Division of Science, New York University Abu Dhabi, Saadiyat Island, United Arab Emirates

  7. School of Biosciences, University of Nottingham, Sutton Bonington Campus, Nottingham, LE12 5RD, UK

  8. Instituto de Tecnología, Universidad Argentina de la Empresa, Buenos Aires, Argentina

  9. Corresponding author: osvaldo.chara@nottingham.ac.uk

Generate an inference in a single SurfaceEvolver step

[1]:
import sys
sys.path.append('..')
import forsys as fs
import os
import matplotlib.pyplot as plt
[2]:
DATA_FOLDER = os.path.join("data", "in_silico")
RESULTS_FOLDER = os.path.join("results")

# This is only necessary if you wish to create outputscu
# if not os.path.exists(RESULTS_FOLDER):
#     os.makedirs(RESULTS_FOLDER)

Create the lattice from the desired time

[3]:
lattice = fs.surface_evolver.SurfaceEvolver(os.path.join(DATA_FOLDER,
                                                           f"step_{24}.dmp"))

Assign the frame object, and create the ForSys main object

[4]:
frames = {}
frames[0] = fs.frames.Frame(0,
                            lattice.vertices,
                            lattice.edges,
                            lattice.cells,
                            gt=True)
forsys = fs.ForSys(frames)

Build and solve the system of equations for the force

[5]:
forsys.build_force_matrix(when=0)
forsys.solve_stress(when=0, allow_negatives=False)
d:\manuscripts\unpublished\protocol_forsys\forsys\.venv\Lib\site-packages\forsys\fmatrix.py:317: UserWarning: Numerically solving due to the following error: Singular matrix
  warnings.warn(f"Numerically solving due to the following error: {e}")

Build and solve the system of equations for the pressure

[6]:
forsys.build_pressure_matrix(when=0)
forsys.solve_pressure(when=0, method="lagrange_pressure")

Create system’s plots

[7]:
fig, ax = fs.plot.plot_inference(forsys.frames[0],
                                 normalized="max",
                                 mirror_y=False,
                                 colorbar=False,
                                 pressure=False)
../_images/examples_static_in_silico_13_0.png

The pressure can be plotted using the pressure argument

[8]:
fig, ax = fs.plot.plot_inference(forsys.frames[0],
                                 normalized="max",
                                 mirror_y=False,
                                 colorbar=False,
                                 pressure=True)
../_images/examples_static_in_silico_15_0.png

Data can be exported through the Frames.get_tensions() method, and compared to the ground truth if it exists

[9]:
tensions_df = forsys.frames[0].get_tensions()

plt.scatter(tensions_df["gt"] / tensions_df["gt"].mean() , tensions_df["stress"])
plt.plot([0, 2], [0, 2], color="black", ls="--")
plt.xlabel("Ground truth")
plt.ylabel("Inferred stress")
plt.show()
../_images/examples_static_in_silico_17_0.png