Mentions légales du service

Skip to content
Snippets Groups Projects
Commit d13bdf83 authored by CERUTTI Guillaume's avatar CERUTTI Guillaume
Browse files

add tissue mesh operations as mesh filter + update to timagetk geometry renaming

parent b8441d6b
No related branches found
No related tags found
No related merge requests found
Pipeline #920284 failed
......@@ -47,6 +47,11 @@ setup_kwds = dict(
'wallMeshImageSignal = gnomon_package_tissueimagemesh.algorithm.cellImageQuantification.wallMeshImageSignal',
'wallMeshSignalPolarities = gnomon_package_tissueimagemesh.algorithm.cellImageQuantification.wallMeshSignalPolarities',
],
'meshFilter': [
'surfaceCellMeshDecimation = gnomon_package_tissueimagemesh.algorithm.meshFilter.surfaceCellMeshDecimation',
'surfaceCellMeshFlipOptimization = gnomon_package_tissueimagemesh.algorithm.meshFilter.surfaceCellMeshFlipOptimization',
'surfaceMeshCellProjection = gnomon_package_tissueimagemesh.algorithm.meshFilter.surfaceMeshCellProjection'
],
'meshFromImage': [
'imageSurfaceMesh = gnomon_package_tissueimagemesh.algorithm.meshFromImage.imageSurfaceMesh',
'segmentationSurfaceMesh = gnomon_package_tissueimagemesh.algorithm.meshFromImage.segmentationSurfaceMesh',
......
......@@ -66,8 +66,8 @@ class surfaceMeshCellProperty(gnomonAbstractCellImageQuantification):
out_tissue.walls.image = out_tissue
cell_labels = out_tissue.cell_ids()
if surface_topomesh.has_wisp_property('cell', 0, is_computed=True):
vertex_cells = surface_topomesh.wisp_property('cell', 0).values(list(surface_topomesh.wisps(0)))
if surface_topomesh.has_wisp_property('label', 0, is_computed=True):
vertex_cells = surface_topomesh.wisp_property('label', 0).values(list(surface_topomesh.wisps(0)))
else:
if 'surface_center' in out_tissue.cells.feature_names():
cell_surface_centers = out_tissue.cells.feature('surface_center')
......@@ -79,7 +79,7 @@ class surfaceMeshCellProperty(gnomonAbstractCellImageQuantification):
vertex_cell_distances = np.linalg.norm(vertex_points[:, np.newaxis] - cell_centers[np.newaxis], axis=-1)
vertex_cells = cell_labels[np.argmin(vertex_cell_distances, axis=-1)]
surface_topomesh.update_wisp_property('cell', 0, dict(zip(surface_topomesh.wisps(0), vertex_cells)))
surface_topomesh.update_wisp_property('label', 0, dict(zip(surface_topomesh.wisps(0), vertex_cells)))
surface_topomesh.update_wisp_property('label', 0, dict(zip(surface_topomesh.wisps(0), vertex_cells%256)))
for property_name in self['attribute_names']:
......
# {# gnomon, plugin.imports
# do not modify, any code after the gnomon tag will be overwritten
from dtkcore import d_bool, d_real
import gnomon.core
from gnomon.utils import algorithmPlugin
from gnomon.utils.decorators import meshInput, meshOutput
# #}
# add your imports before the next gnomon tag
from copy import deepcopy
import numpy as np
import scipy.ndimage as nd
from cellcomplex.property_topomesh.analysis import compute_topomesh_property, compute_topomesh_vertex_property_from_faces
from cellcomplex.property_topomesh.topological_operations import topomesh_collapse_edge
from cellcomplex.property_topomesh.extraction import clean_topomesh_properties
from cellcomplex.utils import array_dict
# {# gnomon, plugin.class
# do not modify, any code after the gnomon tag will be overwritten
@algorithmPlugin(version='0.1.0', coreversion='0.81.0', name="Surface Cell Projection")
@meshInput(attr='in_surface_topomesh', data_plugin='gnomonMeshDataPropertyTopomesh')
@meshOutput(attr='surface_topomesh', data_plugin='gnomonMeshDataPropertyTopomesh')
class surfaceCellMeshDecimation(gnomon.core.gnomonAbstractMeshFilter):
"""Decimate tissue mesh to keep one vertex per cell label
"""
def __init__(self):
super().__init__()
self._parameters = {}
# self.seg_img = {}
self.in_surface_topomesh = {}
self.surface_topomesh = {}
def run(self):
self.surface_topomesh = {}
for time in self.in_surface_topomesh.keys():
surface_topomesh = deepcopy(self.in_surface_topomesh[time])
# #}
# implement the run method
edges = np.array(list(surface_topomesh.wisps(1)))
edge_vertices = surface_topomesh.wisp_property('vertices', 1).values(edges)
edge_vertex_cells = surface_topomesh.wisp_property('label', 0).values(edge_vertices)
inner_edges = edges[edge_vertex_cells[:, 1] == edge_vertex_cells[:, 0]]
inner_edge_lengths = surface_topomesh.wisp_property('length', 1).values(inner_edges)
inner_edges = inner_edges[np.argsort(inner_edge_lengths)]
collapsed_edges = inner_edges
iteration = 0
while len(collapsed_edges)>0:
collapsed_edges = []
affected_edges = set()
for e in inner_edges:
if not e in affected_edges:
neighbor_edges = set(surface_topomesh.border_neighbors(1, e))
collapsed = topomesh_collapse_edge(surface_topomesh, e)
if collapsed:
collapsed_edges += [e]
affected_edges |= set(neighbor_edges)
iteration += 1
print(f"Collapsed {len(collapsed_edges)} edges")
clean_topomesh_properties(surface_topomesh)
compute_topomesh_property(surface_topomesh, 'vertices', 1)
compute_topomesh_property(surface_topomesh, 'length', 1)
edges = np.array(list(surface_topomesh.wisps(1)))
edge_vertices = surface_topomesh.wisp_property('vertices', 1).values(edges)
edge_vertex_cells = surface_topomesh.wisp_property('label', 0).values(edge_vertices)
inner_edges = edges[edge_vertex_cells[:, 1] == edge_vertex_cells[:, 0]]
inner_edge_lengths = surface_topomesh.wisp_property('length', 1).values(inner_edges)
inner_edges = inner_edges[np.argsort(inner_edge_lengths)]
compute_topomesh_property(surface_topomesh, 'borders', 2)
compute_topomesh_property(surface_topomesh, 'vertices', 2)
compute_topomesh_property(surface_topomesh, 'oriented_vertices', 2)
compute_topomesh_property(surface_topomesh, 'oriented_borders', 3)
self.surface_topomesh[time] = surface_topomesh
# {# gnomon, plugin.imports
# do not modify, any code after the gnomon tag will be overwritten
from dtkcore import d_int, d_real
import gnomon.core
from gnomon.utils import algorithmPlugin
from gnomon.utils.decorators import cellImageInput, meshInput, meshOutput
# #}
# add your imports before the next gnomon tag
from copy import deepcopy
import numpy as np
from cellcomplex.property_topomesh.optimization import property_topomesh_edge_flip_optimization
# {# gnomon, plugin.class
# do not modify, any code after the gnomon tag will be overwritten
@algorithmPlugin(version='0.1.0', coreversion='0.72.0', name="Cell Mesh Flip Optimization")
@cellImageInput("seg_img", data_plugin="gnomonCellImageDataTissueImage")
@meshInput(attr='in_surface_topomesh', data_plugin='gnomonMeshDataPropertyTopomesh')
@meshOutput(attr='surface_topomesh', data_plugin='gnomonMeshDataPropertyTopomesh')
class surfaceCellMeshFlipOptimization(gnomon.core.gnomonAbstractMeshFilter):
"""Perform edge flips to get closer to the image cell ajacencies
"""
def __init__(self):
super().__init__()
self._parameters = {}
self._parameters['iterations'] = d_int("Iterations", 3, 0, 5, "The number of iterations to perform in the edge flip process")
self._parameters['regularization'] = d_real("Regularization Weight", 0, 0, 1, 2, "The weight associated to the regularization energy term")
self.seg_img = {}
self.in_surface_topomesh = {}
self.surface_topomesh = {}
def run(self):
self.surface_topomesh = {}
for time in self.in_surface_topomesh.keys():
surface_topomesh = deepcopy(self.in_surface_topomesh[time])
# #}
# implement the run method
if self['iterations']>0:
vertex_cells = surface_topomesh.wisp_property('label', 0)
unique_cells = np.unique(vertex_cells.values())
cell_vertices = {c: [] for c in unique_cells}
for v, c in vertex_cells.items():
cell_vertices[c] += [v]
seg_img = self.seg_img[time]
image_cell_edges = np.array([w for w in seg_img.wall_ids()])
image_edges = []
for c1, c2 in image_cell_edges:
if c1 in cell_vertices and c2 in cell_vertices:
image_edges += [
(v1, v2)
for v1 in cell_vertices[c1] for v2 in cell_vertices[c2]
]
image_edges += [
(v2, v1)
for v1 in cell_vertices[c1] for v2 in cell_vertices[c2]
]
image_edges = np.array(image_edges)
omega_energies = {'image': 1}
if self['regularization'] > 0:
omega_energies.update({'regularization': self['regularization']})
property_topomesh_edge_flip_optimization(
surface_topomesh,
iterations=self['iterations'],
omega_energies=omega_energies,
simulated_annealing=False,
image_edges=image_edges
)
self.surface_topomesh[time] = surface_topomesh
# {# gnomon, plugin.imports
# do not modify, any code after the gnomon tag will be overwritten
from dtkcore import d_bool, d_real, d_inliststring
import gnomon.core
from gnomon.utils import algorithmPlugin
from gnomon.utils.decorators import cellImageInput, meshInput, meshOutput
# #}
# add your imports before the next gnomon tag
from copy import deepcopy
from timagetk_geometry.image_surface.tissue_image_mesh import surface_vertex_normal_sampling_label_projection, surface_vertex_remove_isolated_labels
# {# gnomon, plugin.class
# do not modify, any code after the gnomon tag will be overwritten
@algorithmPlugin(version='0.1.0', coreversion='0.72.0', name="Surface Cell Projection")
@cellImageInput("seg_img", data_plugin="gnomonCellImageDataTissueImage")
@meshInput(attr='in_surface_topomesh', data_plugin='gnomonMeshDataPropertyTopomesh')
@meshOutput(attr='surface_topomesh', data_plugin='gnomonMeshDataPropertyTopomesh')
class surfaceMeshCellProjection(gnomon.core.gnomonAbstractMeshFilter):
"""Project cell labels on surface mesh using normals
"""
def __init__(self):
super().__init__()
self._parameters = {}
self._parameters['sampling_depth'] = d_real("Sampling depth", 3., 0., 10., 1, "Depth up to which to sample the segmented image")
self._parameters['method'] = d_inliststring("Method", "median", ["most", "first", "median"], "Method used to choose the selected label")
self._parameters['remove_isolated_labels'] = d_bool("Remove isolated labels",True, "Whether to remove labels that have no identical neighbor")
self.seg_img = {}
self.in_surface_topomesh = {}
self.surface_topomesh = {}
def run(self):
self.surface_topomesh = {}
for time in self.in_surface_topomesh.keys():
surface_topomesh = deepcopy(self.in_surface_topomesh[time])
# #}
# implement the run method
seg_img = self.seg_img[time]
surface_vertex_normal_sampling_label_projection(
surface_topomesh,
seg_img,
sampling_depth=self['sampling_depth'],
method=self['method']
)
if self['remove_isolated_labels']:
surface_vertex_remove_isolated_labels(surface_topomesh)
self.surface_topomesh[time] = surface_topomesh
......@@ -58,8 +58,8 @@ class surfaceMeshProperty(gnomonAbstractPointCloudQuantification):
out_df = deepcopy(df)
cell_labels = df['label'].values
if surface_topomesh.has_wisp_property('cell', 0, is_computed=True):
vertex_cells = surface_topomesh.wisp_property('cell', 0).values(list(surface_topomesh.wisps(0)))
if surface_topomesh.has_wisp_property('label', 0, is_computed=True):
vertex_cells = surface_topomesh.wisp_property('label', 0).values(list(surface_topomesh.wisps(0)))
else:
cell_centers = df[['center_'+dim for dim in 'xyz']].values
......@@ -67,7 +67,7 @@ class surfaceMeshProperty(gnomonAbstractPointCloudQuantification):
vertex_cell_distances = np.linalg.norm(vertex_points[:, np.newaxis] - cell_centers[np.newaxis], axis=-1)
vertex_cells = cell_labels[np.argmin(vertex_cell_distances, axis=-1)]
surface_topomesh.update_wisp_property('cell', 0, dict(zip(surface_topomesh.wisps(0), vertex_cells)))
surface_topomesh.update_wisp_property('label', 0, dict(zip(surface_topomesh.wisps(0), vertex_cells)))
surface_topomesh.update_wisp_property('label', 0, dict(zip(surface_topomesh.wisps(0), vertex_cells%256)))
for property_name in self['attribute_names']:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment