Source code for tyssue.core.monolayer

"""Monolayer epithelium objects
"""

import logging

import pandas as pd
from scipy.spatial import cKDTree

from ..geometry.bulk_geometry import BulkGeometry
from .objects import Epithelium
from .sheet import Sheet

logger = logging.getLogger(name=__name__)


[docs]class Monolayer(Epithelium): """ 3D monolayer epithelium """ def __init__(self, name, datasets, specs=None, coords=None): super().__init__(name, datasets, specs, coords) self.vert_df["is_active"] = 1 self.cell_df["is_alive"] = 1 self.face_df["is_alive"] = 1 self.reset_topo() # BulkGeometry.update_all(self)
[docs] @classmethod def from_flat_sheet(cls, name, apical_sheet, specs, thickness=1): from ..generation import extrude datasets = extrude( apical_sheet.datasets, method="translation", vector=[0, 0, -thickness] ) mono = cls(name, datasets, specs) mono.reset_topo() return mono
[docs] def segment_index(self, segment, element): df = getattr(self, "{}_df".format(element)) return df[df["segment"] == segment].index
@property def lateral_faces(self): return self.segment_index("lateral", "face") @property def apical_faces(self): return self.segment_index("apical", "face") @property def basal_faces(self): return self.segment_index("basal", "face") @property def lateral_edges(self): return self.segment_index("lateral", "edge") @property def apical_edges(self): return self.segment_index("apical", "edge") @property def basal_edges(self): return self.segment_index("basal", "edge") @property def apical_verts(self): return self.segment_index("apical", "vert") @property def basal_verts(self): return self.segment_index("basal", "vert") @property def lateral_verts(self): return self.segment_index("lateral", "vert")
[docs] def get_sub_sheet(self, segment): """Returns a :class:`Sheet` object of the corresponding segment Parameters ---------- segment: str, the corresponding segment, wether 'apical' or 'basal' """ datasets = { element: self.datasets[element].loc[self.segment_index(segment, element)] for element in ["edge", "face", "vert"] } specs = {k: self.specs[k] for k in ["face", "edge", "vert", "settings"]} return Sheet(self.identifier + segment, datasets, specs)
[docs] def guess_vert_segment(self, vert): """Infers the vertex segment from its surrounding edges.""" v_edges = self.edge_df[self.edge_df["srce"] == vert] if v_edges.shape[0] == 0: logger.info("Vertex %d not found", vert) return if v_edges.shape[0] == 12: self.vert_df.loc[vert, ["segment"]] = "lateral" return intersect = {"apical", "basal"}.intersection(v_edges["segment"]) if len(intersect) == 2: logger.info("Segment of vertex %d could not be determined", vert) self.vert_df.loc[vert, ["segment"]] = "unknown" elif not intersect: self.vert_df.loc[vert, ["segment"]] = "lateral" else: # intersect is {"apical"} or {"basal"} (self.vert_df.loc[vert, ["segment"]],) = intersect
[docs] def guess_face_segment(self, face): """Infers the face segment.""" face_edges = self.edge_df[self.edge_df["face"] == face] if face_edges.shape[0] == 0: logger.info("face %d not found", face) v_segments = set(self.vert_df.loc[face_edges["srce"], "segment"]) if len(v_segments) == 2: self.face_df.loc[face, "segment"] = "lateral" elif len(v_segments) == 1: (new_segment,) = v_segments self.face_df.loc[face, "segment"] = new_segment
[docs]class MonolayerWithLamina(Monolayer): """ 3D monolayer epithelium with a lamina meshing """ def __init__(self, name, datasets, specs=None, coords=None): super().__init__(name, datasets, specs, coords) BulkGeometry.update_all(self) self.reset_index() from ..generation import subdivide_faces subdivided = subdivide_faces(self, self.basal_faces) for name, df in subdivided.items(): setattr(self, "{}_df".format(name), df) self.reset_index() self.reset_topo() subdiv_edges = self.edge_df[self.edge_df["subdiv"] == 1].index self.edge_df.loc[subdiv_edges, "segment"] = "basal" subdiv_verts = self.vert_df[self.vert_df["subdiv"] == 1].index self.vert_df.loc[subdiv_verts, "segment"] = "basal" self.vert_df.loc[subdiv_verts, "basal_shift"] = 0.0 self.vert_df.loc[subdiv_verts, "is_active"] = 1.0 subdiv_verts = self.vert_df[self.vert_df["subdiv"] == 1].index focal_adhesions = self.vert_df.loc[subdiv_verts] max_dist = self.edge_df.length.dropna().median() * 1.74 lamina_tree = cKDTree(focal_adhesions[self.coords].values) lamina_edges = pd.DataFrame( [[i, j] for i, j in lamina_tree.query_pairs(max_dist, eps=1e-3)], columns=["srce", "trgt"], ) lamina_edges.index.name = "edge" lamina_edges["srce"] = focal_adhesions.index[lamina_edges["srce"]] lamina_edges["trgt"] = focal_adhesions.index[lamina_edges["trgt"]] # place holder face and cell lamina_face = self.face_df.index.max() + 1 lamina_edges["face"] = lamina_face self.face_df = pd.concat( [self.face_df, self.face_df.iloc[0:0]], ignore_index=True ) self.face_df.loc[lamina_face, "is_alive"] = 0 lamina_cell = self.cell_df.index.max() + 1 lamina_edges["cell"] = lamina_cell self.cell_df = pd.concat( [self.cell_df, self.cell_df.iloc[0:0]], ignore_index=True ) self.cell_df.loc[lamina_cell, "is_alive"] = 0 lamina_edges.index += self.edge_df.index.max() + 1 lamina_edges["segment"] = "lamina" lamina_edges["subdiv"] = 0 self.edge_df = pd.concat([self.edge_df, lamina_edges], sort=True) self.reset_topo() BulkGeometry.update_all(self) @property def lamina_edges(self): return self.segment_index("lamina", "edge")