Source code for neurd.neuron_geometry_utils

'''



Purpose: To look at the angles and projection
angles of different compartments of neurons




'''
import matplotlib.pyplot as plt
import pandas as pd
from datasci_tools import numpy_dep as np
from datasci_tools import module_utils as modu
from . import microns_volume_utils as mvu
from . import h01_volume_utils as hvu

[docs]def add_xz_angles_to_df( df, compartments=("axon","dendrite","basal","apical")): """ Purpose: To append the xz degree angle for all the vectors in all of the compartments """ df_vec = df for comp in compartments: df_vec[f"{comp}_limb"] = [int(k.split("_")[0][1:]) if k is not None else None for k in df_vec[f"{comp}_node"].to_numpy()]#[:,0] names = [ f"{comp}_skeleton_vector", f"{comp}_skeleton_vector_weighted", f"{comp}_soma_vector", f"{comp}_soma_vector_weighted" ] curr_map = df_vec.eval(f"{comp}_node == {comp}_node") for name in names: angle_name = f"{name}_xz_angle" df_vec[angle_name] = None df_vec.loc[curr_map,angle_name] = nu.angle_from_xy_vec(df_vec[[f"{name}_x_nm",f"{name}_z_nm"]][curr_map].to_numpy().T) return df_vec
[docs]def vec_df_from_compartment( df, compartment, verbose = True, align_array = True, centroid_df = None ): """ To generate a smaller df that contains all of the vector information (and xz angles) for a given compartment. Also aligns the vectors correctly for the given dataset if requested Pseudocode: 1) Filters away nan rows 2) Aligns the vectors 3) computes the xz angles """ vector_names = [k for k in df.columns if (("angle" in k) or ("_nm" in k)) and compartment in k] #print(f"vector_names = {vector_names}") identifier_names = ["segment_id","split_index",f"{compartment}_node",f"{compartment}_n_limbs",f"{compartment}_width"] curr_df = df[identifier_names + vector_names] curr_df = pu.filter_away_nan_rows(curr_df) # adjusts all of the vectors using centroid alignment if align_array: if centroid_df is None: centroid_df = vdi.seg_split_centroid_df(nm=True) centroid_names = ["centroid_x_nm","centroid_y_nm","centroid_z_nm"] df_with_centr = pd.merge(curr_df,centroid_df,on=["segment_id","split_index"],how="left") vector_names = np.sort([k for k in df.columns if ( ("_nm" in k)) and compartment in k]) #print(f"vector_names = {vector_names}") for i in range(len(vector_names)//3): curr_names = vector_names[i*3:(i*3)+3] new_array = [] for curr_vec_array,centr in zip(df_with_centr[curr_names].to_numpy(),df_with_centr[centroid_names].to_numpy()): curr_new_array = vdi.align_array(curr_vec_array,centr) new_array.append(curr_new_array) curr_df[curr_names] = list(new_array) if verbose: print(f"{len(curr_df)} datapoints for {compartment}") return ngu.add_xz_angles_to_df(curr_df,compartments=[compartment])
[docs]def plot_compartment_vector_distribution( df, n_limbs_min = 4, compartment = "basal", axes = np.array([0,2]), normalize = True, # -- parameters for 1D histogram distribution plot_type="angle_360", bins = 100, title_suffix = None, verbose = True, ): """ Purpose: To plot the 3D vectors or the 360 angle on a 1D histogram for a certain compartment over the dataframe Pseudocode: 1) Restrict the dataframe to only those cells with a certain number of limbs in that compartment 2) Get the compartment dataframe For each vector type a) Gets the vectors (restricts them to only certain axes of the vectors) b) Normalizes the vector (because sometimes will be less than one if restricting to less than 3 axes) c) """ df_vec_min_limb = df.query(f"({compartment}_n_limbs >= {n_limbs_min})") df_vec_curr = ngu.vec_df_from_compartment(df_vec_min_limb,compartment) names = [ f"{compartment}_skeleton_vector", f"{compartment}_skeleton_vector_weighted", f"{compartment}_soma_vector", f"{compartment}_soma_vector_weighted" ] axes_names = np.array(["X","Y","Z"]) combined_axes_name = "".join(axes_names[axes]) for name in names: if verbose: print(f"\n\n----Plotting {name}----\n\n") #a) Gets the vectors for that name vector_coords = vdi.coordinates_from_df( df_vec_curr, name=name)[:,axes] #b) Normalizes the vectors if normalize: vector_coords = vector_coords/(np.linalg.norm(vector_coords,axis=1).reshape(-1,1)) if len(axes) == 3: ipvu.plot_scatter(vector_coords) else: if plot_type=="angle_360": #plt.hist(nu.angle_from_xy_vec(vector_coords.T),bins=bins) angle_name = f"{name}_xz_angle" plt.hist(df_vec_curr[f"{name}_xz_angle"].to_numpy(),bins=bins) xlabel = f"{combined_axes_name} Angle (Degrees)" else: sml.hist2D(vector_coords.T[0],vector_coords.T[1]) xlabel = f"{combined_axes_name} Vector" title = f"{name}" if title_suffix is not None: title = f"{title}\n{title_suffix}" plt.title(title) plt.xlabel(xlabel) plt.show() return df_vec_curr
# ------------- Setting up parameters ----------- # -- default attributes_dict_default = dict( voxel_to_nm_scaling = mvu.voxel_to_nm_scaling, vdi = mvu.data_interface ) global_parameters_dict_default = dict( #max_ais_distance_from_soma = 50_000 ) # -- microns global_parameters_dict_microns = {} attributes_dict_microns = {} #-- h01-- attributes_dict_h01 = dict( voxel_to_nm_scaling = hvu.voxel_to_nm_scaling, vdi = hvu.data_interface ) global_parameters_dict_h01 = dict() # data_type = "default" # algorithms = None # modules_to_set = [ngu] # def set_global_parameters_and_attributes_by_data_type(data_type, # algorithms_list = None, # modules = None, # set_default_first = True, # verbose=False): # if modules is None: # modules = modules_to_set # modu.set_global_parameters_and_attributes_by_data_type(modules,data_type, # algorithms=algorithms_list, # set_default_first = set_default_first, # verbose = verbose) # set_global_parameters_and_attributes_by_data_type(data_type, # algorithms) # def output_global_parameters_and_attributes_from_current_data_type( # modules = None, # algorithms = None, # verbose = True, # lowercase = True, # output_types = ("global_parameters"), # include_default = True, # algorithms_only = False, # **kwargs): # if modules is None: # modules = modules_to_set # return modu.output_global_parameters_and_attributes_from_current_data_type( # modules, # algorithms = algorithms, # verbose = verbose, # lowercase = lowercase, # output_types = output_types, # include_default = include_default, # algorithms_only = algorithms_only, # **kwargs, # ) #--- from neurd_packages --- from . import h01_volume_utils as hvu from . import microns_volume_utils as mvu #--- from datasci_tools --- from datasci_tools import ipyvolume_utils as ipvu from datasci_tools import module_utils as modu from datasci_tools import numpy_dep as np from datasci_tools import numpy_utils as nu from datasci_tools import pandas_utils as pu from . import neuron_geometry_utils as ngu