def octahedron_tetrahedra(side_length=15.): points = {} points[2] = np.array([1, 0, 0]) + 0.1 * np.random.rand(3) points[3] = np.array([0, 1, 0]) + 0.1 * np.random.rand(3) points[4] = np.array([-1, 0, 0]) + 0.1 * np.random.rand(3) points[5] = np.array([0, -1, 0]) + 0.1 * np.random.rand(3) points[6] = np.array([0, 0, 1]) + 0.1 * np.random.rand(3) points[7] = np.array([0, 0, -1]) + 0.1 * np.random.rand(3) tetrahedra = [] tetrahedra += [[2, 3, 4, 6]] tetrahedra += [[2, 4, 5, 6]] tetrahedra += [[2, 3, 4, 7]] tetrahedra += [[2, 4, 5, 7]] return tetrahedra_topomesh(tetrahedra, points)
def octahedron_tetrahedra(side_length=15.): points = {} points[2] = np.array([1,0,0]) + 0.1*np.random.rand(3) points[3] = np.array([0,1,0]) + 0.1*np.random.rand(3) points[4] = np.array([-1,0,0]) + 0.1*np.random.rand(3) points[5] = np.array([0,-1,0]) + 0.1*np.random.rand(3) points[6] = np.array([0,0,1]) + 0.1*np.random.rand(3) points[7] = np.array([0,0,-1]) + 0.1*np.random.rand(3) tetrahedra = [] tetrahedra += [[2,3,4,6]] tetrahedra += [[2,4,5,6]] tetrahedra += [[2,3,4,7]] tetrahedra += [[2,4,5,7]] return tetrahedra_topomesh(tetrahedra,points)
def compute_image_adjacency(self): """Compute the adjacency relationships between cells in the tissue image. By default, the DRACO adjacency complex is set to the cell_vertices tetrahedra (!!NOT A VALID CELL COMPLEX!!) !!STRONG RISK OF TOPOLOGICAL ERRORS IF DUALIZING AT THIS STAGE!! Updates: image_graph (PropertyGraph): adjacency graph connecting adjacent cells by edges image_cell_vertex (dict): cell vertices representing 4 co-adjacent cells by the point where they meet cell_layer (int): information whether the cell belong to the first layer of cells (L1), the second one (L2) or lower layers (0) layer_edge_topomesh (PropertyTopomesh): adjacency graphs restricted to the L1 and L2 layers layer_triangle_topomesh (PropertyTopomesh): adjacency triangles between L1 and L2 layers (**TO BE COMPLETED**) triangulation_topomesh (PropertyTopomesh): the tetrahedra representing adjacencies between cells Returns: None """ self.image_graph = graph_from_image( self.segmented_image, spatio_temporal_properties=["volume", "barycenter", "L1"], ignore_cells_at_stack_margins=False, property_as_real=True, ) self.image_labels = np.array(list(self.image_graph.vertices())) self.image_cell_volumes = array_dict( [self.image_graph.vertex_property("volume")[v] for v in self.image_labels], self.image_labels ) img_center = np.nanmean(self.image_graph.vertex_property("barycenter").values(), axis=0) self.positions = array_dict(self.image_graph.vertex_property("barycenter")) self.point_topomesh = vertex_topomesh(self.positions) img_analysis = SpatialImageAnalysis(self.segmented_image) exterior_cells = np.array(list(img_analysis.neighbors(1))) self.image_wall_surfaces = img_analysis.wall_areas(real=True) self.image_graph.add_vertex(1) for c in exterior_cells: self.image_graph.add_edge(1, c) for v in self.image_cell_vertex.keys(): self.image_cell_vertex[v] = self.image_cell_vertex[v] * self.resolution image_cell_vertex_tetrahedra = np.sort(self.image_cell_vertex.keys()) image_cell_vertex_tetrahedra = np.delete( image_cell_vertex_tetrahedra, np.where(image_cell_vertex_tetrahedra[:, 0] == 1)[0], axis=0 ) self.image_cell_vertex_topomesh = tetrahedra_topomesh(image_cell_vertex_tetrahedra, self.positions) self.triangulation_topomesh = deepcopy(self.image_cell_vertex_topomesh) truncated_image = self.segmented_image[:, :, :] truncated_image_graph = graph_from_image( truncated_image, spatio_temporal_properties=["barycenter", "L1"], background=1, ignore_cells_at_stack_margins=True, property_as_real=True, ) self.cell_layer = array_dict(np.zeros_like(self.positions.keys()), self.positions.keys()) for c in truncated_image_graph.vertices(): if c > 1 and truncated_image_graph.vertex_property("L1")[c]: self.cell_layer[c] = 1 for c in self.cell_layer.keys(): if c > 1 and self.cell_layer[c] == 1: for n in truncated_image_graph.neighbors(c): if n > 1 and self.cell_layer[n] != 1: self.cell_layer[n] = 2 self.point_topomesh.update_wisp_property( "layer", 0, self.cell_layer.values(list(self.point_topomesh.wisps(0))), list(self.point_topomesh.wisps(0)) ) self.layer_edge_topomesh = {} if (self.cell_layer.values() == 1).sum() > 1: L1_edges = np.array( [ [(c, n) for n in self.image_graph.neighbors(c) if n > 1 and self.cell_layer[n] == 1] for c in self.cell_layer.keys() if self.cell_layer[c] == 1 ] ) L1_edges = np.concatenate([e for e in L1_edges if len(e) > 0]) L1_edges = L1_edges[L1_edges[:, 1] > L1_edges[:, 0]] L1_edge_topomesh = edge_topomesh(L1_edges, self.positions) self.layer_edge_topomesh["L1"] = L1_edge_topomesh if (self.cell_layer.values() == 2).sum() > 1: L2_edges = np.array( [ [(c, n) for n in self.image_graph.neighbors(c) if n > 1 and self.cell_layer[n] == 2] for c in self.cell_layer.keys() if self.cell_layer[c] == 2 ] ) L2_edges = np.concatenate([e for e in L2_edges if len(e) > 0]) L2_edges = L2_edges[L2_edges[:, 1] > L2_edges[:, 0]] L2_edge_topomesh = edge_topomesh(L2_edges, self.positions) self.layer_edge_topomesh["L2"] = L2_edge_topomesh self.layer_triangle_topomesh = {} if (self.cell_layer.values() == 1).sum() > 1 and (self.cell_layer.values() == 2).sum() > 1: L1_L2_edges = np.array( [ [(c, n) for n in self.image_graph.neighbors(c) if n > 1 and self.cell_layer[n] in [1, 2]] for c in self.cell_layer.keys() if self.cell_layer[c] in [1, 2] ] ) L1_L2_edges = np.concatenate([e for e in L1_L2_edges if len(e) > 0]) L1_L2_edges = L1_L2_edges[L1_L2_edges[:, 1] > L1_L2_edges[:, 0]] L1_L2_additional_edges = np.array( [ [ (c, n) for n in np.unique( np.array(self.image_cell_vertex.keys())[ np.where(np.array(self.image_cell_vertex.keys()) == c)[0] ] ) if n > 1 and n != c and (n not in self.image_graph.neighbors(c)) and (self.cell_layer[n] in [1, 2]) ] for c in self.cell_layer.keys() if self.cell_layer[c] in [1, 2] ] ) L1_L2_additional_edges = np.concatenate([e for e in L1_L2_additional_edges if len(e) > 0]) L1_L2_additional_edges = L1_L2_additional_edges[L1_L2_additional_edges[:, 1] > L1_L2_additional_edges[:, 0]] self.layer_triangle_topomesh["L1_L2"] = triangle_topomesh( triangles_from_adjacency_edges(np.concatenate([L1_L2_edges, L1_L2_additional_edges])), self.positions )