"""
Basic event module
=======================
"""
import logging
import warnings
import numpy as np
from ...core.sheet import Sheet
from ...topology.base_topology import collapse_edge
from ...topology.bulk_topology import split_vert as bulk_split
from ...topology.sheet_topology import remove_face
from ...topology.sheet_topology import split_vert as sheet_split
from ...topology.sheet_topology import type1_transition
from ...utils import connectivity
logger = logging.getLogger(__name__)
[docs]def merge_vertices(sheet):
"""Merges all the vertices that are closer than the threshold length
Parameters
----------
sheet : a :class:`Sheet` object
"""
d_min = sheet.settings.get("threshold_length", 1e-3)
short = sheet.edge_df[sheet.edge_df["length"] < d_min].index.to_numpy()
np.random.shuffle(short)
if not short.shape[0]:
return -1
logger.info(f"Collapsing {short.shape[0]} edges")
while short.shape[0]:
collapse_edge(sheet, short[0], allow_two_sided=False)
short = sheet.edge_df[sheet.edge_df["length"] < d_min].index.to_numpy()
np.random.shuffle(short)
return 0
[docs]def detach_vertices(sheet):
"""Stochastically detaches vertices from rosettes.
Uses two probabilities `p_4` and `p_5p` stored in
sheet.settings.
Parameters
----------
sheet : a :class:`Sheet` object
"""
# sheet.update_rank()
st_connect = connectivity.srce_trgt_connectivity(sheet)
rank = ((st_connect + st_connect.T) > 0).sum(axis=0)
if isinstance(sheet, Sheet):
min_rank = 3
split_vert = sheet_split
else:
min_rank = 4
split_vert = bulk_split
if rank.max() == min_rank:
return 0
dt = sheet.settings.get("dt", 1.0)
p_4 = sheet.settings.get("p_4", 0.1) * dt
p_5p = sheet.settings.get("p_5p", 1e-2) * dt
rank4 = sheet.vert_df[rank == min_rank + 1].index
dice4 = np.random.random(rank4.size)
rank5p = sheet.vert_df[rank > min_rank + 1].index
dice5p = np.random.random(rank5p.size)
to_detach = np.concatenate([rank4[dice4 < p_4], rank5p[dice5p < p_5p]])
if to_detach.size:
logger.info(f"Detaching {to_detach.size} vertices")
for vert in to_detach:
split_vert(sheet, vert)
[docs]def set_value(sheet, element, index, set_value, col):
"""Set the value in the dataset at position index/col.
Parameters
----------
sheet : a :class:`Sheet` object
element : str: 'cell' or 'face' or 'edge' or 'vert'
index : index in the datasets[element]
set_value : value to set.
col : column from dataset which apply increase_rate.
"""
sheet.datasets[element].loc[index, col] = set_value
[docs]def increase(sheet, element, index, increase_rate, col, multiply=True, bound=None):
"""Increase the value in the dataset at position index/col.
Parameters
----------
sheet : a :class:`Sheet` object
element : str: 'cell' or 'face' or 'edge' or 'vert'
index : index in the datasets[element]
increase_rate : rate use to multiply value in the column col.
col : column from dataset which apply increase_rate.
multiply : bool:
if True, the current col value is multiplied by increase_rate.
if False it is added. Default True.
bound: Higher limit of the modify value. Default None
"""
if multiply:
new_value = sheet.datasets[element].loc[index, col] * increase_rate
else:
new_value = sheet.datasets[element].loc[index, col] + increase_rate
if bound is not None:
if new_value <= bound:
sheet.datasets[element].loc[index, col] = new_value
else:
sheet.datasets[element].loc[index, col] = new_value
[docs]def decrease(sheet, element, index, decrease_rate, col, divide=True, bound=None):
"""Decrease the value in the dataset at position index/col.
Parameters
----------
sheet : a :class:`Sheet` object
element : str: 'cell' or 'face' or 'edge' or 'vert'
index : index in the datasets[element]
decrease_rate : rate use to divide value in the column col.
col : column from element which apply decrease_rate.
divide : bool: if true the current col value is divide by decrease_rate.
If false it is substracted. Default divide.
bound: lower limit of the modify value. Default None.
"""
if divide:
new_value = sheet.datasets[element].loc[index, col] / decrease_rate
else:
new_value = sheet.datasets[element].loc[index, col] - decrease_rate
if bound is not None:
if new_value >= bound:
sheet.datasets[element].loc[index, col] = new_value
else:
sheet.datasets[element].loc[index, col] = new_value
[docs]def exchange(sheet, face, geom, remove_tri_faces=True):
"""
Execute a type1 transition on the shorter edge of a face.
Parameters
----------
sheet : a :class:`Sheet` object
face : index of the face
geom : a Geometry class
remove_tri_faces : remove automaticaly triangular faces if existed. Default True.
"""
edges = sheet.edge_df[sheet.edge_df["face"] == face]
shorter = edges.length.idxmin()
# type1_transition(sheet, shorter, 2 * min(edges.length), remove_tri_faces)
type1_transition(sheet, shorter, remove_tri_faces=remove_tri_faces)
geom.update_all(sheet)
[docs]def remove(sheet, face, geom):
"""
Removes the face and updates the geometry
Parameters
----------
sheet : a :class:`Sheet` object
face : index of the face
geom : a Geometry class
"""
remove_face(sheet, face)
geom.update_all(sheet)
[docs]def ab_pull(sheet, face, radial_tension, distributed=False):
"""Adds radial_tension to the face's vertices radial_tension
Parameters
----------
sheet : a :class:`Sheet` object
face : index of face
radial_tension :
distributed : bool: If true devide radial_tension by number of vertices,
and apply this new radial tension to each vertices. Default not distributed.
"""
verts = sheet.edge_df[sheet.edge_df["face"] == face]["srce"].unique()
if distributed:
radial_tension = radial_tension / len(verts)
sheet.vert_df.loc[verts, "radial_tension"] += radial_tension
[docs]def increase_linear_tension(
sheet,
face,
line_tension_increase,
multiply=True,
isotropic=True,
angle=np.pi / 4,
limit=100,
):
"""
Increase edges line tension from face isotropic or according to an angle.
Parameters
----------
face : index of face
line_tension_increase : factor for increase line tension value
multiply : line_tension_increase is multiply or add to the current
line_tension value. Default True.
isotropic : all edges are increase, or only a subset of edges. Default True.
angle : angle below edges are increase by line_tension_increase if
isotropic is False. Default pi/4
limit : line_tension stay below this limit value
"""
edges = sheet.edge_df[sheet.edge_df["face"] == face]
if isotropic:
for index, edge in edges.iterrows():
increase(
sheet,
"edge",
edge.name,
line_tension_increase,
"line_tension",
multiply,
limit,
)
else:
for index, edge in edges.iterrows():
angle_ = np.arctan2(
sheet.edge_df.loc[edge.name, "dx"], sheet.edge_df.loc[edge.name, "dy"]
)
if np.abs(angle_) < np.pi / 4:
increase(
sheet,
"edge",
edge.name,
line_tension_increase,
"line_tension",
multiply,
limit,
)
[docs]def grow(sheet, face, growth_rate, growth_col="prefered_vol"):
"""Multiplies the grow columns of face by a factor.
Parameters
----------
sheet : a :class:`Sheet` object
face : index of face
growth_rate : rate use to multiply value of growth_col of face.
growth_col : column from face dataframe which apply growth_rate.
growth_col need to exist in face_df. Default 'prefered_vol'
:Example:
>>> print(sheet.face_df[face, 'prefered_vol'])
10
>>> grow(sheet, face, 1.7, 'prefered_vol')
>>> print(sheet.face_df[face, 'prefered_vol'])
17.0
"""
warnings.warn("deprecated, use increase function")
increase(sheet, "face", face, growth_rate, growth_col, True)
[docs]def shrink(sheet, face, shrink_rate, shrink_col="prefered_vol"):
"""Devides the shrink_col of face by a factor.
Parameters
----------
sheet : a :class:`Sheet` object
face : index of face
shrink_rate : rate use to multiply value of shrink_col of face.
shrink_col : column from face dataframe which apply shrink_rate.
shrink_col need to exist in face_df. Default 'prefered_vol'
"""
warnings.warn("deprecated, use decrease function")
decrease(sheet, "face", face, shrink_rate, shrink_col, True)
[docs]def contract(
sheet, face, contractile_increase, multiply=False, contract_col="contractility"
):
"""
Contract the face by increasing the 'contractility' parameter
by contractile_increase
Parameters
----------
sheet : a :class:`Sheet` object
face : index of face
contractile_increase : rate use to multiply/add value of contraction_col of face.
multiply : contractile_increase is multiply/add to the current contract_col value.
Default False.
contract_col : column from face dataframe which apply contractile_increase.
contract_col need to exist in face_df. Default 'contractility'
"""
warnings.warn("contract is deprecated, use increase function")
increase(sheet, "face", face, contractile_increase, contract_col, multiply)