Skip to content

Commit

Permalink
cleaned pyTFM evaluation code
Browse files Browse the repository at this point in the history
  • Loading branch information
rgerum committed Apr 19, 2024
1 parent 073567e commit b2d3e22
Show file tree
Hide file tree
Showing 12 changed files with 302 additions and 483 deletions.
17 changes: 2 additions & 15 deletions saenopy/gui/tfm2d/modules/CalculateDisplacements.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import matplotlib.pyplot as plt
from qtpy import QtWidgets
from saenopy.gui.common import QtShortCuts
from tifffile import imread
from typing import Tuple

from saenopy.gui.common.gui_classes import CheckAbleGroup
from saenopy.gui.common.code_export import get_code
from .PipelineModule import PipelineModule
from .result import Result2D

from saenopy.pyTFM.TFM_functions import calculate_deformation
from saenopy.pyTFM.calculate_deformation import calculate_deformation
from saenopy.pyTFM.plotting import show_quiver


Expand Down Expand Up @@ -45,18 +44,6 @@ def __init__(self, parent=None, layout=None):
"std_factor": self.input_std
})

def valueChanged(self):
if self.check_available(self.result):
im = imread(self.result.reference_stack).shape
#voxel_size1 = self.result.stacks[0].voxel_size
#stack_deformed = self.result.stacks[0]
#overlap = 1 - (self.input_element_size.value() / self.input_win.value())
#stack_size = np.array(stack_deformed.shape)[:3] * voxel_size1 - self.input_win.value()
#self.label.setText(
# f"""Overlap between neighbouring windows\n(size={self.input_win.value()}µm or {(self.input_win.value() / np.array(voxel_size1)).astype(int)} px) is choosen \n to {int(overlap * 100)}% for an element_size of {self.input_element_size.value():.1f}μm elements.\nTotal region is {stack_size}.""")
else:
self.label.setText("")

def check_available(self, result):
return True

Expand Down Expand Up @@ -87,7 +74,7 @@ def process(self, result: Result2D, piv_parameters: dict): # type: ignore
plt.savefig("deformation.png")

def get_code(self) -> Tuple[str, str]:
import_code = "from saenopy.pyTFM.TFM_functions import calculate_deformation\n"
import_code = "from saenopy.pyTFM.calculate_deformation import calculate_deformation\n"

results = []
def code(my_piv_params): # pragma: no cover
Expand Down
90 changes: 12 additions & 78 deletions saenopy/gui/tfm2d/modules/CalculateForceGeneration.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import numpy as np
from qtpy import QtWidgets
from tifffile import imread
try:
from scipy.ndimage import binary_fill_holes
except ImportError:
from scipy.ndimage.morphology import binary_fill_holes
from typing import List, Tuple

from saenopy.gui.common import QtShortCuts
Expand All @@ -14,8 +8,7 @@
from .result import Result2D
from .PipelineModule import PipelineModule

from saenopy.pyTFM.TFM_functions import strain_energy_points, contractillity
from saenopy.pyTFM.grid_setup_solids_py import interpolation # a simple function to resize the mask
from saenopy.pyTFM.calculate_strain_energy import calculate_strain_energy


class ForceGeneration(PipelineModule):
Expand All @@ -37,18 +30,6 @@ def __init__(self, parent=None, layout=None):

self.setParameterMapping("force_gen_parameters", {})

def valueChanged(self):
if self.check_available(self.result):
im = imread(self.result.reference_stack).shape
#voxel_size1 = self.result.stacks[0].voxel_size
#stack_deformed = self.result.stacks[0]
#overlap = 1 - (self.input_element_size.value() / self.input_win.value())
#stack_size = np.array(stack_deformed.shape)[:3] * voxel_size1 - self.input_win.value()
#self.label.setText(
# f"""Overlap between neighbouring windows\n(size={self.input_win.value()}µm or {(self.input_win.value() / np.array(voxel_size1)).astype(int)} px) is choosen \n to {int(overlap * 100)}% for an element_size of {self.input_element_size.value():.1f}μm elements.\nTotal region is {stack_size}.""")
else:
self.label.setText("")

def check_available(self, result):
return result.tx is not None

Expand All @@ -59,74 +40,27 @@ def tabChanged(self, tab):
pass

def process(self, result: Result2D, force_gen_parameters: dict): # type: ignore
print("process")
print("a")
x = result.mask == 1
print(result.mask)
print(x.dtype, x.shape)
print("x")
mask = binary_fill_holes(result.mask == 1) # the mask should be a single patch without holes
# changing the masks dimensions to fit to the deformation and traction fields
print("a")
mask = interpolation(mask, dims=result.u.shape)
print("a")
ps1 = result.pixel_size # pixel size of the image of the beads
# dimensions of the image of the beads
print("b")
ps2 = ps1 * np.mean(np.array(result.shape) / np.array(result.u.shape)) # pixel size of the deformation field
print("c")
# strain energy:
# first we calculate a map of strain energy
energy_points = strain_energy_points(result.u, result.v, result.tx, result.ty, ps1, ps2) # J/pixel
print("d")
#plt.imsave("strain_energy.png", energy_points)
#plt.imsave("mask.png", mask)
# then we sum all energy points in the area defined by mask
strain_energy = np.sum(energy_points[mask]) # 2.14*10**-13 J
print("e")
# contractility
contractile_force, proj_x, proj_y, center = contractillity(result.tx, result.ty, ps2, mask) # 2.03*10**-6 N
print("f")
result.res_dict["contractility"] = contractile_force
result.res_dict["area Traction Area"] = np.sum(mask) * ((result.pixel_size * 10 ** -6) ** 2)
result.res_dict["strain energy"] = strain_energy
result.res_dict["center of object"] = center
print("a")

results_dict = calculate_strain_energy(result.mask, result.pixel_size, result.shape,
result.u, result.v, result.tx, result.ty)

result.res_dict.update(results_dict)
result.save()

def get_code(self) -> Tuple[str, str]:
import_code = "from saenopy.pyTFM.TFM_functions import strain_energy_points, contractillity\nfrom scipy.ndimage import binary_fill_holes\nfrom pyTFM.grid_setup_solids_py import interpolation\n"
import_code = "\n".join([
"from saenopy.pyTFM.calculate_strain_energy import calculate_strain_energy",
])+"\n"

results: List[Result2D] = []
def code(): # pragma: no cover
# iterate over all the results objects
for result in results:
result.get_mask()
mask = binary_fill_holes(result.mask == 1) # the mask should be a single patch without holes
# changing the masks dimensions to fit to the deformation and traction fields
mask = interpolation(mask, dims=result.u.shape)

ps1 = result.pixel_size # pixel size of the image of the beads
# dimensions of the image of the beads
ps2 = ps1 * np.mean(
np.array(result.shape) / np.array(result.u.shape)) # pixel size of the deformation field

# strain energy:
# first we calculate a map of strain energy
energy_points = strain_energy_points(result.u, result.v, result.tx, result.ty, ps1, ps2) # J/pixel

# then we sum all energy points in the area defined by mask
strain_energy = np.sum(energy_points[mask]) # 2.14*10**-13 J

# contractility
contractile_force, proj_x, proj_y, center = contractillity(result.tx, result.ty, ps2,
mask) # 2.03*10**-6 N

result.res_dict["contractility"] = contractile_force
result.res_dict["area Traction Area"] = np.sum(mask) * ((result.pixel_size * 10 ** -6) ** 2)
result.res_dict["strain energy"] = strain_energy
result.res_dict["center of object"] = center
results_dict = calculate_strain_energy(result.mask, result.pixel_size, result.shape,
result.u, result.v, result.tx, result.ty)

result.res_dict.update(results_dict)
result.save()

data = {}
Expand Down
58 changes: 16 additions & 42 deletions saenopy/gui/tfm2d/modules/CalculateForces.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import matplotlib.pyplot as plt
from qtpy import QtWidgets
from tifffile import imread
import numpy as np
from typing import Tuple

from saenopy.gui.common import QtShortCuts
Expand All @@ -11,7 +9,7 @@
from .PipelineModule import PipelineModule
from .result import Result2D

from saenopy.pyTFM.TFM_tractions import TFM_tractions
from saenopy.pyTFM.calculate_forces import calculate_forces
from saenopy.pyTFM.plotting import show_quiver


Expand All @@ -20,24 +18,24 @@ class Force(PipelineModule):
def __init__(self, parent=None, layout=None):
super().__init__(parent, layout)
self.parent = parent
#layout.addWidget(self)

with self.parent.tabs.createTab("Forces") as self.tab:
pass

with QtShortCuts.QVBoxLayout(self) as layout:
layout.setContentsMargins(0, 0, 0, 0)
with CheckAbleGroup(self, "calculate forces").addToLayout() as self.group:
with QtShortCuts.QVBoxLayout() as layout:
with QtShortCuts.QVBoxLayout():
with QtShortCuts.QHBoxLayout():
self.input_young = QtShortCuts.QInputNumber(None, "young", 49000, float=False,
value_changed=self.valueChanged, unit="Pa",
tooltip="the size of the volume to look for a match")
value_changed=self.valueChanged, unit="Pa",
tooltip="the size of the volume to look for a match")
self.input_sigma = QtShortCuts.QInputNumber(None, "poisson ratio", 0.49, step=1, float=True,
value_changed=self.valueChanged,
tooltip="the overlap of windows")
self.input_h = QtShortCuts.QInputNumber(None, "h", 300, step=1, float=True,
value_changed=self.valueChanged, unit="µm",
tooltip="the overlap of windows")
value_changed=self.valueChanged, unit="µm",
tooltip="the overlap of windows")
self.label = QtWidgets.QLabel().addToLayout()
self.input_button = QtShortCuts.QPushButton(None, "calculate traction forces", self.start_process)

Expand All @@ -47,18 +45,6 @@ def __init__(self, parent=None, layout=None):
"h": self.input_h,
})

def valueChanged(self):
if self.check_available(self.result):
im = imread(self.result.reference_stack).shape
#voxel_size1 = self.result.stacks[0].voxel_size
#stack_deformed = self.result.stacks[0]
#overlap = 1 - (self.input_element_size.value() / self.input_win.value())
#stack_size = np.array(stack_deformed.shape)[:3] * voxel_size1 - self.input_win.value()
#self.label.setText(
# f"""Overlap between neighbouring windows\n(size={self.input_win.value()}µm or {(self.input_win.value() / np.array(voxel_size1)).astype(int)} px) is choosen \n to {int(overlap * 100)}% for an element_size of {self.input_element_size.value():.1f}μm elements.\nTotal region is {stack_size}.""")
else:
self.label.setText("")

def check_available(self, result):
return result.u is not None

Expand All @@ -71,25 +57,19 @@ def tabChanged(self, tab):
im = self.result.get_force_field()
self.parent.draw.setImage(im*255)


def process(self, result: Result2D, force_parameters: dict): # type: ignore
ps1 = result.pixel_size # pixel size of the image of the beads
# dimensions of the image of the beads
im1_shape = result.shape
print("process", force_parameters)
ps2 = ps1 * np.mean(np.array(im1_shape) / np.array(result.u.shape)) # pixel size of the deformation field
tx, ty = TFM_tractions(result.u, result.v, pixelsize1=ps1, pixelsize2=ps2,
h=force_parameters["h"], young=force_parameters["young"], sigma=force_parameters["sigma"])

def process(self, result: Result2D, force_parameters: dict): # type: ignore
tx, ty = calculate_forces(result.u, result.v, pixel_size=result.pixel_size, shape=result.shape,
h=force_parameters["h"], young=force_parameters["young"],
sigma=force_parameters["sigma"])
result.tx = tx
result.ty = ty
result.im_force = None
result.save()
fig2, ax = show_quiver(tx, ty, cbar_str="tractions\n[Pa]")
show_quiver(tx, ty, cbar_str="tractions\n[Pa]")
plt.savefig("force.png")

def get_code(self) -> Tuple[str, str]:
import_code = "from saenopy.pyTFM.TFM_functions import TFM_tractions\n"
import_code = "from saenopy.pyTFM.calculate_forces import calculate_forces\n"

results = []
def code(my_force_parameters): # pragma: no cover
Expand All @@ -101,15 +81,9 @@ def code(my_force_parameters): # pragma: no cover
# set the parameters
result.piv_parameters = force_parameters

ps1 = result.pixel_size # pixel size of the image of the beads
# dimensions of the image of the beads
im1_shape = result.shape
ps2 = ps1 * np.mean(
np.array(im1_shape) / np.array(result.u.shape)) # pixel size of the deformation field
tx, ty = TFM_tractions(result.u, result.v, pixelsize1=ps1, pixelsize2=ps2,
h=force_parameters["h"], young=force_parameters["young"],
sigma=force_parameters["sigma"])

tx, ty = calculate_forces(result.u, result.v, pixel_size=result.pixel_size, shape=result.shape,
h=force_parameters["h"], young=force_parameters["young"],
sigma=force_parameters["sigma"])
result.tx = tx
result.ty = ty

Expand Down
Loading

0 comments on commit b2d3e22

Please sign in to comment.