import logging
from functools import wraps
from itertools import count
import numpy as np
from ..core.sheet import Sheet
from .base_topology import ( # noqa: F401
add_vert,
close_face,
collapse_edge,
condition_4i,
condition_4ii,
drop_two_sided_faces,
get_neighbour_face_pairs,
get_num_common_edges,
merge_border_edges,
merge_vertices,
split_vert,
)
from .bulk_topology import (
HI_transition,
IH_transition,
find_HIs,
find_IHs,
find_rearangements,
)
from .sheet_topology import remove_face, type1_transition
MAX_ITER = 10
logger = logging.getLogger(name=__name__)
[docs]class TopologyChangeError(ValueError):
"""Raised when trying to assign values without
the correct length to an epithelium dataset
"""
pass
[docs]def all_rearangements(eptm, with_t3=True):
"""Performs rearangements (T3/HI first) until
there are none left or MAX_ITER is reached.
"""
for i in count():
if i == MAX_ITER:
return 2
retcode = single_rearangement(eptm, with_t3=with_t3)
if retcode: # No transition found
return retcode
[docs]def single_rearangement(eptm, with_t3=True):
"""Performs a single rearangement (if any) on epithelium `eptm`.
If `with_t3` is True and there are removeable faces, will perform
a type 3 or HI transition on one of those faces. If no such
transition should occur, will perform a type 1 or IH transition on one
of the edges.
"""
edges, faces = find_rearangements(eptm)
if len(edges):
for i in count():
if i == MAX_ITER:
return 3
if isinstance(eptm, Sheet):
retcode = type1_transition(eptm, np.random.choice(edges))
else:
retcode = IH_transition(eptm, np.random.choice(edges))
if not retcode:
return 0
elif len(faces) and with_t3:
for i in count():
if i == MAX_ITER:
return 3
if isinstance(eptm, Sheet):
retcode = remove_face(eptm, np.random.choice(faces))
else:
retcode = HI_transition(eptm, np.random.choice(faces))
if not retcode:
return 0
return 1
[docs]def auto_t1(fun):
@wraps(fun)
def with_rearange(*args, **kwargs):
eptm, geom = args[:2]
logger.debug("checking for t1s")
res = fun(*args, **kwargs)
shorts = find_IHs(eptm)
if not len(shorts):
return res
i = 0
while len(shorts):
# shorter_edge = shorts[0]
shorter_edge = np.random.choice(shorts)
logger.info("transition on edge %i", shorter_edge)
if isinstance(eptm, Sheet):
type1_transition(eptm, shorter_edge)
else:
IH_transition(eptm, shorter_edge)
eptm.reset_index()
eptm.reset_topo()
geom.update_all(eptm)
shorts = find_IHs(eptm)
if len(shorts) and shorts[0] == shorter_edge:
# IH transition did not work, skipping
logger.info("removing shorter edge %i from edge list", shorter_edge)
shorts = shorts[1:]
i += 1
if i > MAX_ITER:
break
if eptm.position_buffer is not None:
logger.info("out T1 changed buffer")
eptm.position_buffer = eptm.vert_df[eptm.coords].copy()
logger.info("performed %i T1", i)
return res
return with_rearange
[docs]def auto_t3(fun):
@wraps(fun)
def with_rearange(*args, **kwargs):
eptm, geom = args[:2]
logger.debug("checking for t3s")
res = fun(*args, **kwargs)
tri_faces = find_HIs(eptm)
if not len(tri_faces):
return res
i = 0
while len(tri_faces):
smaller_face = tri_faces[0]
logger.debug("Performing t3 on face %d", smaller_face)
if isinstance(eptm, Sheet):
remove_face(eptm, smaller_face)
else:
HI_transition(eptm, smaller_face)
eptm.reset_index()
eptm.reset_topo()
geom.update_all(eptm)
tri_faces = find_HIs(eptm)
i += 1
if i > MAX_ITER:
break
if eptm.position_buffer is not None:
logger.info("out T3 changed buffer")
eptm.position_buffer = eptm.vert_df[eptm.coords].copy()
logger.info("performed %i T3", i)
return res
return with_rearange