Reversible Network Reconnection Model

Attempt at implementing the RNR model as described in Okuda et al. 2012:

Reversible network reconnection model for simulating large deformation in dynamic tissue morphogenesis, Satoru Okuda, Yasuhiro Inoue, Mototsugu Eiraku, Yoshiki Sasai and Taiji Adachi Biomech Model Mechanobiol (2013) 12:627–644 DOI 10.1007/s10237-012-0430-7

The authors give 4 conditions which we detail and implement bellow.

Condition 1 - Center of a face

The center of a face is defined by the average position of the face’s edges midpoints, weighted by their lengths.

\[ \mathbf{r}_{\alpha} = \frac{\sum_{ij\alpha}\ell_{ij} (\mathbf{r}_i + \mathbf{r}_j)/2}{\sum_{ij\alpha}\ell_{ij}}\]
import numpy as np, pandas as pd
import ipyvolume as ipv
import matplotlib.pyplot as plt
%matplotlib inline

from tyssue import Epithelium
from tyssue import BulkGeometry, RNRGeometry
from tyssue import Sheet
from tyssue.config.geometry import bulk_spec
from tyssue.generation import three_faces_sheet
from tyssue.generation import extrude
from tyssue.draw import sheet_view, highlight_cells

from tyssue.topology.bulk_topology import IH_transition, HI_transition



draw_spec = {'face': {'visible': True}}




sheet = Sheet.planar_sheet_3d('sheet', 5, 5, 1, 1)
sheet.sanitize()
datasets = extrude(sheet.datasets, method='translation')

eptm = Epithelium('20faces_3D', datasets, bulk_spec())
RNRGeometry.update_all(eptm)
RNRGeometry.center(eptm)
RNRGeometry.update_all(eptm)


eptm.settings['threshold_length'] = 1e-4
print(eptm.Nf, eptm.Ne, eptm.Nv)
draw_spec['face']['color'] = eptm.face_df.area
draw_spec['face']['color_range'] = (0, 1)

ipv.clear()
fig, meshes = sheet_view(eptm, mode='3D', **draw_spec)
fig
93 414 70

I→H transition

IH transition in a bulk and a RNR

This produces a shape similar to the one studied by LM Escudero and collegues in their article.

e_1011 = 26
eptm.settings['threshold_length'] = 0.5

srce, trgt, face, cell = eptm.edge_df.loc[e_1011,
                                          ['srce', 'trgt',
                                           'face', 'cell']]

IH_transition(eptm, e_1011)
RNRGeometry.update_all(eptm)

highlight_cells(eptm, cell, reset_visible=True)
draw_spec['face']['color'] = eptm.face_df.area


ipv.clear()
fig, meshes = sheet_view(eptm, mode='3D', **draw_spec)
fig
cell 0 is already closed
cell 5 is already closed

H → I transition

eptm.Nv
71
eptm.active_verts.size
71
fa = 93


HI_transition(eptm, fa)
RNRGeometry.update_all(eptm)

highlight_cells(eptm, cell, reset_visible=False)
ipv.clear()
draw_spec['face']['color'] = eptm.face_df.area

fig, meshes = sheet_view(eptm, mode='3D', **draw_spec)
fig
cell 4 is already closed
cell 0 is already closed
cell 5 is already closed
cell 1 is already closed

Testing for I→H / H →I transition triggers

#eptm.settings['threshold_length'] = 1e-3
eptm.settings['threshold_length'] = eptm.edge_df.length.min()+1e-3
def find_rearangements(eptm):
    l_th = eptm.settings['threshold_length']
    up_num_sides = eptm.upcast_face(eptm.face_df['num_sides'])   
    shorts = eptm.edge_df[eptm.edge_df['length'] < l_th]
    non_triangular = up_num_sides[up_num_sides > 4 ].index
    edges_IH = set(shorts.index).intersection(non_triangular)

    max_f_length = shorts.groupby('face')['length'].apply(max)
    short_faces = max_f_length[max_f_length < l_th].index
    three_faces = eptm.face_df[eptm.face_df['num_sides'] == 3].index
    faces_HI = set(three_faces).intersection(short_faces)
    return edges_IH, faces_HI

find_rearangements(eptm)
({20, 21}, set())

Condition 3

This condition is satisfied if eptm.settings['threshold_length'] is well defined, i.e, small with respect to the unit length or the average edge length.

Condition 4

  • (i) Two edges never share two vertices simultaneously.

In our half-edge architecture, this is not as straight forward. But I think the condition can be reformulated as: Two edges from the same face never share two edges simultanously. I don’t know how to demonstrate this, but I think these are equivalent (to get two edges together, you need to “squeeze” one face between those two.

  • (ii) Two polygonal faces never share two or more edges simultaneously.

from tyssue.topology.base_topology import condition_4i, condition_4ii
condition_4i(eptm), condition_4ii(eptm)
(Int64Index([], dtype='int64', name='face'),
 array([], shape=(0, 2), dtype=int64))
eptm.settings['threshold_length'] = 0.5

IH_transition(eptm, eptm.edge_df.index[-1])
RNRGeometry.update_all(eptm)
draw_spec['face']['color'] = eptm.face_df.area

ipv.clear()
fig, meshes = sheet_view(eptm, mode='3D', **draw_spec)
fig
cell 0 is already closed
cell 5 is already closed
invalid = eptm.get_invalid()
assert np.alltrue(1 - invalid)
assert np.alltrue(eptm.edge_df['sub_vol'] > 0)