%load_ext autoreload
%autoreload 2
%run nb_init.py
%matplotlib inline
/home/guillaume/Python/leg-joint
According to the Farhadifar et al. paper, in the case of a regular hexagonal latice, energy is given by:
$$ E = N\frac{K}{2} (A - A_0)^2 + N\frac{\Gamma}{2} L^2 + 6N\frac{\Lambda}{2}\ell $$In our model, the area dependant term is replaced by a volume term : $$ E = N\frac{K_v}{2} (V - V_0)^2 + N\frac{\Gamma}{2} L^2 + 3N\Lambda\ell $$
Here the $V = A(\rho - R_L) = Ah $ where $R_L$ is the lumen radius and $\rho$ the radius of the apical sheet of the epithelium. As they did, we define the adimentional contractility $\bar\Gamma = \Gamma/K_vA_0h_0^2$ and line tension $\bar\Lambda = \Lambda /K_v (A_0^{3/2}h_0^2)$, where $h_0$ is such that $V_0 = A_0h_0$.
As the epithelium is distributed over a cylinder, the radius of the cylinder determines the number of cells forming a ring around it, $ N_\perp $, so we have: $ \ell = \frac{2\pi}{N_\perp}\rho $ if the cells are aligned along the $z$ axis. The perimeter $L$ of a cell is equal to $6\ell$ and the area $A$ equals $(3\sqrt{3}/2)\ell^2$. We define the constant $\mu = 6\left(2/3\sqrt{3}\right)^{1/2}$, then $\ell = \frac{\mu}{6}A^{1/2}$ and $L^2 = \mu^2 A$.
The normalized energy $\bar E = E/NK_v(A_0h_0)^2$ then reads: $$ \bar E = \frac{1}{2} \left(\frac{V - V_0}{V_0}\right)^2
\bar E = \frac{1}{2} \left(\delta^3 - 1\right)^2
\bar E_{2D} = \frac{1}{2} (\delta^2 - 1)^2
$$
We can implement those functions rightaway:
mu = 6 * np.sqrt(2. / (3 * np.sqrt(3)))
def elasticity(delta):
return (delta**3 - 1 )**2 / 2.
def contractility(delta, gamma):
return gamma * mu**2 * delta**2 / 2.
def tension(delta, lbda):
return lbda * mu * delta / 2.
def isotropic_energy(delta, gamma, lbda):
energy = (elasticity(delta)
+ contractility(delta, gamma)
+ tension(delta, lbda))
return energy
def isotropic_energy_2D(delta, gamma, lbda):
elasticity = (delta**2 - 1)**2 / 2.
contractility = gamma * mu**2 * delta**2 / 2.
tension = lbda * mu * delta / 2.
return elasticity + contractility + tension
delta = np.linspace(0, 1.2, 200)
#aspects = np.logspace(-6, 0, 40, base=2)
fig, ax = plt.subplots(figsize=(6, 4))
ax.plot(delta, isotropic_energy_2D(delta, 0.04, 0.12), 'b-', lw=2, alpha=0.8, label='2D case')
ax.plot(delta, isotropic_energy(delta, 0.04, 0.12), 'k-', lw=2, alpha=0.8, label='3D case')
#for aspect in aspects:
# ax.plot(delta, isotropic_energy(delta, aspect, 0.04, 0.12), 'b-',
# label=(r'$R_L/R_0 = %.3e$' % aspect), alpha= aspect * 0.6)
ylbl = ax.set_ylabel(r'Normalized energy $\bar E$')
xlblb = ax.set_xlabel('')
xlblb = ax.set_xlabel(r'Scaling factor $\delta$')
ax.legend(loc='upper left')
fig.savefig(lj.data.get_image('isotropic_energy_vs_scaling.svg'))
/home/guillaume/anaconda/envs/python3/lib/python3.4/site-packages/matplotlib-1.4.x-py3.4-linux-x86_64.egg/matplotlib/figure.py:1644: UserWarning: This figure includes Axes that are not compatible with tight_layout, so its results might be incorrect. warnings.warn("This figure includes Axes that are not "
The ground state of the regular epithelium is attained when enregy is minimal with respect to $\delta$:
$$ \frac{\partial \bar E}{\partial \delta} = 0 $$That is (dropping the top bar notation):
$$ 3 \delta^2(\delta^3 - 1) + \mu^2\Gamma\delta + \frac{\mu\Lambda}{2} = 0 $$In 2D:
$$ 2 \delta(\delta^2 - 1) + \mu^2\Gamma\delta + \frac{\mu\Lambda}{2} = 0 $$Once again let's code this:
def isotropic_grad_poly(lbda, gamma):
grad_poly = [3, 0, 0,
-3,
mu**2 * gamma,
mu * lbda / 2.]
return grad_poly
def isotropic_grad(delta, lbda, gamma):
grad_poly = isotropic_grad_poly(lbda, gamma)
return np.polyval(grad_poly, delta)
def isotropic_grad_poly_2D(lbda, gamma):
grad_poly = [2, 0,
mu**2 * gamma - 2,
mu * lbda / 2.]
return grad_poly
def isotropic_grad_2D(delta, lbda, gamma):
grad_poly = isotropic_grad_poly_2D(lbda, gamma)
return np.polyval(grad_poly, delta)
## The (archetypal) case I simulations in the article are for
## the following values:
gamma_case1 = 0.04
lbda_case1 = 0.12
# We can plot the above function for a range of values for aspect
deltas = np.linspace(0, 1.1, 200)
fig, ax = plt.subplots(1, 1, figsize=(6.,4.))
grad = isotropic_grad(deltas, lbda_case1, gamma_case1)
line = ax.plot(deltas, grad, 'k-', alpha=0.8, lw=2, label='3D case')
grad2D = isotropic_grad_2D(deltas, lbda_case1, gamma_case1)
line = ax.plot(deltas, grad2D, 'b-', alpha=0.8, lw=2, label='2D case')
zero_x = ax.plot(deltas, np.zeros_like(deltas), 'k-')
ylbl = ax.set_ylabel(r'Isotropic gradient amplitude'
'$\partial E / \partial \delta$')
xlblb = ax.set_xlabel(r'Scaling factor $\delta$')
ax.legend(loc='upper left')
plt.draw()
fig.savefig(lj.data.get_image('isotropic_gradient_vs_scaling.svg'))
/home/guillaume/anaconda/envs/python3/lib/python3.4/site-packages/matplotlib-1.4.x-py3.4-linux-x86_64.egg/matplotlib/figure.py:1644: UserWarning: This figure includes Axes that are not compatible with tight_layout, so its results might be incorrect. warnings.warn("This figure includes Axes that are not "
In order for the apical junction to find a stable configuration, the energy must have a minimum as a function of $\delta$. We can look at several cases and deduce the necessary conditions on $\bar\Gamma$ and $\bar\Lambda$ for this to apply.
The tissue will behave as a soft network if the energy minimum for equilibrium volumes equal the initial volume ($\delta = 1$), and contractility and elasticity can compensate each over. There exist a minimum energy in this case if: $$ \mu^2 \Gamma \delta + \mu\Lambda / 2 < 0 $$ The boundary between soft and cristal-like network is given by the line $\Gamma = - 2 \Lambda / 2\mu$ in the $(\Gamma, \Lambda)$ plane.
To fix the correct conditions we have to look in the $(\Gamma, \Lambda)$ plane for real values of the gradient roots.
We can seek the maximum possible values of $\Gamma$ for a given $\Lambda$. We have: $$ \Gamma = - \frac{\Lambda}{2\mu\delta} + \frac{3}{\mu^2}\delta(1 - \delta^3) $$
$\Gamma$ is maximal with respect to $\delta$ if $$ \begin{align*} \frac{\partial \Gamma}{\partial \delta} = \frac{\Lambda}{2\mu\delta^2} + 3\frac{1 - 4\delta^3}{\mu^2} = 0\\ \Leftrightarrow -12\delta^5 + 3\delta^2 + \Lambda\mu / 2 = 0 \end{align*} $$
The phase space boundary for valid values of $\Gamma$ and $\Lambda$ is given by the values of $\Gamma$ for the roots of the above polynomial as a function of $\Lambda$.
If $\Lambda = 0$, this gives $\delta_m(\Lambda = 0) = 4^{-1/3}$ and $\Gamma_m(\Lambda = 0) \simeq 0.123$. With a similar reasoning for $\Lambda$, we have $\delta_m(\Gamma = 0) = (2 / 5)^{1/3}$ and $\Lambda_m(\Gamma = 0) \simeq 0.525$
We can solve numerically for the other values of $\Lambda$
### This function does a brute force search for the roots of
## the gradient in the lambda, gamma plane
def find_grad_roots(lbda, gamma):
p = isotropic_grad_poly(lbda, gamma)
roots = np.roots(p)
good_roots = np.real([r for r in roots if np.abs(r) == r])
np.sort(good_roots)
if len(good_roots) == 1:
return good_roots
elif len(good_roots) > 1:
return good_roots[0]
else:
return np.nan
def find_boundary_roots(lbda):
delta_poly = [-12, 0, 0, 3, 0, lbda * mu / 2]
roots = np.roots(delta_poly)
good_roots = np.real([r for r in roots if (np.abs(r) == r) and (0 < r < 1)])
np.sort(good_roots)
return good_roots[0]
def get_boundary_gamma(lbda):
lbda = np.atleast_1d(lbda)
dm = np.array([find_boundary_roots(l) for l in lbda])
gamma = -lbda/(2 * mu * dm) + 3 * dm * (1 - dm**3) / mu**2
return gamma
### Compute the boundary line
lbda_max = 6 * (2 / 5.)**(2/3.) * 0.6 / mu
gamma_max = 3 * 4**(-1 / 3.) * 0.75 / mu**2
b_lbdas = np.linspace(0, lbda_max, 100)
b_gammas = get_boundary_gamma(b_lbdas)
print('''Maximum value for Lambda: %.3f \n'''
'''Maximum value for Gamma: %.3f''' % (lbda_max, gamma_max))
Maximum value for Lambda: 0.525 Maximum value for Gamma: 0.102
### Compute the value of delta over a grid in the (Lambda, Gamma) plane
grid_size = 128
lbdas, gammas = np.meshgrid(np.linspace(0, lbda_max * 1.1, grid_size),
np.linspace(0, gamma_max * 1.5, grid_size))
roots = []
for l, g in zip(lbdas.ravel(), gammas.ravel()):
roots.append(find_grad_roots(l, g))
roots = np.array(roots).reshape(gammas.shape)
### 2D case
gammas_2D = np.linspace(0, 2/mu**2, 20)
lambdas_max_2D = ((4 - 2 * gammas_2D * mu**2) / 3.)**(3./2.) / mu
### Plot everything
fig, ax = plt.subplots()
roots[np.isnan(roots)] = 0.5
lbdas, gammas = np.meshgrid(np.linspace(0, lbda_max * 1.1, grid_size), np.linspace(0, gamma_max * 1.5, grid_size))
contour_set = ax.contourf(lbdas, gammas, roots.clip(0.5, 1), 256, cmap='gray')
fig.colorbar(contour_set, ticks=[0.5, 0.6, 0.7, 0.8, 0.9, 1.])
boundary = ax.plot(b_lbdas, b_gammas, 'g-', lw=3, alpha=0.8, label='3D case')
boundary2D = ax.plot(lambdas_max_2D, gammas_2D, 'b-',
lw=3, alpha=0.8, label='2D case')
ax.plot(lbda_case1, gamma_case1, 'ko')
ax.set_xlabel(r'Line tension $\bar\Lambda$')
ax.set_ylabel(r'Contractility $\bar\Gamma$')
ax.set_title('Values of $\delta$')
ax.legend(loc='upper right')
fig.savefig(lj.data.get_image('phase_space_boundaries.svg'))
/home/guillaume/anaconda/envs/python3/lib/python3.4/site-packages/matplotlib-1.4.x-py3.4-linux-x86_64.egg/matplotlib/figure.py:1644: UserWarning: This figure includes Axes that are not compatible with tight_layout, so its results might be incorrect. warnings.warn("This figure includes Axes that are not "
We can now get the values of the optimal scaling $\delta_o$ and of the ground state energy $E_0$
with a simple root finding on the isotropic_grad
function:
delta_o = find_grad_roots(lbda_case1, gamma_case1)
print("Optimum scaling factor = %.3f" % delta_o)
ground_energy = isotropic_energy(delta_o, gamma_case1, lbda_case1)
print("Ground energy = %.3f" % ground_energy)
Optimum scaling factor = 0.887 Ground energy = 0.462
Let's note $A_i$ and $\rho_i$ the initial area and radius, before relaxation, and $A_f, \rho_f$ the same variables after the isotropic relaxation is applied. We now want to multiply all the distances by a factor $c$ such that $h_fA_f = \delta_o^3h_0A_0$, with $\rho_f = c\rho_i$ and $A_f = c^2A_i$.
By noting $\delta_i = h_i / h_0$, we simply have $c = \delta_o / \delta_i$
We now have the two phase space boundaries given by Faradhifar on figure 1. When we pass to the simulation we'll use all that to ensure that optimisation will converge and that we start the simultations close to the ground state.
In order to find the local energy minimum, as shown below, we use a conjugate gradient method
(namely the fmin_lbfgs
algorithm from SciPy). So we need to compute said gradient at each junction vertex that concur to the optimization.
In order to compute the local minimum of the energy, we calculate its gradient at junction vertex $i$ whose position in the 3D space is defined by the vector $\mathbf{r_i}$ pointing from the coordinate system's origin. An edge between two vertices is noted $\mathbf{r_{ij}} = \mathbf{r_j} - \mathbf{r_i}$. The coefficients noted $c_{ij}$ correspond to the terms of the graph's adjacency matrix, such that they are equal to 1 if an edge exists between vertices $i$ and $j$, and 0 otherwise.
$$ \begin{aligned} \mathbf{\nabla_i} E &= (\frac{\partial E}{\partial x}, \frac{\partial E}{\partial y}, \frac{\partial E}{\partial z}) \\ \mathbf{\nabla_i} E &= \sum_\alpha \left(K (V_\alpha - V_0) \mathbf{\nabla_i} V_\alpha + \Gamma L_\alpha \mathbf{\nabla_i} L_\alpha \right)c_{i \alpha} + \sum_i \Lambda_{ij} \mathbf{\nabla_i} \ell_{ij}c_{ij} \end{aligned} $$We have $$ \begin{aligned} \mathbf{\nabla_i}\ell_{ij} &= \frac{\mathbf{r}{ij}}{\ell{ij}}c_{ij}\ \mathbf{\nabla_i}L_\alpha &= \sum_{kn} \mathbf{\nabla_i} \ell_{kn} c_{\alpha k} c_{\alpha n} = \sum_{j} \mathbf{\nabla_i}\ell_{ij} c_{ij} c_{\alpha i} c_{\alpha j} = \sum_{j} \frac{\mathbf{r_{ij}}}{\ell_{ij}}c_{ij}c_{\alpha i} c_{\alpha j}\ \mathbf{\nabla_i}V_{\alpha} &= \sum_{km}\mathbf{\nabla_i}V_{\alpha km} c_{\alpha k}c_{\alpha m}c_{km} = \sum_{km} \mathbf{\nabla_i}h_\alpha A_{\alpha km} c_{\alpha k}c_{\alpha m}c_{km} = A_\alpha \mathbf{\nabla_i}h_\alpha + h_\alpha \sum_{km} \mathbf{\nabla_i} A_{\alpha km}c_{\alpha k} c_{\alpha m}c_{km}\ \mathbf{\nabla_i}V_{\alpha} &= \frac{h_\alpha}{2} \sum_{km}\mathbf{u}{\alpha km} \times \frac{\mathbf{r}{km}}{\nu}c_{\alpha k}c_{\alpha m}c_{km}
\end{aligned} $$
With the normal perpendicular to the $(\mathbf{r_k}, \mathbf{r_m})$ plane noted:
$$ \mathbf{u}_{\alpha km} = \frac{\mathbf{r}_{\alpha k} \times \mathbf{r}_{\alpha m}}{||\mathbf{r}_{\alpha k} \times \mathbf{r}_{\alpha m}||} $$%pdb
Automatic pdb calling has been turned ON
def draw_xz_cut(eptm):
pos = gt.group_vector_property([eptm.z, eptm.x])
front = eptm.is_cell_vert.copy()
front.a = eptm.y.a > 0
is_ctoj_edge = eptm.is_junction_edge.copy()
is_ctoj_edge.a = 1 - eptm.is_junction_edge.a
eptm.graph.set_vertex_filter(front)
gt.graph_draw(eptm.graph, pos=pos,
vertex_fill_color=eptm.is_cell_vert,
edge_color=is_ctoj_edge,
vorder=eptm.y,
inline=True)
eptm.graph.set_vertex_filter(None)
## Epithelium instantiation
eptm = lj.Epithelium(#graphXMLfile=lj.data.initial_graph_xml(),
save_dir='saved_graphs',
identifier='tuto',
copy=True)
## Scaling so that we start at global epithelium
#eptm.isotropic_relax()
draw_xz_cut(eptm)
2015-04-08 11:56:30,271 -leg_joint.epithelium.epithelium -__init__ -- INFO -Instanciating epithelium tuto 2015-04-08 11:56:30,273 -leg_joint.epithelium.epithelium -__init__ -- INFO -Created new graph 2015-04-08 11:56:30,333 -leg_joint.epithelium.generation -reorient_edges -- INFO -filpped 391 edges 2015-04-08 11:56:30,445 -leg_joint.epithelium.epithelium -__init__ -- INFO -Update geometry 2015-04-08 11:56:30,513 -leg_joint.epithelium.epithelium -__init__ -- INFO -Initial cells 2015-04-08 11:56:30,515 -leg_joint.epithelium.epithelium -__init__ -- INFO -Initial junctions 2015-04-08 11:56:30,730 -leg_joint.epithelium.epithelium -__init__ -- INFO -Isotropic relaxation
eptm.udf_atoi['dz'].index
MultiIndex(levels=[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, ...], [1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23, 24, 25, 27, 28, 30, 31, 33, 34, 36, 37, 39, 40, 42, 43, 45, 46, 49, 50, 52, 53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 72, 73, 75, 76, 78, 79, 81, 82, 84, 85, 87, 88, 90, 91, 93, 94, 97, 98, 100, 101, 103, 104, 106, 107, 109, 110, 112, 113, 115, 116, 118, 119, 120, 121, 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 145, 146, 148, 149, ...]], labels=[[0, 0, 0, 3, 3, 3, 6, 6, 6, 9, 9, 9, 12, 12, 12, 15, 15, 15, 18, 18, 18, 21, 21, 21, 26, 26, 26, 26, 26, 29, 29, 29, 29, 29, 32, 32, 32, 32, 32, 35, 35, 35, 35, 35, 38, 38, 38, 38, 38, 41, 41, 41, 41, 41, 44, 44, 44, 44, 44, 47, 47, 47, 47, 47, 48, 48, 48, 48, 48, 51, 51, 51, 51, 51, 54, 54, 54, 54, 54, 57, 57, 57, 57, 57, 60, 60, 60, 60, 60, 63, 63, 63, 63, 63, 66, 66, 66, 66, 66, 69, ...], [0, 15, 16, 1, 2, 18, 3, 4, 20, 5, 6, 22, 7, 8, 24, 9, 10, 26, 11, 12, 28, 13, 14, 30, 0, 1, 17, 18, 32, 2, 3, 19, 20, 34, 4, 5, 21, 22, 36, 6, 7, 23, 24, 38, 8, 9, 25, 26, 40, 10, 11, 27, 28, 42, 12, 13, 29, 30, 44, 14, 15, 16, 31, 46, 16, 17, 32, 47, 48, 18, 19, 33, 34, 50, 20, 21, 35, 36, 52, 22, 23, 37, 38, 54, 24, 25, 39, 40, 56, 26, 27, 41, 42, 58, 28, 29, 43, 44, 60, 30, ...]], names=['source', 'target'])
tri_graph, faces = lj.topology.topology.get_faces(eptm.graph, as_array=False)
import pandas as pd
tix_aij = pd.Index(faces, name='aij')
tix_aij[:2]
Index([<PropertyMap object with key type 'Vertex' and value type 'int32_t', for Graph 0x7fcf606237b8, at 0x7fcf606234e0, with values:\n[ 0 1 25]>, <PropertyMap object with key type 'Vertex' and value type 'int32_t', for Graph 0x7fcf606237b8, at 0x7fcf60623278, with values:\n[ 0 23 24]>], dtype='object')
np.bincount(eptm.tdf_cell._ix)
array([3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 0, 0, 6, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3, 0, 0, 3])
eptm.graph
<Graph object, directed, with 408 vertices and 1176 edges, edges filtered by (<PropertyMap object with key type 'Edge' and value type 'bool', for Graph 0x7fcf3ef64da0, at 0x7fcf5c138240, with values: [1 1 1 ..., 1 1 1]>, False), vertices filtered by (<PropertyMap object with key type 'Vertex' and value type 'bool', for Graph 0x7fcf3ef64da0, at 0x7fcf3ef5dcc0, with values: [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]>, False) at 0x7fcf3ef64da0>
eptm.triangles_array
array([[ 0, 1, 25], [ 0, 23, 24], [ 0, 24, 25], ..., [405, 381, 382], [405, 381, 404], [405, 382, 406]])
lj.epithelium.generation.reorient_edges(eptm.graph, eptm.is_cell_vert, eptm.is_junction_edge)
draw_xz_cut(eptm)
2015-04-08 10:30:43,810 -leg_joint.epithelium.generation -reorient_edges -- INFO -filpped 391 edges
%pdb
Automatic pdb calling has been turned ON
## eptm.isotropic_relax() ## mixes the edges
eptm.update_pmaps() ## mixes the edges
#
draw_xz_cut(eptm)
To do so, we use graph-tool's filtering mechanism. We use two attributes of the Epithelium
object:
is_cell_vert
and is_alive
, which are graph-tools boolean PropertyMaps
.
## Create a filter with only the 'live' cell vertices
vfilt = eptm.is_cell_vert.copy()
vfilt.a *= eptm.is_alive.a
## Filtering
eptm.graph.set_vertex_filter(vfilt)
area = eptm.area.fa.mean()
height = eptm.height.fa.mean()
eptm.delta_o = eptm.find_grad_roots()
print('Square root of the ratio between the prefered area\n'
'and the actual average area: %.6f\n'
% (np.sqrt(area / eptm.params["prefered_area"])))
print('Ratio between the prefered height\n'
'and the actual average height: %.6f\n'
% (height / eptm.params['prefered_height']))
print('Scaling factor with respect to elastic volume equilibrium: %.6f\n'
% eptm.delta_o)
# Remove the filter
eptm.graph.set_vertex_filter(None)
Square root of the ratio between the prefered area and the actual average area: 0.870634 Ratio between the prefered height and the actual average height: 0.886593 Scaling factor with respect to elastic volume equilibrium: 0.886593
All three numbers should be equal by definition
The graph bellow corresponds to the analytical computations above
fig, ax = plt.subplots(figsize=(6, 4))
lbda = eptm.paramtree.relative_dic['line_tension']
gamma = eptm.paramtree.relative_dic['contractility']
deltas = np.linspace(0.4, 1.2)
ax.plot(deltas, eptm.isotropic_energy(deltas), 'k-',
label='Analytical total')
ax.plot(eptm.delta_o, eptm.isotropic_energy(eptm.delta_o), 'ro')
ax.set_ylabel('Normalized energy')
ax.set_xlabel('Scaling');
/home/guillaume/anaconda/envs/python3/lib/python3.4/site-packages/matplotlib-1.4.x-py3.4-linux-x86_64.egg/matplotlib/figure.py:1644: UserWarning: This figure includes Axes that are not compatible with tight_layout, so its results might be incorrect. warnings.warn("This figure includes Axes that are not "
eptm.calc_energy(full_output=False) / eptm.norm_factor
56.199266753480046
deltas = np.linspace(0.5, 1.2, 20)
fig, ax = plt.subplots(figsize=(5, 8))
lbda = eptm.paramtree.relative_dic['line_tension']
gamma = eptm.paramtree.relative_dic['contractility']
ax.plot(deltas, eptm.isotropic_energy(deltas), 'k-',
label='Analytical total')
ax.plot(eptm.delta_o, eptm.isotropic_energy(eptm.delta_o), 'ro')
ax.plot(deltas, elasticity(deltas), 'b-',
label='Analytical volume elasticity')
ax.plot(deltas, contractility(deltas, gamma), c='orange', ls='-',
label='Analytical contractility')
ax.plot(deltas, tension(deltas, lbda), 'g-',
label='Analytical line tension')
ax.set_xlabel(r'Isotropic scaling $\delta$')
ax.set_ylabel(r'Isotropic energie $\bar E$')
#eptm.update_rhotheta()
area0 = eptm.params['prefered_area']
h_0 = eptm.params['prefered_height']
## Create a filter with only the 'live' cell vertices
vfilt = eptm.is_cell_vert.copy()
vfilt.a *= eptm.is_alive.a
### Cells only area and height
eptm.graph.set_vertex_filter(vfilt)
area_avg = eptm.area.fa.mean()
rho_avg = eptm.rho.fa.mean()
eptm.graph.set_vertex_filter(None)
### Set height and area to height0 and area0
scale = (area0 / area_avg)**0.5
eptm.scale(scale)
eptm.rho_lumen = rho_avg * scale - h_0
eptm.update_geometry()
lj.epithelium.generation.reorient_edges(eptm.graph, eptm.is_cell_vert, eptm.is_junction_edge)
energy = eptm.calc_energy()
norm = (eptm.params['prefered_area']**2
* eptm.params['prefered_height']**2
* eptm.params['vol_elasticity']
* (eptm.is_cell_vert.a * eptm.is_alive.a).sum())
cell = eptm.graph.vertex(60)
energies = np.zeros((deltas.size, 3))
#scales = np.linspace(0.5, 1.2, 20) / eptm.delta_o
for n, delta in enumerate(deltas):
eptm.scale(delta)
El, Ec, Ev = eptm.calc_energy(full_output=True)
energies[n, :] = [Ev.sum(), El.sum(), Ec.sum()]
eptm.scale(1 / delta)
eptm.isotropic_relax()
energies = np.array(energies) / norm
ax.plot(deltas, energies[:, 0], 'bo:', lw=2, alpha=0.8,
label='Computed volume elasticity')
ax.plot(deltas, energies[:, 1], 'go:', lw=2, alpha=0.8,
label='Computed line tension')
ax.plot(deltas, energies[:, 2], ls=':',
marker='o', c='orange', label='Computed contractility')
ax.plot(deltas, energies.sum(axis=1), 'ko:', lw=2, alpha=0.8,
label='Computed total')
ax.legend(loc='upper left', fontsize=10)
ax.set_ylim(0, 1.2)
plt.savefig(lj.data.get_image('scaling_comparison.svg'))
print(eptm.delta_o, deltas[energies.sum(axis=1).argmin()] * eptm.delta_o)
0.886592687387 0.737271813722
/home/guillaume/anaconda/envs/python3/lib/python3.4/site-packages/matplotlib-1.4.x-py3.4-linux-x86_64.egg/matplotlib/figure.py:1644: UserWarning: This figure includes Axes that are not compatible with tight_layout, so its results might be incorrect. warnings.warn("This figure includes Axes that are not "
Note that at initialisation time, we also
invoked the isotropic_relax
method,
and we start with an hexagonal lattice, so we should be fairly close to
the ground state energy, except from the cells closer to edges along the $z$ axis.
lj.epithelium.generation.reorient_edges(eptm.graph, eptm.is_cell_vert, eptm.is_junction_edge)
eptm.scale(2)
pos = gt.group_vector_property([eptm.z, eptm.x])
front = eptm.is_cell_vert.copy()
front.a = eptm.y.a > 0
is_ctoj_edge = eptm.is_junction_edge.copy()
is_ctoj_edge.a = 1 - eptm.is_junction_edge.a
eptm.graph.set_vertex_filter(front)
gt.graph_draw(eptm.graph, pos=pos, vertex_fill_color=eptm.is_cell_vert,
edge_color=is_ctoj_edge, vorder=eptm.y, inline=True)
eptm.graph.set_vertex_filter(None)
#eptm.isotropic_relax()
for src, idx in eptm.edge_df.index:
print(src, idx)
0 1 0 23 0 25 0 24 1 2 1 25 2 27 3 4 3 27 3 28 3 2 4 5 4 28 5 30 6 7 6 31 6 30 6 5 7 8 7 31 8 33 9 10 9 33 9 34 9 8 10 11 10 34 11 36 12 13 12 37 12 36 12 11 13 14 13 37 14 39 15 16 15 40 15 39 15 14 16 17 16 40 17 42 18 19 18 43 18 42 18 17 19 20 19 43 20 45 21 22 21 46 21 45 21 20 22 23 22 46 23 24 24 25 24 71 25 49 26 50 26 27 26 49 26 1 26 2 26 25 27 50 27 28 28 52 29 53 29 52 29 30 29 4 29 5 29 28 30 53 30 31 31 55 32 55 32 56 32 33 32 7 32 8 32 31 33 56 33 34 34 58 35 59 35 58 35 36 35 10 35 11 35 34 36 59 36 37 37 61 38 61 38 62 38 39 38 13 38 14 38 37 39 40 39 62 40 64 41 42 41 65 41 64 41 16 41 17 41 40 42 43 42 65 43 67 44 68 44 45 44 67 44 19 44 20 44 43 45 46 45 68 46 70 47 71 47 70 47 22 47 23 47 24 47 46 48 49 48 71 48 73 48 72 48 24 48 25 49 50 49 73 50 75 51 52 51 75 51 76 51 27 51 28 51 50 52 53 52 76 53 78 54 55 54 79 54 78 54 30 54 31 54 53 55 56 55 79 56 81 57 58 57 81 57 82 57 33 57 34 57 56 58 59 58 82 59 84 60 61 60 85 60 84 60 36 60 37 60 59 61 62 61 85 62 87 63 64 63 88 63 87 63 39 63 40 63 62 64 65 64 88 65 90 66 67 66 91 66 90 66 42 66 43 66 65 67 68 67 91 68 93 69 70 69 94 69 93 69 45 69 46 69 68 70 71 70 94 71 72 72 73 72 119 73 97 74 98 74 75 74 97 74 49 74 50 74 73 75 98 75 76 76 100 77 101 77 100 77 78 77 52 77 53 77 76 78 101 78 79 79 103 80 103 80 104 80 81 80 55 80 56 80 79 81 104 81 82 82 106 83 107 83 106 83 84 83 58 83 59 83 82 84 107 84 85 85 109 86 109 86 110 86 87 86 61 86 62 86 85 87 88 87 110 88 112 89 90 89 113 89 112 89 64 89 65 89 88 90 91 90 113 91 115 92 116 92 93 92 115 92 67 92 68 92 91 93 94 93 116 94 118 95 119 95 118 95 70 95 71 95 72 95 94 96 121 96 120 96 97 96 119 96 72 96 73 97 98 97 121 98 123 99 123 99 124 99 100 99 75 99 76 99 98 100 124 100 101 101 126 102 127 102 126 102 103 102 78 102 79 102 101 103 127 103 104 104 129 105 129 105 130 105 106 105 81 105 82 105 104 106 130 106 107 107 132 108 133 108 132 108 109 108 84 108 85 108 107 109 133 109 110 110 135 111 136 111 112 111 135 111 87 111 88 111 110 112 136 112 113 113 138 114 139 114 138 114 115 114 90 114 91 114 113 115 116 115 139 116 141 117 142 117 118 117 141 117 93 117 94 117 116 118 142 118 119 119 120 120 121 120 167 121 145 122 123 122 146 122 145 122 97 122 98 122 121 123 124 123 146 124 148 125 126 125 149 125 148 125 100 125 101 125 124 126 127 126 149 127 151 128 129 128 151 128 152 128 103 128 104 128 127 129 130 129 152 130 154 131 132 131 155 131 154 131 106 131 107 131 130 132 133 132 155 133 157 134 135 134 157 134 158 134 109 134 110 134 133 135 136 135 158 136 160 137 138 137 161 137 160 137 112 137 113 137 136 138 139 138 161 139 163 140 141 140 164 140 163 140 115 140 116 140 139 141 142 141 164 142 166 143 167 143 166 143 118 143 119 143 120 143 142 144 169 144 168 144 145 144 167 144 120 144 121 145 146 145 169 146 171 147 171 147 172 147 148 147 123 147 124 147 146 148 172 148 149 149 174 150 175 150 174 150 151 150 126 150 127 150 149 151 175 151 152 152 177 153 177 153 178 153 154 153 129 153 130 153 152 154 178 154 155 155 180 156 181 156 180 156 157 156 132 156 133 156 155 157 181 157 158 158 183 159 184 159 160 159 183 159 135 159 136 159 158 160 184 160 161 161 186 162 187 162 186 162 163 162 138 162 139 162 161 163 164 163 187 164 189 165 190 165 166 165 189 165 141 165 142 165 164 166 190 166 167 167 168 168 169 168 215 169 193 170 171 170 194 170 193 170 145 170 146 170 169 171 172 171 194 172 196 173 174 173 197 173 196 173 148 173 149 173 172 174 175 174 197 175 199 176 177 176 199 176 200 176 151 176 152 176 175 177 178 177 200 178 202 179 180 179 203 179 202 179 154 179 155 179 178 180 181 180 203 181 205 182 183 182 205 182 206 182 157 182 158 182 181 183 184 183 206 184 208 185 186 185 209 185 208 185 160 185 161 185 184 186 187 186 209 187 211 188 189 188 212 188 211 188 163 188 164 188 187 189 190 189 212 190 214 191 215 191 214 191 166 191 167 191 168 191 190 192 217 192 216 192 193 192 215 192 168 192 169 193 194 193 217 194 219 195 219 195 220 195 196 195 171 195 172 195 194 196 220 196 197 197 222 198 223 198 222 198 199 198 174 198 175 198 197 199 223 199 200 200 225 201 225 201 226 201 202 201 177 201 178 201 200 202 226 202 203 203 228 204 229 204 228 204 205 204 180 204 181 204 203 205 229 205 206 206 231 207 232 207 208 207 231 207 183 207 184 207 206 208 232 208 209 209 234 210 235 210 234 210 211 210 186 210 187 210 209 211 212 211 235 212 237 213 238 213 214 213 237 213 189 213 190 213 212 214 238 214 215 215 216 216 217 216 263 217 241 218 242 218 219 218 241 218 193 218 194 218 217 219 242 219 220 220 244 221 245 221 244 221 222 221 196 221 197 221 220 222 245 222 223 223 247 224 247 224 248 224 225 224 199 224 200 224 223 225 248 225 226 226 250 227 251 227 250 227 228 227 202 227 203 227 226 228 251 228 229 229 253 230 253 230 254 230 231 230 205 230 206 230 229 231 232 231 254 232 256 233 234 233 257 233 256 233 208 233 209 233 232 234 235 234 257 235 259 236 260 236 237 236 259 236 211 236 212 236 235 237 238 237 260 238 262 239 263 239 262 239 214 239 215 239 216 239 238 240 241 240 263 240 265 240 264 240 216 240 217 241 242 241 265 242 267 243 244 243 267 243 268 243 219 243 220 243 242 244 245 244 268 245 270 246 247 246 271 246 270 246 222 246 223 246 245 247 248 247 271 248 273 249 250 249 273 249 274 249 225 249 226 249 248 250 251 250 274 251 276 252 253 252 277 252 276 252 228 252 229 252 251 253 254 253 277 254 279 255 256 255 280 255 279 255 231 255 232 255 254 256 257 256 280 257 282 258 259 258 283 258 282 258 234 258 235 258 257 259 260 259 283 260 285 261 262 261 286 261 285 261 237 261 238 261 260 262 263 262 286 263 264 264 265 264 311 265 289 266 290 266 267 266 289 266 241 266 242 266 265 267 290 267 268 268 292 269 293 269 292 269 270 269 244 269 245 269 268 270 293 270 271 271 295 272 295 272 296 272 273 272 247 272 248 272 271 273 296 273 274 274 298 275 299 275 298 275 276 275 250 275 251 275 274 276 299 276 277 277 301 278 301 278 302 278 279 278 253 278 254 278 277 279 280 279 302 280 304 281 282 281 305 281 304 281 256 281 257 281 280 282 283 282 305 283 307 284 308 284 285 284 307 284 259 284 260 284 283 285 286 285 308 286 310 287 311 287 310 287 262 287 263 287 264 287 286 288 313 288 312 288 289 288 311 288 264 288 265 289 290 289 313 290 315 291 315 291 316 291 292 291 267 291 268 291 290 292 316 292 293 293 318 294 319 294 318 294 295 294 270 294 271 294 293 295 319 295 296 296 321 297 321 297 322 297 298 297 273 297 274 297 296 298 322 298 299 299 324 300 325 300 324 300 301 300 276 300 277 300 299 301 325 301 302 302 327 303 328 303 304 303 327 303 279 303 280 303 302 304 328 304 305 305 330 306 331 306 330 306 307 306 282 306 283 306 305 307 308 307 331 308 333 309 334 309 310 309 333 309 285 309 286 309 308 310 334 310 311 311 312 312 313 312 359 313 337 314 315 314 338 314 337 314 289 314 290 314 313 315 316 315 338 316 340 317 318 317 341 317 340 317 292 317 293 317 316 318 319 318 341 319 343 320 321 320 343 320 344 320 295 320 296 320 319 321 322 321 344 322 346 323 324 323 347 323 346 323 298 323 299 323 322 324 325 324 347 325 349 326 327 326 349 326 350 326 301 326 302 326 325 327 328 327 350 328 352 329 330 329 353 329 352 329 304 329 305 329 328 330 331 330 353 331 355 332 333 332 356 332 355 332 307 332 308 332 331 333 334 333 356 334 358 335 359 335 358 335 310 335 311 335 312 335 334 336 361 336 360 336 337 336 359 336 312 336 313 337 338 337 361 338 363 339 363 339 364 339 340 339 315 339 316 339 338 340 364 340 341 341 366 342 367 342 366 342 343 342 318 342 319 342 341 343 367 343 344 344 369 345 369 345 370 345 346 345 321 345 322 345 344 346 370 346 347 347 372 348 373 348 372 348 349 348 324 348 325 348 347 349 373 349 350 350 375 351 376 351 352 351 375 351 327 351 328 351 350 352 376 352 353 353 378 354 379 354 378 354 355 354 330 354 331 354 353 355 356 355 379 356 381 357 382 357 358 357 381 357 333 357 334 357 356 358 382 358 359 359 360 360 361 360 407 361 385 362 363 362 386 362 385 362 337 362 338 362 361 363 364 363 386 364 388 365 366 365 389 365 388 365 340 365 341 365 364 366 367 366 389 367 391 368 369 368 391 368 392 368 343 368 344 368 367 369 370 369 392 370 394 371 372 371 395 371 394 371 346 371 347 371 370 372 373 372 395 373 397 374 375 374 397 374 398 374 349 374 350 374 373 375 376 375 398 376 400 377 378 377 401 377 400 377 352 377 353 377 376 378 379 378 401 379 403 380 381 380 404 380 403 380 355 380 356 380 379 381 382 381 404 382 406 383 407 383 406 383 358 383 359 383 360 383 382 384 385 384 407 384 360 384 361 385 386 387 388 387 363 387 364 387 386 388 389 390 391 390 366 390 367 390 389 391 392 393 394 393 369 393 370 393 392 394 395 396 397 396 372 396 373 396 395 397 398 399 400 399 375 399 376 399 398 400 401 402 403 402 378 402 379 402 401 403 404 405 406 405 381 405 382 405 404 406 407
for e in eptm.graph.edges():
print(e)
(0, 1) (0, 23) (0, 25) (0, 24) (1, 2) (1, 25) (2, 27) (3, 4) (3, 27) (3, 28) (3, 2) (4, 5) (4, 28) (5, 30) (6, 7) (6, 31) (6, 30) (6, 5) (7, 8) (7, 31) (8, 33) (9, 10) (9, 33) (9, 34) (9, 8) (10, 11) (10, 34) (11, 36) (12, 13) (12, 37) (12, 36) (12, 11) (13, 14) (13, 37) (14, 39) (15, 16) (15, 40) (15, 39) (15, 14) (16, 17) (16, 40) (17, 42) (18, 19) (18, 43) (18, 42) (18, 17) (19, 20) (19, 43) (20, 45) (21, 22) (21, 46) (21, 45) (21, 20) (22, 23) (22, 46) (23, 24) (24, 25) (24, 71) (25, 49) (26, 50) (26, 27) (26, 49) (26, 1) (26, 2) (26, 25) (27, 50) (27, 28) (28, 52) (29, 53) (29, 52) (29, 30) (29, 4) (29, 5) (29, 28) (30, 53) (30, 31) (31, 55) (32, 55) (32, 56) (32, 33) (32, 7) (32, 8) (32, 31) (33, 56) (33, 34) (34, 58) (35, 59) (35, 58) (35, 36) (35, 10) (35, 11) (35, 34) (36, 59) (36, 37) (37, 61) (38, 61) (38, 62) (38, 39) (38, 13) (38, 14) (38, 37) (39, 40) (39, 62) (40, 64) (41, 42) (41, 65) (41, 64) (41, 16) (41, 17) (41, 40) (42, 43) (42, 65) (43, 67) (44, 68) (44, 45) (44, 67) (44, 19) (44, 20) (44, 43) (45, 46) (45, 68) (46, 70) (47, 71) (47, 70) (47, 22) (47, 23) (47, 24) (47, 46) (48, 49) (48, 71) (48, 73) (48, 72) (48, 24) (48, 25) (49, 50) (49, 73) (50, 75) (51, 52) (51, 75) (51, 76) (51, 27) (51, 28) (51, 50) (52, 53) (52, 76) (53, 78) (54, 55) (54, 79) (54, 78) (54, 30) (54, 31) (54, 53) (55, 56) (55, 79) (56, 81) (57, 58) (57, 81) (57, 82) (57, 33) (57, 34) (57, 56) (58, 59) (58, 82) (59, 84) (60, 61) (60, 85) (60, 84) (60, 36) (60, 37) (60, 59) (61, 62) (61, 85) (62, 87) (63, 64) (63, 88) (63, 87) (63, 39) (63, 40) (63, 62) (64, 65) (64, 88) (65, 90) (66, 67) (66, 91) (66, 90) (66, 42) (66, 43) (66, 65) (67, 68) (67, 91) (68, 93) (69, 70) (69, 94) (69, 93) (69, 45) (69, 46) (69, 68) (70, 71) (70, 94) (71, 72) (72, 73) (72, 119) (73, 97) (74, 98) (74, 75) (74, 97) (74, 49) (74, 50) (74, 73) (75, 98) (75, 76) (76, 100) (77, 101) (77, 100) (77, 78) (77, 52) (77, 53) (77, 76) (78, 101) (78, 79) (79, 103) (80, 103) (80, 104) (80, 81) (80, 55) (80, 56) (80, 79) (81, 104) (81, 82) (82, 106) (83, 107) (83, 106) (83, 84) (83, 58) (83, 59) (83, 82) (84, 107) (84, 85) (85, 109) (86, 109) (86, 110) (86, 87) (86, 61) (86, 62) (86, 85) (87, 88) (87, 110) (88, 112) (89, 90) (89, 113) (89, 112) (89, 64) (89, 65) (89, 88) (90, 91) (90, 113) (91, 115) (92, 116) (92, 93) (92, 115) (92, 67) (92, 68) (92, 91) (93, 94) (93, 116) (94, 118) (95, 119) (95, 118) (95, 70) (95, 71) (95, 72) (95, 94) (96, 121) (96, 120) (96, 97) (96, 119) (96, 72) (96, 73) (97, 98) (97, 121) (98, 123) (99, 123) (99, 124) (99, 100) (99, 75) (99, 76) (99, 98) (100, 124) (100, 101) (101, 126) (102, 127) (102, 126) (102, 103) (102, 78) (102, 79) (102, 101) (103, 127) (103, 104) (104, 129) (105, 129) (105, 130) (105, 106) (105, 81) (105, 82) (105, 104) (106, 130) (106, 107) (107, 132) (108, 133) (108, 132) (108, 109) (108, 84) (108, 85) (108, 107) (109, 133) (109, 110) (110, 135) (111, 136) (111, 112) (111, 135) (111, 87) (111, 88) (111, 110) (112, 136) (112, 113) (113, 138) (114, 139) (114, 138) (114, 115) (114, 90) (114, 91) (114, 113) (115, 116) (115, 139) (116, 141) (117, 142) (117, 118) (117, 141) (117, 93) (117, 94) (117, 116) (118, 142) (118, 119) (119, 120) (120, 121) (120, 167) (121, 145) (122, 123) (122, 146) (122, 145) (122, 97) (122, 98) (122, 121) (123, 124) (123, 146) (124, 148) (125, 126) (125, 149) (125, 148) (125, 100) (125, 101) (125, 124) (126, 127) (126, 149) (127, 151) (128, 129) (128, 151) (128, 152) (128, 103) (128, 104) (128, 127) (129, 130) (129, 152) (130, 154) (131, 132) (131, 155) (131, 154) (131, 106) (131, 107) (131, 130) (132, 133) (132, 155) (133, 157) (134, 135) (134, 157) (134, 158) (134, 109) (134, 110) (134, 133) (135, 136) (135, 158) (136, 160) (137, 138) (137, 161) (137, 160) (137, 112) (137, 113) (137, 136) (138, 139) (138, 161) (139, 163) (140, 141) (140, 164) (140, 163) (140, 115) (140, 116) (140, 139) (141, 142) (141, 164) (142, 166) (143, 167) (143, 166) (143, 118) (143, 119) (143, 120) (143, 142) (144, 169) (144, 168) (144, 145) (144, 167) (144, 120) (144, 121) (145, 146) (145, 169) (146, 171) (147, 171) (147, 172) (147, 148) (147, 123) (147, 124) (147, 146) (148, 172) (148, 149) (149, 174) (150, 175) (150, 174) (150, 151) (150, 126) (150, 127) (150, 149) (151, 175) (151, 152) (152, 177) (153, 177) (153, 178) (153, 154) (153, 129) (153, 130) (153, 152) (154, 178) (154, 155) (155, 180) (156, 181) (156, 180) (156, 157) (156, 132) (156, 133) (156, 155) (157, 181) (157, 158) (158, 183) (159, 184) (159, 160) (159, 183) (159, 135) (159, 136) (159, 158) (160, 184) (160, 161) (161, 186) (162, 187) (162, 186) (162, 163) (162, 138) (162, 139) (162, 161) (163, 164) (163, 187) (164, 189) (165, 190) (165, 166) (165, 189) (165, 141) (165, 142) (165, 164) (166, 190) (166, 167) (167, 168) (168, 169) (168, 215) (169, 193) (170, 171) (170, 194) (170, 193) (170, 145) (170, 146) (170, 169) (171, 172) (171, 194) (172, 196) (173, 174) (173, 197) (173, 196) (173, 148) (173, 149) (173, 172) (174, 175) (174, 197) (175, 199) (176, 177) (176, 199) (176, 200) (176, 151) (176, 152) (176, 175) (177, 178) (177, 200) (178, 202) (179, 180) (179, 203) (179, 202) (179, 154) (179, 155) (179, 178) (180, 181) (180, 203) (181, 205) (182, 183) (182, 205) (182, 206) (182, 157) (182, 158) (182, 181) (183, 184) (183, 206) (184, 208) (185, 186) (185, 209) (185, 208) (185, 160) (185, 161) (185, 184) (186, 187) (186, 209) (187, 211) (188, 189) (188, 212) (188, 211) (188, 163) (188, 164) (188, 187) (189, 190) (189, 212) (190, 214) (191, 215) (191, 214) (191, 166) (191, 167) (191, 168) (191, 190) (192, 217) (192, 216) (192, 193) (192, 215) (192, 168) (192, 169) (193, 194) (193, 217) (194, 219) (195, 219) (195, 220) (195, 196) (195, 171) (195, 172) (195, 194) (196, 220) (196, 197) (197, 222) (198, 223) (198, 222) (198, 199) (198, 174) (198, 175) (198, 197) (199, 223) (199, 200) (200, 225) (201, 225) (201, 226) (201, 202) (201, 177) (201, 178) (201, 200) (202, 226) (202, 203) (203, 228) (204, 229) (204, 228) (204, 205) (204, 180) (204, 181) (204, 203) (205, 229) (205, 206) (206, 231) (207, 232) (207, 208) (207, 231) (207, 183) (207, 184) (207, 206) (208, 232) (208, 209) (209, 234) (210, 235) (210, 234) (210, 211) (210, 186) (210, 187) (210, 209) (211, 212) (211, 235) (212, 237) (213, 238) (213, 214) (213, 237) (213, 189) (213, 190) (213, 212) (214, 238) (214, 215) (215, 216) (216, 217) (216, 263) (217, 241) (218, 242) (218, 219) (218, 241) (218, 193) (218, 194) (218, 217) (219, 242) (219, 220) (220, 244) (221, 245) (221, 244) (221, 222) (221, 196) (221, 197) (221, 220) (222, 245) (222, 223) (223, 247) (224, 247) (224, 248) (224, 225) (224, 199) (224, 200) (224, 223) (225, 248) (225, 226) (226, 250) (227, 251) (227, 250) (227, 228) (227, 202) (227, 203) (227, 226) (228, 251) (228, 229) (229, 253) (230, 253) (230, 254) (230, 231) (230, 205) (230, 206) (230, 229) (231, 232) (231, 254) (232, 256) (233, 234) (233, 257) (233, 256) (233, 208) (233, 209) (233, 232) (234, 235) (234, 257) (235, 259) (236, 260) (236, 237) (236, 259) (236, 211) (236, 212) (236, 235) (237, 238) (237, 260) (238, 262) (239, 263) (239, 262) (239, 214) (239, 215) (239, 216) (239, 238) (240, 241) (240, 263) (240, 265) (240, 264) (240, 216) (240, 217) (241, 242) (241, 265) (242, 267) (243, 244) (243, 267) (243, 268) (243, 219) (243, 220) (243, 242) (244, 245) (244, 268) (245, 270) (246, 247) (246, 271) (246, 270) (246, 222) (246, 223) (246, 245) (247, 248) (247, 271) (248, 273) (249, 250) (249, 273) (249, 274) (249, 225) (249, 226) (249, 248) (250, 251) (250, 274) (251, 276) (252, 253) (252, 277) (252, 276) (252, 228) (252, 229) (252, 251) (253, 254) (253, 277) (254, 279) (255, 256) (255, 280) (255, 279) (255, 231) (255, 232) (255, 254) (256, 257) (256, 280) (257, 282) (258, 259) (258, 283) (258, 282) (258, 234) (258, 235) (258, 257) (259, 260) (259, 283) (260, 285) (261, 262) (261, 286) (261, 285) (261, 237) (261, 238) (261, 260) (262, 263) (262, 286) (263, 264) (264, 265) (264, 311) (265, 289) (266, 290) (266, 267) (266, 289) (266, 241) (266, 242) (266, 265) (267, 290) (267, 268) (268, 292) (269, 293) (269, 292) (269, 270) (269, 244) (269, 245) (269, 268) (270, 293) (270, 271) (271, 295) (272, 295) (272, 296) (272, 273) (272, 247) (272, 248) (272, 271) (273, 296) (273, 274) (274, 298) (275, 299) (275, 298) (275, 276) (275, 250) (275, 251) (275, 274) (276, 299) (276, 277) (277, 301) (278, 301) (278, 302) (278, 279) (278, 253) (278, 254) (278, 277) (279, 280) (279, 302) (280, 304) (281, 282) (281, 305) (281, 304) (281, 256) (281, 257) (281, 280) (282, 283) (282, 305) (283, 307) (284, 308) (284, 285) (284, 307) (284, 259) (284, 260) (284, 283) (285, 286) (285, 308) (286, 310) (287, 311) (287, 310) (287, 262) (287, 263) (287, 264) (287, 286) (288, 313) (288, 312) (288, 289) (288, 311) (288, 264) (288, 265) (289, 290) (289, 313) (290, 315) (291, 315) (291, 316) (291, 292) (291, 267) (291, 268) (291, 290) (292, 316) (292, 293) (293, 318) (294, 319) (294, 318) (294, 295) (294, 270) (294, 271) (294, 293) (295, 319) (295, 296) (296, 321) (297, 321) (297, 322) (297, 298) (297, 273) (297, 274) (297, 296) (298, 322) (298, 299) (299, 324) (300, 325) (300, 324) (300, 301) (300, 276) (300, 277) (300, 299) (301, 325) (301, 302) (302, 327) (303, 328) (303, 304) (303, 327) (303, 279) (303, 280) (303, 302) (304, 328) (304, 305) (305, 330) (306, 331) (306, 330) (306, 307) (306, 282) (306, 283) (306, 305) (307, 308) (307, 331) (308, 333) (309, 334) (309, 310) (309, 333) (309, 285) (309, 286) (309, 308) (310, 334) (310, 311) (311, 312) (312, 313) (312, 359) (313, 337) (314, 315) (314, 338) (314, 337) (314, 289) (314, 290) (314, 313) (315, 316) (315, 338) (316, 340) (317, 318) (317, 341) (317, 340) (317, 292) (317, 293) (317, 316) (318, 319) (318, 341) (319, 343) (320, 321) (320, 343) (320, 344) (320, 295) (320, 296) (320, 319) (321, 322) (321, 344) (322, 346) (323, 324) (323, 347) (323, 346) (323, 298) (323, 299) (323, 322) (324, 325) (324, 347) (325, 349) (326, 327) (326, 349) (326, 350) (326, 301) (326, 302) (326, 325) (327, 328) (327, 350) (328, 352) (329, 330) (329, 353) (329, 352) (329, 304) (329, 305) (329, 328) (330, 331) (330, 353) (331, 355) (332, 333) (332, 356) (332, 355) (332, 307) (332, 308) (332, 331) (333, 334) (333, 356) (334, 358) (335, 359) (335, 358) (335, 310) (335, 311) (335, 312) (335, 334) (336, 361) (336, 360) (336, 337) (336, 359) (336, 312) (336, 313) (337, 338) (337, 361) (338, 363) (339, 363) (339, 364) (339, 340) (339, 315) (339, 316) (339, 338) (340, 364) (340, 341) (341, 366) (342, 367) (342, 366) (342, 343) (342, 318) (342, 319) (342, 341) (343, 367) (343, 344) (344, 369) (345, 369) (345, 370) (345, 346) (345, 321) (345, 322) (345, 344) (346, 370) (346, 347) (347, 372) (348, 373) (348, 372) (348, 349) (348, 324) (348, 325) (348, 347) (349, 373) (349, 350) (350, 375) (351, 376) (351, 352) (351, 375) (351, 327) (351, 328) (351, 350) (352, 376) (352, 353) (353, 378) (354, 379) (354, 378) (354, 355) (354, 330) (354, 331) (354, 353) (355, 356) (355, 379) (356, 381) (357, 382) (357, 358) (357, 381) (357, 333) (357, 334) (357, 356) (358, 382) (358, 359) (359, 360) (360, 361) (360, 407) (361, 385) (362, 363) (362, 386) (362, 385) (362, 337) (362, 338) (362, 361) (363, 364) (363, 386) (364, 388) (365, 366) (365, 389) (365, 388) (365, 340) (365, 341) (365, 364) (366, 367) (366, 389) (367, 391) (368, 369) (368, 391) (368, 392) (368, 343) (368, 344) (368, 367) (369, 370) (369, 392) (370, 394) (371, 372) (371, 395) (371, 394) (371, 346) (371, 347) (371, 370) (372, 373) (372, 395) (373, 397) (374, 375) (374, 397) (374, 398) (374, 349) (374, 350) (374, 373) (375, 376) (375, 398) (376, 400) (377, 378) (377, 401) (377, 400) (377, 352) (377, 353) (377, 376) (378, 379) (378, 401) (379, 403) (380, 381) (380, 404) (380, 403) (380, 355) (380, 356) (380, 379) (381, 382) (381, 404) (382, 406) (383, 407) (383, 406) (383, 358) (383, 359) (383, 360) (383, 382) (384, 385) (384, 407) (384, 360) (384, 361) (385, 386) (387, 388) (387, 363) (387, 364) (387, 386) (388, 389) (390, 391) (390, 366) (390, 367) (390, 389) (391, 392) (393, 394) (393, 369) (393, 370) (393, 392) (394, 395) (396, 397) (396, 372) (396, 373) (396, 395) (397, 398) (399, 400) (399, 375) (399, 376) (399, 398) (400, 401) (402, 403) (402, 378) (402, 379) (402, 401) (403, 404) (405, 406) (405, 381) (405, 382) (405, 404) (406, 407)
e
<Edge object with source '406' and target '407' at 0x7ff4a4b01af8>
eptm.edge_df.shape, eptm.graph.num_edges()
((1176, 11), 1176)
for edge, val in zip(eptm.graph.edges(), eptm.edge_df.is_junction_edge.values):
assert eptm.is_junction_edge[edge] == val