from ..backend._log_interface import rise_warning
from ..nmod._nerve import nerve
from ..nmod._fascicles import fascicle
from ..utils._misc import get_MRG_parameters
from ..fmod._electrodes import *
from ..fmod._extracellular import is_FEM_extra_stim, FEM_stimulation
from ..fmod.FEM.mesh_creator._NerveMshCreator import *
from ._spec_loaders import load_axon, load_fascicle, load_nerve
[docs]
def mesh_from_electrode(
elec: FEM_electrode,
mesh: NerveMshCreator = None,
Length: float = 10000,
Outer_D: float = 5,
Nerve_D: float = 4000,
y_c: float = 0,
z_c: float = 0,
res: float | str = "default",
) -> NerveMshCreator:
"""
returns the corresponding mesh from a nrv.facsicle
"""
elec = load_any(elec)
if not is_FEM_electrode(elec):
rise_warning("Only FEM electrode can be added to a mesh")
else:
if mesh is None:
mesh = NerveMshCreator(
Length=Length, Outer_D=Outer_D, Nerve_D=Nerve_D, y_c=y_c, z_c=z_c
)
elec.parameter_model(mesh, res=res)
return mesh
[docs]
def mesh_from_fascicle(
fasc: fascicle,
mesh: NerveMshCreator | None = None,
Length: float = 10000,
Outer_D: float = 5,
Nerve_D: float = 4000,
y_c: float = 0,
z_c: float = 0,
add_axons: bool = True,
x_shift: float | None = None,
add_context: bool = False,
res_nerve: float | str = "default",
res_fasc: float | str = "default",
res_ax: list[float] | float | str = "default",
res_elec: list[float] | float | str = "default",
) -> NerveMshCreator:
"""
returns the corresponding mesh from a nrv.facsicle
"""
fasc = load_fascicle(fasc, extracel_context=True)
if mesh is None:
mesh = NerveMshCreator(
Length=Length, Outer_D=Outer_D, Nerve_D=Nerve_D, y_c=y_c, z_c=z_c
)
if res_nerve != "default":
mesh.reshape_nerve(res=res_nerve)
mesh.reshape_fascicle(geometry=fasc.geom, res=res_fasc)
if add_axons:
ax_pop = fasc.axons.get_sub_population(mask_labels=fasc.sim_mask)
if fasc.axons.has_node_shift:
node_shift = ax_pop["node_shift"]
else:
node_shift = np.zeros(fasc.n_ax)
if x_shift is not None:
i_myel = ax_pop["types"].astype(bool)
__deltaxs = get_MRG_parameters(ax_pop["diameters"][i_myel].to_numpy())[5]
__l1_ = ax_pop["node_shift"][i_myel] * __deltaxs
__x_l = (__l1_ - x_shift) % __deltaxs
node_shift[i_myel] = __x_l / __deltaxs
for i_ax, id_ax in enumerate(ax_pop.index):
ax_d = round(ax_pop["diameters"][id_ax], 3)
ax_y = round(ax_pop["y"][id_ax], 3)
ax_z = round(ax_pop["z"][id_ax], 3)
mye = bool(ax_pop["types"][id_ax])
res_ax_ = res_ax
if isinstance(res_ax, str) and res_ax != "default":
res_ax_ = eval(str(ax_pop["diameters"][id_ax]) + res_ax)
elif np.iterable(res_ax) and not isinstance(res_ax, str):
res_ax_ = res_ax[i_ax]
mesh.reshape_axon(
d=ax_d,
y=ax_y,
z=ax_z,
myelinated=mye,
node_shift=node_shift[id_ax],
res=res_ax_,
)
if add_context and fasc.extra_stim is not None:
mesh = mesh_from_extracellular_context(
fasc.extra_stim, mesh=mesh, res_elec=res_elec
)
return mesh
[docs]
def mesh_from_nerve(
nerve: nerve,
length: float | None = None,
add_axons: bool = True,
x_shift: float | None = None,
res_nerve: float | str = "default",
res_fasc: list[float] | float | str = "default",
res_ax: list[float] | float | str = "default",
res_elec: list[float] | float | str = "default",
) -> NerveMshCreator:
"""
Build a mesh nerve mesh from an ``nrv.mesh`` instance
Parameters
----------
nerve : nerve
nerve to use for meshing mesh
length : float | None, optional
if not None, length to use to resize the nerve, by default None
add_axons : bool, optional
if True axons are added to the nerve, by default True
x_shift : float | None, optional
if not None, add a node shift in um to mesh the myelinated axons by default None
res_nerve : float | str, optional
nerve resolution in the epineurium domain, by default "default"
res_fasc : list[float] | float | str, optional
fascicle reoulution in the endoneurium domain, by default "default"
res_ax : list[float] | float | str, optional
axon resolution in the epneurium domain,, by default "default"
res_elec : list[float] | float | str, optional
electrode resolution, by default "default"
Returns
-------
NerveMshCreator
"""
nerve = load_any(nerve, extracel_context=True)
if length is not None:
length = length
else:
length = nerve.L
mesh = NerveMshCreator(
Length=length,
Outer_D=nerve.Outer_D,
Nerve_D=nerve.D,
y_c=nerve.y_grav_center,
z_c=nerve.z_grav_center,
)
mesh.reshape_nerve(res=res_nerve)
if np.iterable(res_fasc) and not isinstance(res_fasc, str):
if len(res_fasc) == len(nerve.fascicles):
res = res_fasc
else:
rise_warning(
"length of res_fasc and nerve.fascicles does not match",
"only first value kept",
)
res = [res_fasc[0] for k in range(len(nerve.fascicles))]
else:
res = [res_fasc for k in range(len(nerve.fascicles))]
for i_fasc, fasc in enumerate(nerve.fascicles.values()):
mesh = mesh_from_fascicle(
fasc,
mesh=mesh,
add_context=False,
add_axons=add_axons,
x_shift=x_shift,
res_ax=res_ax,
res_fasc=res[i_fasc],
)
if nerve.extracel_status():
mesh = mesh_from_extracellular_context(
nerve.extra_stim, mesh=mesh, res_elec=res_elec
)
return mesh