def simulate_passive_cable(current_injection_location=DEFAULT_INPUT_LOCATION, input_current=DEFAULT_INPUT_CURRENT, length=CABLE_LENGTH, diameter=CABLE_DIAMETER, r_longitudinal=R_LONGITUDINAL, r_transversal=R_TRANSVERSAL, e_leak=E_LEAK, initial_voltage=E_LEAK, capacitance=CAPACITANCE, nr_compartments=200, simulation_time=5 * b2.ms): """Builds a multicompartment cable and numerically approximates the cable equation. Args: t_spikes (int): list of spike times current_injection_location (list): List [] of input locations (Quantity, Length): [123.*b2.um] input_current (TimedArray): TimedArray of current amplitudes. One column per current_injection_location. length (Quantity): Length of the cable: 0.8*b2.mm diameter (Quantity): Diameter of the cable: 0.2*b2.um r_longitudinal (Quantity): The longitudinal (axial) resistance of the cable: 0.5*b2.kohm*b2.mm r_transversal (Quantity): The transversal resistance (=membrane resistance): 1.25*b2.Mohm*b2.mm**2 e_leak (Quantity): The reversal potential of the leak current (=resting potential): -70.*b2.mV initial_voltage (Quantity): Value of the potential at t=0: -70.*b2.mV capacitance (Quantity): Membrane capacitance: 0.8*b2.uF/b2.cm**2 nr_compartments (int): Number of compartments. Spatial discretization: 200 simulation_time (Quantity): Time for which the dynamics are simulated: 5*b2.ms Returns: (StateMonitor, SpatialNeuron): The state monitor contains the membrane voltage in a Time x Location matrix. The SpatialNeuron object specifies the simulated neuron model and gives access to the morphology. You may want to use those objects for spatial indexing: myVoltageStateMonitor[mySpatialNeuron.morphology[0.123*b2.um]].v """ assert isinstance(input_current, b2.TimedArray), "input_current is not of type TimedArray" assert input_current.values.shape[1] == len(current_injection_location),\ "number of injection_locations does not match nr of input currents" cable_morphology = b2.Cylinder(diameter=diameter, length=length, n=nr_compartments) # Im is transmembrane current # Iext is injected current at a specific position on dendrite EL = e_leak RT = r_transversal eqs = """ Iext = current(t, location_index): amp (point current) location_index : integer (constant) Im = (EL-v)/RT : amp/meter**2 """ cable_model = b2.SpatialNeuron(morphology=cable_morphology, model=eqs, Cm=capacitance, Ri=r_longitudinal) monitor_v = b2.StateMonitor(cable_model, "v", record=True) # inject all input currents at the specified location: nr_input_locations = len(current_injection_location) input_current_0 = np.insert( input_current.values, 0, 0., axis=1) * b2.amp # insert default current: 0. [amp] current = b2.TimedArray(input_current_0, dt=input_current.dt * b2.second) for current_index in range(nr_input_locations): insert_location = current_injection_location[current_index] compartment_index = int( np.floor(insert_location / (length / nr_compartments))) # next line: current_index+1 because 0 is the default current 0Amp cable_model.location_index[compartment_index] = current_index + 1 # set initial values and run for 1 ms cable_model.v = initial_voltage b2.run(simulation_time) return monitor_v, cable_model
def biophysics(self, morpho_data): """Inserting biophysics""" neuron = br2.SpatialNeuron(morphology=self.morpho, model=eqs, \ Cm=Capacit, Ri=R_axial, threshold = "v/mV>0", refractory = "v/mV > -10", threshold_location = 0, reset = 's_trace += x_reset*(taux/ms)',method='heun') # # define the different parts of the neuron N_soma = neuron[morpho_data['soma'][0]:morpho_data['soma'][-1] + 1] N_axon = neuron[morpho_data['axon'][0]:morpho_data['axon'][-1] + 1] N_basal = neuron[morpho_data['basal'][0]:morpho_data['basal'][-1] + 1] N_apical = neuron[morpho_data['apical'][0]:morpho_data['apical'][-1] + 1] Theta_low = morpho_data['thetalow'] * mV # insert leak conductance neuron.gLeak = g_leak # noise neuron.noise_sigma = 0 * pA # initial value membrane voltage neuron.noise_avg = 0 * pA # initial value membrane voltage N_soma.noise_sigma = noise_std # initial value membrane voltage N_soma.noise_avg = noise_mean # initial value membrane voltage #################### # ACTIVE CHANNELS #################### # Na channels soma, axon, apical dendrites N_soma.gNav = somaNa N_axon.gNav = axonNa N_apical.gNav = apicalNa neuron.thi1 = thi1_all N_axon.thi1 = thi1_axn neuron.thi2 = thi2_all N_axon.thi2 = thi2_axn #Kv channels N_soma.gKv = somagKv N_basal.gKv = dendgKv N_apical.gKv = dendgKv N_axon.gKv = axongKv #Ca channels sina N_soma.gCav = ratio_ca * somaCa N_soma.gIt = (1 - ratio_ca) * somaCa #Ka channels soma N_soma.gKa_prox = somaKap #Ka channels dendrites, Na channels basal dendrites, Ca channels dendrites, axon initial segment for sec in self.sections: secNr = self.sections[sec][2] seclen = len(self.sections[sec][0].x) #BASAL if secNr in morpho_data['basal']: # decreasing Na channels gNa_diff = 0.5 * np.array( self.distances[sec][:]) * psiemens / um**2 neuron[secNr:secNr + seclen].gNav = np.multiply( basalNa - gNa_diff, basalNa - gNa_diff > 0) # increasing Ka channels gKa_diff = 0.7 * np.array( self.distances[sec][:]) * psiemens / um**2 ratio_A = np.multiply( 1. - (1. / 300.) * np.array(self.distances[sec][:]), 1. - (1. / 300.) * np.array(self.distances[sec][:]) > 0) neuron[secNr:secNr + seclen].gKa_prox = ratio_A * np.multiply( basalKa + gKa_diff, basalKa + gKa_diff > 0) neuron[secNr:secNr + seclen].gKa_dist = (1. - ratio_A) * np.multiply( basalKa + gKa_diff, basalKa + gKa_diff > 0) # Ca channels neuron[secNr:secNr + seclen].gCav = dendCa * ratio_ca * ( np.array(self.distances[sec][:]) > 30) + somaCa * ratio_ca * (np.array(self.distances[sec][:]) <= 30) neuron[secNr:secNr + seclen].gIt = dendCa * (1. - ratio_ca) * ( np.array(self.distances[sec][:]) > 30) + somaCa * ( 1. - ratio_ca) * (np.array(self.distances[sec][:]) <= 30) #spines addSpines = np.array(self.distances[sec][:]) > spinedist noSpines = np.array(self.distances[sec][:]) <= spinedist neuron[ secNr:secNr + seclen].gLeak = noSpines * g_leak + addSpines * g_leak_dend neuron[ secNr:secNr + seclen].Cm = noSpines * Capacit + addSpines * Capacit_dend #APICAL if secNr in morpho_data['apical']: #ratio of Ka channels ratio_A = np.multiply( 1. - (1. / 300.) * np.array(self.distances[sec][:]), 1. - (1. / 300.) * np.array(self.distances[sec][:]) > 0) neuron[secNr:secNr + seclen].gKa_prox = ratio_A * apicalKa neuron[secNr:secNr + seclen].gKa_dist = (1. - ratio_A) * apicalKa # Ca channels neuron[secNr:secNr + seclen].gCav = dendCa * ratio_ca * ( np.array(self.distances[sec][:]) > 30) + somaCa * ratio_ca * (np.array(self.distances[sec][:]) <= 30) neuron[secNr:secNr + seclen].gIt = dendCa * (1. - ratio_ca) * ( np.array(self.distances[sec][:]) > 30) + somaCa * ( 1. - ratio_ca) * (np.array(self.distances[sec][:]) <= 30) #spines addSpines = np.array(self.distances[sec][:]) > spinedist noSpines = np.array(self.distances[sec][:]) <= spinedist neuron[ secNr:secNr + seclen].gLeak = noSpines * g_leak + addSpines * g_leak_dend neuron[ secNr:secNr + seclen].Cm = noSpines * Capacit + addSpines * Capacit_dend #AXON if secNr in morpho_data['axon']: #KL current addKL = np.array(self.distances[sec][:]) > 35 neuron[secNr:secNr + seclen].gKL = addKL * axongL neuron[1:6].gKv = [40., 100., 500., 500., 500. ] * psiemens / um**2 neuron[1:6].gKL = [20., 35., 125., 250., 0] * psiemens / um**2 neuron[1:6].gNav = 4 * np.array( [8000., 7000., 5000., 5000., 5000.]) * psiemens / um**2 # neuron[1:6].gNav = [8000.,7000.,5000.,5000.,5000.]*psiemens/um**2 neuron[1:3].gCav = somaCa * ratio_ca neuron[1:3].gIt = somaCa * (1. - ratio_ca) # SET INITIAL VALUES set_init_nrn(neuron, Theta_low) return neuron