Source code for nrv.ui._fascicle_postprocessing

"""
NRV-Facsiclular Level postprocessing.
"""

import faulthandler
import os

import matplotlib.pyplot as plt

from ..backend._file_handler import json_load
from ..backend._log_interface import pass_info
from ..fmod._electrodes import is_FEM_electrode
from ._axon_postprocessing import *

# enable faulthandler to ease 'segmentation faults' debug
faulthandler.enable()


#############################
####### File handeler #######
#############################


[docs] def ls_axons_results(dir_path): """ return list of axons simulation result files Parameters ---------- dir_path : str path the results directory Returns ------- files :list of str list of axons result files """ rise_warning("DeprecationWarning: ", "ls_axons_results is deprecated.") list_files = [file for file in os.listdir(dir_path) if file[0:9] == "sim_axon_"] return list_files
[docs] def ls_csv(dir_path): """ return list of axons simulation result files Parameters ---------- dir_path : str path the results directory Returns ------- files :list of str list of axons result files """ rise_warning("DeprecationWarning: ", "ls_csv is depecrated.") list_files = [file for file in os.listdir(dir_path) if file[-4:] == ".csv"] return list_files
[docs] def rm_file(file_path, verbose=True): """ Delete file Parameters ---------- file_path : str path and name of the file to remove verbose : str pass information when file is deleted """ rise_warning("DeprecationWarning: ", "rm_file is deprecated.") os.remove(file_path) pass_info("folowing file removed :" + file_path, verbose=verbose)
[docs] def rm_sim_dir(dir_path, verbose=True): """ Delete directory Warning: use with caution deleted files cannot be recovered Parameters ---------- file_path : str path and name of the file to remove verbose : str pass information when file is deleted """ rise_warning("DeprecationWarning: ", "rm_sim_dir is deprecated.") if os.path.exists(dir_path): # messaging saying folder not empty if os.path.exists( dir_path + "00_Fascicle_config.json", ): rm_file(dir_path + "00_Fascicle_config.json", verbose) for file in ls_axons_results(dir_path) + ls_csv(dir_path): rm_file(dir_path + file, verbose) # checking whether the folder is empty or not if len(os.listdir(dir_path)) == 0: os.rmdir(dir_path) pass_info("folowing folder removed :" + dir_path, verbose=verbose) else: os.rmdir(dir_path) pass_info( "Folder contains files or folders which cannot be deleted", verbose=verbose, ) else: # file not found message pass_info("Folder not found in the directory", verbose=verbose)
[docs] def rm_sim_dir_from_results(results, verbose=True): """ Delete directory Warning: use with caution deleted files cannot be recovered Parameters ---------- file_path : str path and name of the file to remove verbose : str pass information when file is deleted """ rise_warning("DeprecationWarning: ", "rm_sim_dir_from_results is deprecated.") fasc_dir = results["save_path"] + "Fascicle_" + str(results["ID"]) + "/" rm_sim_dir(dir_path=fasc_dir, verbose=verbose)
[docs] def CAP_time_detection( Voltage, t, t_stim=0, stim_duration=0, tol=0.05, myelinated=False, index=True ): """ internal use, Return index in the time scale or time of the start and stop of a Compound Action Potentiel Parameters ---------- Voltage : list(float) list of voltage value t : list(float) list of time value t_stim : float time of the stimulation (to skip the stimulation artefact) stim_duration : list(float) list of time value tol : float absolute tolerence in Volt index : bool if true the time index is returned, else the time value """ rise_warning("DeprecationWarning: ", "CAP_time_detection is deprecated.") i_start_unm, i_stop_unm = 0, 0 i_start_m, i_stop_m = 0, 0 dt = t[1] - t[0] offset = int((t_stim + stim_duration) / dt) + 1 S = Voltage N = len(S) - offset for i in range(N - 1): if i_start_unm == 0 and S[i + offset] - S[-1] > tol: i_start_unm = i + offset if i_stop_unm == 0 and abs(S[len(S) - i - 1]) - abs(S[-1]) > tol: i_stop_unm = len(S) - i - 1 if myelinated is False: i_max = i_start_unm + np.argmax(Voltage[i_start_unm:i_stop_unm]) i_min = i_start_unm + np.argmin(Voltage[i_start_unm:i_stop_unm]) if index: return i_start_unm, i_max, i_min, i_stop_unm else: return t[i_start_unm], t[i_max], t[i_min], t[i_stop_unm] else: ## No unmyelinated CAP found if i_start_unm == 0: i_stop_m = i_stop_unm for i in range(N - 1): if i_start_m == 0 and abs(S[i + offset]) - abs(S[-1]) > tol: i_start_m = i + offset else: N = i_start_unm - offset for i in range(N - 1): if i_start_m == 0 and abs(S[i + offset]) - abs(S[-1]) > tol: i_start_m = i + offset if i_stop_m == 0 and abs(S[i_start_unm - i - 1]) - abs(S[-1]) > tol: i_stop_m = i_start_unm - i - 1 i_max = np.argmax(Voltage[offset:]) i_min = i_start_m + np.argmin(Voltage[i_start_m:i_stop_m]) if index: return i_start_m, i_max, i_min, i_stop_m else: return t[i_start_m], t[i_max], t[i_min], t[i_stop_m]
############################# ##### Result processing ##### #############################
[docs] def fascicular_state( dir_path, save=False, saving_file="facsicular_state.json", delete_files=False, verbose=True, ): """ Return each axon caracteristics (blocked, Onset response, ...) Parameters ---------- dir_path : str path the results directory save : bool if True save result in json file saving_file : str if save is True path and name of the saving file Returns ------- facsicular_state : dict """ rise_warning( "DeprecationWarning: ", "fascicular_state is deprecated, use block_summary from axon_results instead.", ) fascicular = json_load(dir_path + "00_Fascicle_config.json") facsicular_state = {"-1": fascicular} N_ax = len(fascicular["axons_diameter"]) for i in range(N_ax): file = "sim_axon_" + str(i) + ".json" if "extra_stim" not in facsicular_state["-1"]: facsicular_state["-1"]["extra_stim"] = extra_stim_properties( dir_path + file ) axon = axon_state(dir_path + file) facsicular_state[axon["ID"]] = axon if delete_files: rm_file(dir_path + file, verbose) if save: save_axon_results_as_json(facsicular_state, saving_file) return facsicular_state
############################# ## VISUALIZATION FUNCTIONS ## #############################
[docs] def plot_fasc_state( facsicular_state, axes, contour_color="k", myel_color="r", unmyel_color="b", num=False, ): """ plot the fascicle in the Y-Z plane (transverse section) Parameters ---------- axes : matplotlib.axes axes of the figure to display the fascicle contour_color : str matplotlib color string applied to the contour. Black by default myel_color : str matplotlib color string applied to the myelinated axons. Red by default unmyel_color : str matplotlib color string applied to the myelinated axons. Blue by default num : bool if True, the index of each axon is displayed on top of the circle """ rise_warning( "DeprecationWarning: ", "plot_fasc_state is deprecated, use plot_block_summary from fascicules_results instead.", ) fasc = facsicular_state["-1"] colors = [] alpha = [] N = 0 while N in facsicular_state: if facsicular_state[N]["block_state"]: if facsicular_state[N]["onset_state"]: colors += ["green"] alpha += [facsicular_state[N]["onset number"]] else: colors += ["bleu"] alpha += [0] elif facsicular_state[N]["block_state"] is None: colors += ["red"] alpha += [facsicular_state[N]["onset number"]] else: if facsicular_state[N]["onset_state"]: colors += ["orange"] alpha += [facsicular_state[N]["onset number"]] else: colors += ["lightgray"] alpha += [0] N += 1 alpha = [1 - (i / (1 + max(alpha))) for i in alpha] ## plot contour axes.add_patch( plt.Circle( (fasc["y_grav_center"], fasc["z_grav_center"]), fasc["D"] / 2, color=contour_color, fill=False, linewidth=2, ) ) ## plot axons circles = [] for k in range(N): if fasc["axons_type"][k] == 1: # myelinated circles.append( plt.Circle( (fasc["axons_y"][k], fasc["axons_z"][k]), fasc["axons_diameter"][k] / 2, color=colors[k], fill=True, alpha=alpha[k], ) ) else: circles.append( plt.Circle( (fasc["axons_y"][k], fasc["axons_z"][k]), fasc["axons_diameter"][k] / 2, color=colors[k], fill=True, alpha=alpha[k], ) ) for circle in circles: axes.add_patch(circle) if num: for k in range(N): axes.text(fasc["axons_y"][k], fasc["axons_z"][k], str(k)) ## plot electrode(s) if existings if "extra_stim" in fasc: extra_stim = load_any(fasc["extra_stim"]) for electrode in extra_stim.electrodes: if electrode.type == "LIFE": circles.append( plt.Circle( (electrode.y, electrode.z), electrode.D / 2, color="gold", fill=True, ) ) elif not is_FEM_electrode(electrode): axes.scatter(electrode.y, electrode.z, color="gold")