Source code for cellcomplex.property_topomesh.utils.tissue_analysis_tools
# -*- coding: utf-8 -*-
# -*- python -*-
#
# PropertyTopomesh
#
# Copyright 2015-2016 INRIA - CIRAD - INRA
#
# File author(s): Guillaume Cerutti <guillaume.cerutti@inria.fr>
#
# File contributor(s): Guillaume Cerutti <guillaume.cerutti@inria.fr>,
# Jonathan Legrand <jonathan.legrand@inria.fr>
#
# Distributed under the Cecill-C License.
# See accompanying file LICENSE.txt or copy at
# http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html
#
# OpenaleaLab Website : http://virtualplants.github.io/
#
###############################################################################
import logging
import numpy as np
from time import time as current_time
from cellcomplex.property_topomesh.analysis import compute_topomesh_property
from scipy.cluster.vq import vq
from time import time
[docs]def cell_topological_elements_extraction(img, dimensions=[2,1,0]):
start_time = time()
logging.info("--> Extracting cell topological elements")
shape = np.array(img.shape)
neighborhood_img = []
for x in np.arange(-1,1):
for y in np.arange(-1,1):
for z in np.arange(-1,1):
neighborhood_img.append(img[1+x:shape[0]+x,1+y:shape[1]+y,1+z:shape[2]+z])
neighborhood_img = np.sort(np.transpose(neighborhood_img,(1,2,3,0))).reshape((shape-1).prod(),8)
vertex_coords = np.transpose(np.mgrid[0:shape[0]-1,0:shape[1]-1,0+z:shape[2]-1],(1,2,3,0)).reshape((shape-1).prod(),3)+0.5
non_flat = np.sum(neighborhood_img == np.tile(neighborhood_img[:,:1],(1,8)),axis=1)!=8
neighborhood_img = neighborhood_img[non_flat]
vertex_coords = vertex_coords[non_flat]
neighborhoods = np.array(list(map(np.unique,neighborhood_img)))
neighborhood_size = np.array(list(map(len,neighborhoods)))
neighborhoods = np.array(neighborhoods)
topological_elements = {}
for dimension in dimensions:
element_points = vertex_coords[neighborhood_size==4-dimension]
element_cells = np.array([p for p in neighborhoods[neighborhood_size==4-dimension]],int)
if (dimension==0) & ((neighborhood_size>=5).sum() > 0):
clique_vertex_points = np.concatenate([(p,p) for p in vertex_coords[neighborhood_size==5]])
clique_vertex_cells = np.concatenate([[p[:4],np.concatenate([[p[0]],p[2:]])] for p in neighborhoods[neighborhood_size==5]]).astype(int)
element_points = np.concatenate([element_points,clique_vertex_points])
element_cells = np.concatenate([element_cells,clique_vertex_cells])
unique_cell_elements = np.unique(element_cells,axis=0)
element_matching = vq(element_cells,unique_cell_elements)[0]
topological_elements[dimension] = dict(list(zip([tuple(e) for e in unique_cell_elements],[element_points[element_matching == e] for e,_ in enumerate(unique_cell_elements)])))
end_time = time()
logging.info("<-- Extracting cell topological elements [",end_time - start_time,"s]")
return topological_elements
[docs]def cell_vertex_extraction(img,physical_units=False):
start_time = time()
print("--> Extracting cell vertices")
shape = np.array(img.shape)
if img.ndim==3 and shape[2]>1:
neighborhood_img = []
for x in np.arange(-1,1):
for y in np.arange(-1,1):
for z in np.arange(-1,1):
neighborhood_img.append(img[1+x:shape[0]+x,1+y:shape[1]+y,1+z:shape[2]+z])
neighborhood_img = np.sort(np.transpose(neighborhood_img,(1,2,3,0))).reshape((shape-1).prod(),8)
vertex_coords = np.transpose(np.mgrid[0:shape[0]-1,0:shape[1]-1,0+z:shape[2]-1],(1,2,3,0)).reshape((shape-1).prod(),3)+0.5
non_flat = np.sum(neighborhood_img == np.tile(neighborhood_img[:,:1],(1,8)),axis=1)!=8
neighborhood_img = neighborhood_img[non_flat]
vertex_coords = vertex_coords[non_flat]
neighborhoods = np.array(list(map(np.unique,neighborhood_img)))
neighborhood_size = np.array(list(map(len,neighborhoods)))
neighborhoods = np.array(neighborhoods)
# vertex_coords = np.where(neighborhood_size==4)
#vertex_coords = np.where(neighborhood_size >= 4)
# vertex_points = np.transpose(vertex_coords)+0.5
vertex_points = vertex_coords[neighborhood_size==4]
# vertex_cells = np.array([p for p in neighborhoods[vertex_coords]],int)
vertex_cells = np.array([p for p in neighborhoods[neighborhood_size==4]],int)
#vertex_cells = np.array([p[:4] for p in neighborhoods[vertex_coords]],int)
if (neighborhood_size>=5).sum() > 0:
clique_vertex_points = np.concatenate([(p,p) for p in vertex_coords[neighborhood_size==5]])
clique_vertex_cells = np.concatenate([[p[:4],np.concatenate([[p[0]],p[2:]])] for p in neighborhoods[neighborhood_size==5]]).astype(int)
# clique_vertex_coords = np.where(neighborhood_size==5)
# clique_vertex_points = np.concatenate([(p,p) for p in np.transpose(clique_vertex_coords)])+0.5
# clique_vertex_cells = np.concatenate([[p[:4],np.concatenate([[p[0]],p[2:]])] for p in neighborhoods[clique_vertex_coords]]).astype(int)
# clique_vertex_points = np.concatenate([(p,p,p,p,p) for p in np.transpose(clique_vertex_coords)])+0.5
# clique_vertex_cells = np.concatenate([[np.concatenate([p[:i],p[i+1:]]) for i in range(5)] for p in neighborhoods[clique_vertex_coords]]).astype(int)
vertex_points = np.concatenate([vertex_points,clique_vertex_points])
vertex_cells = np.concatenate([vertex_cells,clique_vertex_cells])
unique_cell_vertices = np.unique(vertex_cells,axis=0)
vertices_matching = vq(vertex_cells,unique_cell_vertices)[0]
unique_cell_vertex_points = np.array([np.mean(vertex_points[vertices_matching == v],axis=0) for v in range(len(unique_cell_vertices))])
if physical_units:
cell_vertex_dict = dict(zip([tuple(c) for c in unique_cell_vertices],unique_cell_vertex_points*np.array(img.voxelsize)))
else:
cell_vertex_dict = dict(zip([tuple(c) for c in unique_cell_vertices],unique_cell_vertex_points))
elif img.ndim==2 or (img.ndim==3 and shape[2]==1):
if img.ndim==3:
img = img[:,:,0]
shape = np.array(img.shape)
neighborhood_img = []
for x in np.arange(-1,1):
for y in np.arange(-1,1):
neighborhood_img.append(img[1+x:shape[0]+x,1+y:shape[1]+y])
neighborhood_img = np.sort(np.transpose(neighborhood_img,(1,2,0))).reshape((shape-1).prod(),4)
neighborhoods = np.array(list(map(np.unique,neighborhood_img)))
neighborhood_size = np.array(list(map(len,neighborhoods))).reshape(shape[0]-1,shape[1]-1)
neighborhoods = np.array(neighborhoods).reshape(shape[0]-1,shape[1]-1)
vertex_coords = np.where(neighborhood_size==3)
vertex_points = np.transpose(vertex_coords)+0.5
vertex_cells = np.array([p for p in neighborhoods[vertex_coords]],int)
if (neighborhood_size>=4).sum() > 0:
clique_vertex_coords = np.where(neighborhood_size==4)
clique_vertex_points = np.concatenate([(p,p) for p in np.transpose(clique_vertex_coords)])+0.5
clique_vertex_cells = np.concatenate([[p[:3],np.concatenate([[p[0]],p[2:]])] for p in neighborhoods[clique_vertex_coords]]).astype(int)
vertex_points = np.concatenate([vertex_points,clique_vertex_points])
vertex_cells = np.concatenate([vertex_cells,clique_vertex_cells])
unique_cell_vertices = np.unique(vertex_cells,axis=0)
vertices_matching = vq(vertex_cells,unique_cell_vertices)[0]
unique_cell_vertex_points = np.array([np.mean(vertex_points[vertices_matching == v],axis=0) for v in range(len(unique_cell_vertices))])
cell_vertex_dict = dict(list(zip([tuple(c) for c in unique_cell_vertices],list(unique_cell_vertex_points))))
else:
cell_vertex_dict = {}
end_time = time()
print("<-- Extracting cell vertices (",len(cell_vertex_dict),"vertices ) [",end_time - start_time,"s]")
return cell_vertex_dict
[docs]def voxel_cell_vertex_extraction(img,**kwargs):
shape = np.array(img.shape)
neighborhood_img = []
for x in np.arange(-1,2):
for y in np.arange(-1,2):
for z in np.arange(-1,2):
neighborhood_img.append(img[1+x:shape[0]-1+x,1+y:shape[1]-1+y,1+z:shape[2]-1+z])
neighborhood_img = np.sort(np.transpose(neighborhood_img,(1,2,3,0))).reshape((shape-2).prod(),27)
neighborhoods = np.array(list(map(np.unique,neighborhood_img)))
neighborhood_size = np.array(list(map(len,neighborhoods))).reshape(shape[0]-2,shape[1]-2,shape[2]-2)
neighborhoods = np.array(neighborhoods).reshape(shape[0]-2,shape[1]-2,shape[2]-2)
vertex_coords = np.where(neighborhood_size==4)
vertex_points = np.transpose(vertex_coords)+1
vertex_cells = np.array([p for p in neighborhoods[vertex_coords]],int)
unique_cell_vertices = np.unique(vertex_cells,axis=0)
vertices_matching = vq(vertex_cells,unique_cell_vertices)[0]
unique_cell_vertex_points = np.array([np.mean(vertex_points[vertices_matching == v],axis=0) for v in range(len(unique_cell_vertices))])
cell_vertex_dict = dict(list(zip([tuple(c) for c in unique_cell_vertices],list(unique_cell_vertex_points))))
return cell_vertex_dict
[docs]def topomesh_cell_vertex_extraction(topomesh, background_label=1):
compute_topomesh_property(topomesh, 'cells', degree=0)
vertex_cell_neighbours = topomesh.wisp_property('cells', degree=0)
surface_faces = [f for f in topomesh.wisps(2) if topomesh.nb_regions(2, f) == 1]
surface_vertices = [v for v in topomesh.wisps(0) if np.any([f in surface_faces for f in topomesh.regions(0, v, 2)])]
start_time = current_time()
print("--> Computing mesh cell vertices")
mesh_cell_vertex = {}
for v in topomesh.wisps(0):
if len(vertex_cell_neighbours[v]) == 5:
for k in range(5):
vertex_cell_labels = tuple([c for c in vertex_cell_neighbours[v]][:k]) + tuple([c for c in vertex_cell_neighbours[v]][k + 1:])
if vertex_cell_labels not in mesh_cell_vertex:
mesh_cell_vertex[vertex_cell_labels] = v
if len(vertex_cell_neighbours[v]) == 4:
vertex_cell_labels = tuple([c for c in vertex_cell_neighbours[v]])
mesh_cell_vertex[vertex_cell_labels] = v
if v in surface_vertices:
# and count_l1_cells(vertex_cell_neighbours[v]) == 4:
for k in range(4):
vertex_cell_labels = (background_label,) + tuple([c for c in vertex_cell_neighbours[v]][:k]) + tuple([c for c in vertex_cell_neighbours[v]][k + 1:])
if vertex_cell_labels not in mesh_cell_vertex:
mesh_cell_vertex[vertex_cell_labels] = v
if (len(vertex_cell_neighbours[v]) == 3) and (v in surface_vertices):
# and (count_l1_cells(vertex_cell_neighbours[v]) == 3):
vertex_cell_labels = (background_label,) + tuple([c for c in vertex_cell_neighbours[v]])
mesh_cell_vertex[vertex_cell_labels] = v
end_time = current_time()
print("<-- Computing mesh cell vertices [", end_time - start_time, "s]")
return mesh_cell_vertex
[docs]def move_topomesh_cell_vertices(topomesh, cell_vertex_positions, background_label=1, coef=0.5):
mesh_cell_vertex = topomesh_cell_vertex_extraction(topomesh, background_label=background_label)
# cell_vertex_matching = vq(np.sort(array_dict(cell_vertex_positions).keys()),np.sort(array_dict(mesh_cell_vertex).keys()))
cell_vertex_matching = vq(np.sort(np.array(list(cell_vertex_positions.keys()))), np.sort(np.array(list(mesh_cell_vertex.keys()))))
matched_image_index = np.where(cell_vertex_matching[1] == 0)[0]
matched_mesh_index = cell_vertex_matching[0][np.where(cell_vertex_matching[1] == 0)[0]]
matched_cell_vertex_positions = np.array(list(cell_vertex_positions.values()))[matched_image_index]
matched_keys = np.sort(np.array(list(cell_vertex_positions.keys())))[matched_image_index]
matched_mesh_vertices = np.array(list(mesh_cell_vertex.values()))[cell_vertex_matching[0][np.where(cell_vertex_matching[1] == 0)[0]]]
matched_keys = np.sort(np.array(list(mesh_cell_vertex.keys())))[matched_mesh_index]
vertex_positions = topomesh.wisp_property('barycenter', 0).to_dict()
for i, v in enumerate(matched_mesh_vertices):
if not np.isnan(matched_cell_vertex_positions[i]).any():
vertex_positions[v] = coef * matched_cell_vertex_positions[i] + (1 - coef) * vertex_positions[v]
topomesh.update_wisp_property('barycenter', 0, vertex_positions)