Source code for bsb.connectivity.connectome.NCDCN_golgi

import numpy as np
from ..strategy import ConnectionStrategy
from ...reporting import report, warn


[docs]class ConnectomeDcnGolgi(ConnectionStrategy): """ Implementation for the connections between mossy fibers and glomeruli. The connectivity is somatotopic and """
[docs] def validate(self): pass
def connect(self): # Source and target neurons are extracted dcn_cell_type = self.from_cell_types[0] golgi_cell_type = self.to_cell_types[0] dcn_cells = self.from_cells[dcn_cell_type.name] golgi_cells = self.to_cells[golgi_cell_type.name] divergence = int(self.divergence) # NC fibers reach only superficially the granule cell layer: only the first 50 um y_min = self.scaffold.configuration.layers["dcn_layer"].dimensions[ 1 ] # this value represents the beginning of GCL thickness_y = 50 # only the superficial part of GCL golgi_selected = golgi_cells[ np.where(golgi_cells[:, 3] <= y_min + thickness_y)[0], : ] # Boundaries of X, Y and Z space for Golgi BoundsX = np.array( [0, self.scaffold.configuration.layers["granular_layer"].dimensions[0]] ) BoundsY = np.array([y_min, y_min + thickness_y]) BoundsZ = np.array( [0, self.scaffold.configuration.layers["granular_layer"].dimensions[2]] ) # Density dcn NC mossy fibers vol_xyz = ( (BoundsX[1] - BoundsX[0]) * (BoundsY[1] - BoundsY[0]) * (BoundsZ[1] - BoundsZ[0]) ) N_MF = len(dcn_cells[:, 0]) # Each NC DCN cell forms 1 MF dcn_glom_density = ( N_MF / vol_xyz ) # Each NC mossy fiber forms just 1 rosette-like terminal (phantom glom) # Numerosity along the X, Z axes MF_per_X = np.ceil( (BoundsX[1] - BoundsX[0]) * np.power(dcn_glom_density, 1 / 3) ).astype(int) MF_per_Z = np.ceil( (BoundsZ[1] - BoundsZ[0]) * np.power(dcn_glom_density, 1 / 3) ).astype(int) # Points where virtual rosettes are present delta_x = (BoundsX[1] - BoundsX[0]) / MF_per_X delta_y = ( BoundsY[1] - BoundsY[0] ) / MF_per_X # MF_per_X in order to have an oblique or random distribution along y delta_z = (BoundsZ[1] - BoundsZ[0]) / MF_per_Z # Points start not from the edges of the volume MF_X = np.arange(BoundsX[0] + delta_x / 2, BoundsX[1], delta_x) MF_Y = np.arange(BoundsY[0] + delta_y / 2, BoundsY[1], delta_y) MF_Z = np.arange(BoundsZ[0] + delta_z / 2, BoundsZ[1], delta_z) # Construct the X,Z grid of points self.x_points, self.z_points = np.meshgrid( MF_X, MF_Z, sparse=False, indexing="ij" ) self.x_points = self.x_points.flatten() self.z_points = self.z_points.flatten() # For each point in the column(i) of points -> [X = Xi and Z = [Zo:Zn]] # we assign a different y value taken from MF_Y np.random.shuffle(MF_Y) self.y_points = np.array(MF_Y) for i in range(MF_per_X - 1): np.random.shuffle(MF_Y) self.y_points = np.hstack((self.y_points, MF_Y)) # The number of points could be higher than the number of NC MF if len(self.x_points) > N_MF: delete_points = np.random.choice( len(self.x_points), len(self.x_points) - N_MF, replace=False ) self.x_points = np.delete(self.x_points, delete_points) self.y_points = np.delete(self.y_points, delete_points) self.z_points = np.delete(self.z_points, delete_points) # Connectome construction based on minimum distance phantom glom <-> Golgi cell pre_post = np.zeros((divergence * N_MF, 2)) k = 0 for i in range(N_MF): distance_array = np.zeros(len(golgi_selected)) for j in range(len(golgi_selected)): distance_array[j] = np.sqrt( (self.x_points[i] - golgi_selected[j, 2]) ** 2 + (self.y_points[i] - golgi_selected[j, 3]) ** 2 + (self.z_points[i] - golgi_selected[j, 4]) ** 2 ) sorted_distance_indexes = np.argsort( distance_array ) # sorted so that the first values correspond to the closest golgi cells best_golgi = golgi_selected[sorted_distance_indexes[0:divergence], 0] pre_post[divergence * k : divergence * (k + 1), 0] = dcn_cells[i, 0] pre_post[divergence * k : divergence * (k + 1), 1] = best_golgi k += 1 self.scaffold.connect_cells(self, pre_post)