grid_electrode_parameters_tensor = { 'sigma': sigma_tensor, # extracellular conductivity 'x': X.flatten(), # electrode requires 1d vector of positions 'y': Y.flatten(), 'z': Z.flatten(), 'method': 'root_as_point' } # Run simulation, electrode object argument in cell.simulate print("running simulation...") cell.simulate(rec_imem=True) # Create electrode objects grid_electrode = LFPy.RecExtElectrode(cell, **grid_electrode_parameters) grid_electrode.data = grid_electrode.get_transformation_matrix() @ cell.imem grid_electrode_tensor = LFPy.RecExtElectrode( cell, **grid_electrode_parameters_tensor) grid_electrode_tensor.data = \ grid_electrode_tensor.get_transformation_matrix() @ cell.imem fig = plt.figure(figsize=[10, 5]) ax = fig.add_subplot(121, aspect='equal', xlabel='x ($\\mu$m)', ylabel='z ($\\mu$m)', title="Sigma: %s S/m" % str(sigma), ylim=[np.min(grid_electrode.z),
def test_cell_with_recextelectrode_01(self): stickParams = { 'morphology': os.path.join(LFPy.__path__[0], 'test', 'stick.hoc'), 'templatefile': os.path.join(LFPy.__path__[0], 'test', 'stick_template.hoc'), 'templatename': 'stick_template', 'templateargs': None, 'cm': 1, 'Ra': 150, 'v_init': -65, 'passive': True, 'passive_parameters': { 'g_pas': 1. / 30000, 'e_pas': -65 }, 'tstart': -100, 'tstop': 100, 'dt': 2**-4, 'nsegs_method': 'lambda_f', 'lambda_f': 100, } electrodeParams = { 'sigma': 0.3, 'x': np.ones(11) * 100., 'y': np.zeros(11), 'z': np.linspace(1000, 0, 11), 'method': 'pointsource' } stimParams = { 'pptype': 'SinSyn', 'delay': 0., 'dur': 1000., 'pkamp': 1., 'freq': 100., 'phase': 0, 'bias': 0., 'record_current': False } stick = LFPy.TemplateCell(**stickParams) synapse = LFPy.StimIntElectrode(stick, stick.get_closest_idx(0, 0, 1000), **stimParams) electrode = LFPy.RecExtElectrode(**electrodeParams) stick.simulate(electrode, rec_imem=True) electrode1 = LFPy.RecExtElectrode(cell=stick, **electrodeParams) electrode1.calc_lfp() np.testing.assert_allclose(electrode.LFP, electrode1.LFP)
def simulate_laminar_LFP(): # DEPRECATED, and not updated for LFPy2.2 and newer dt = 2**-5 cell_name = 'hay' elec_z = np.linspace(-200, 1200, 15) elec_x = np.ones(len(elec_z)) * 50 elec_y = np.zeros(len(elec_z)) h = np.abs(elec_z[1] - elec_z[0]) electrode_parameters = { 'sigma': 0.3, # extracellular conductivity 'x': elec_x, # x,y,z-coordinates of contact points 'y': elec_y, 'z': elec_z } elec_clr = lambda idx: plt.cm.viridis(idx / len(elec_z)) num_sims = 10 cells = [] summed_LFP = [] summed_cdm = [] for sim in range(num_sims): print(sim + 1, "/", num_sims) cell_wca, idx_clr, plot_idxs = run_cell_simulation_distributed_input( dt=dt, cell_name=cell_name) cells.append([cell_wca, idx_clr, plot_idxs]) for sim in range(num_sims): cell_wca, idx_clr, plot_idxs = cells[sim] fig = plt.figure(figsize=[7, 7]) fig.subplots_adjust(hspace=0.5, left=0.0, wspace=0.4, right=0.96, top=0.97, bottom=0.1) ax_m = fig.add_axes([-0.01, 0.05, 0.3, 0.97], aspect=1, frameon=False, xlim=[-350, 350], xticks=[], yticks=[]) [ ax_m.plot([cell_wca.xstart[idx], cell_wca.xend[idx]], [cell_wca.zstart[idx], cell_wca.zend[idx]], c='k') for idx in range(cell_wca.totnsegs) ] [ ax_m.plot(cell_wca.xmid[idx], cell_wca.zmid[idx], 'o', c=idx_clr[idx], ms=13) for idx in plot_idxs ] [ ax_m.plot(cell_wca.xmid[idx], cell_wca.zmid[idx], 'rd') for idx in cell_wca.synidx ] ax_top = 0.98 ax_h = 0.25 h_space = 0.1 ax_w = 0.17 ax_left = 0.4 cell = cell_wca elec = LFPy.RecExtElectrode(cell, **electrode_parameters) elec.calc_lfp() ax_vm = fig.add_axes([ax_left, ax_top - ax_h, ax_w, ax_h], ylim=[-80, 50], xlim=[0, 80], xlabel="Time (ms)") ax_eap = fig.add_axes([ax_left + 0.3, 0.1, ax_w, 0.8], xlim=[0, 80], xlabel="Time (ms)") ax_cdm = fig.add_axes( [ax_left, 0.2, ax_w, ax_h], xlabel="Time (ms)", ylim=[-0.5, 1], xlim=[0, 80], ) ax_vm.set_ylabel("Membrane\npotential\n(mV)", labelpad=-3) ax_eap.set_ylabel("Extracellular potential ($\mu$V)", labelpad=-3) ax_cdm.set_ylabel("Curent dipole\nmoment\n($\mu$A$\cdot \mu$m)", labelpad=-3) [ ax_vm.plot(cell.tvec, cell.vmem[idx], c=idx_clr[idx]) for idx in plot_idxs ] elec.LFP -= elec.LFP[:, 0, None] cell.current_dipole_moment -= cell.current_dipole_moment[0, :] summed_LFP.append(elec.LFP) summed_cdm.append(cell.current_dipole_moment) normalize = np.max(np.abs(elec.LFP)) for idx in range(len(elec_x)): ax_eap.plot(cell.tvec, elec.LFP[idx] / normalize * h + elec_z[idx], c=elec_clr(idx)) ax_m.plot(elec_x[idx], elec_z[idx], c=elec_clr(idx), marker='D') ax_cdm.plot(cell.tvec, 1e-3 * cell.current_dipole_moment[:, 2], c='k') mark_subplots([ax_m], xpos=0.1, ypos=0.95) simplify_axes(fig.axes) plt.savefig( join("figures", 'laminar_LFP_ca_spike_{}_{}.png'.format(cell_name, sim))) # plt.savefig(join("figures", 'hay_ca_spike.pdf')) plt.close("all") summed_LFP = np.sum(summed_LFP, axis=0) summed_cdm = np.sum(summed_cdm, axis=0) normalize = np.max(np.abs(summed_LFP)) plt.subplot(121) for idx in range(len(elec_x)): plt.plot(cell.tvec, summed_LFP[idx] / normalize * h + elec_z[idx], c=elec_clr(idx)) plt.subplot(122) plt.plot(cell.tvec, summed_cdm[:, 2]) plt.savefig( join("figures", 'summed_LFP_CDM_{}_num:{}.png'.format(cell_name, num_sims)))
def simulate_network(self,filename,COMM,SIZE,RANK): filename = filename # to load data from the LIF network # XY cell positions: randomly placed within a circle if RANK == 0: x_cell_pos = [[],[]] y_cell_pos = [[],[]] for cell in range(sum(self.simulation_params["population_sizes"])): r = np.random.rand()*self.simulation_params["radius"] angle = np.random.rand()*(2*np.pi) x = r * np.cos(angle) y = r * np.sin(angle) if cell < self.simulation_params["population_sizes"][0]: x_cell_pos[0].append(x) y_cell_pos[0].append(y) else: x_cell_pos[1].append(x) y_cell_pos[1].append(y) else: x_cell_pos = None y_cell_pos = None x_cell_pos = COMM.bcast(x_cell_pos, root=0) y_cell_pos = COMM.bcast(y_cell_pos, root=0) # Resync MPI threads COMM.Barrier() # Z positions z_cell_pos = [self.simulation_params["z_cell_pos"], self.simulation_params["z_cell_pos"]] # XYZ cell rotations xyz_rotations = [self.simulation_params["xyz_rotations"][0], self.simulation_params["xyz_rotations"][1]] # Synapse parameters synapse_parameters = {} # Recurrent connections synapse_parameters['exc_exc']={ 'e' : 0.0, # reversal potential (mV) 'tau1' : 0.4, # rise time constant (ms) 'tau2' : 2.0, # decay time constant (ms) 'weight' : self.simulation_params["weight_factor"]*\ 0.178*10**(-3), # syn. weight (uS) 'position_parameters' : { 'z_min': self.simulation_params["AMPA_syn_position"]["z_min"], 'z_max': self.simulation_params["AMPA_syn_position"]["z_max"]} } synapse_parameters['inh_exc']={ 'e' : -80., 'tau1' : 0.25, 'tau2' : 5.0, 'weight' : self.simulation_params["weight_factor"]*\ 2.01*10**(-3), 'position_parameters' : { 'z_min': self.simulation_params["GABA_syn_position"]["z_min"], 'z_max': self.simulation_params["GABA_syn_position"]["z_max"]} } synapse_parameters['exc_inh']={ 'e' : 0., 'tau1' : 0.2, 'tau2' : 1.0, 'weight' : self.simulation_params["weight_factor"]*\ 0.233*10**(-3), 'position_parameters' : { 'z_min': -10**6, 'z_max': 10**6} } synapse_parameters['inh_inh']={ 'e' : -80., 'tau1' : 0.25, 'tau2' : 5.0, 'weight' : self.simulation_params["weight_factor"]*\ 2.70*10**(-3), 'position_parameters' : { 'z_min': -10**6, 'z_max': 10**6} } # External inputs synapse_parameters['th_exc']={ 'e' : 0.0, 'tau1' : 0.4, 'tau2' : 2.0, 'weight' : self.simulation_params["weight_factor"]*\ 0.234*10**(-3), 'position_parameters' : { 'z_min': self.simulation_params["AMPA_syn_position"]["z_min"], 'z_max': self.simulation_params["AMPA_syn_position"]["z_max"]} } synapse_parameters['th_inh']={ 'e' : 0.0, 'tau1' : 0.2, 'tau2' : 1.0, 'weight' : self.simulation_params["weight_factor"]*\ 0.317*10**(-3), 'position_parameters' : { 'z_min': -10**6, 'z_max': 10**6} } synapse_parameters['cc_exc']={ 'e' : 0.0, 'tau1' : 0.4, 'tau2' : 2.0, 'weight' : self.simulation_params["weight_factor"]*\ 0.187*10**(-3), 'position_parameters' : { 'z_min': self.simulation_params["AMPA_syn_position"]["z_min"], 'z_max': self.simulation_params["AMPA_syn_position"]["z_max"]} } synapse_parameters['cc_inh']={ 'e' : 0.0, 'tau1' : 0.2, 'tau2' : 1.0, 'weight' : self.simulation_params["weight_factor"]*\ 0.254*10**(-3), 'position_parameters' : { 'z_min': -10**6, 'z_max': 10**6} } # Define electrode parameters Z = self.simulation_params["Z_electrode"] X = self.simulation_params["X_electrode"] electrode_parameters = { 'sigma' : 0.3, # extracellular conductivity 'z' : Z, 'x' : X, 'y' : np.zeros(Z.size), } # EEG: four_sphere parameters # Dimensions that approximate those of a rat head model radii = [9000.,9500.,10000.,10500.] sigmas = [0.3, 1.5, 0.015, 0.3] rad_tol = 1e-2 # Summed LFPs if RANK==0: summed_LFP = np.zeros( (self.simulation_params["Z_size"], int(self.cell_params_ex["tstop"] /\ self.cell_params_ex["dt"] + 1)) ) if self.simulation_params["individual_EEG"]: summed_EEG_top = np.zeros(int(self.cell_params_ex["tstop"] /\ self.cell_params_ex["dt"] + 1)) else: summed_dipole = np.zeros((int(self.cell_params_ex["tstop"] /\ self.cell_params_ex["dt"] + 1),3)) # Load presynaptic spike times and connection matrix of the LIF network spike_times = tools.loadLIFData(self.simulation_params["experiment_id_LIF"], filename,'.spikes') connection_matrix = tools.loadLIFData(self.simulation_params["experiment_id_LIF"], filename,'.connections') # Start timer if RANK==0: start_c = time.time() # Iterate over cells in populations for j,pop_size in enumerate(self.simulation_params["population_sizes"]): for cell_id in range(pop_size): sys.stdout.write("\r" + "Simulating cell %s " % (cell_id+\ j*self.simulation_params["population_sizes"][0])) sys.stdout.flush() if cell_id % SIZE == RANK: # Initialize cell instance, using the LFPy.TemplateCell class if j==0: post_cell = LFPy.TemplateCell(**self.cell_params_ex) # Position and rotation of the cell post_cell.set_rotation(**xyz_rotations[0]) post_cell.set_pos(x = x_cell_pos[0][cell_id], y = y_cell_pos[0][cell_id], z = z_cell_pos[0]) else: post_cell = LFPy.TemplateCell(**self.cell_params_in) # Position and rotation of the cell post_cell.set_rotation(**xyz_rotations[1]) post_cell.set_pos(x = x_cell_pos[1][cell_id], y = y_cell_pos[1][cell_id], z = z_cell_pos[1]) # Search for presynaptic connections for conn,pre_cell in enumerate(connection_matrix[cell_id+\ j*self.simulation_params["population_sizes"][0]]): # Recurrent: Exc. -> Exc. if j==0 and pre_cell < self.simulation_params["population_sizes"][0]: dict_syn = synapse_parameters['exc_exc'] # Recurrent: Exc. -> Inh. elif j==1 and pre_cell < self.simulation_params["population_sizes"][0]: dict_syn = synapse_parameters['exc_inh'] # Recurrent: Inh. -> Exc. elif j==0 and pre_cell >= self.simulation_params["population_sizes"][0] and\ pre_cell < sum(self.simulation_params["population_sizes"]): dict_syn = synapse_parameters['inh_exc'] # Recurrent: Inh. -> Inh. elif j==1 and pre_cell >= self.simulation_params["population_sizes"][0] and\ pre_cell < sum(self.simulation_params["population_sizes"]): dict_syn = synapse_parameters['inh_inh'] # External: Th. -> Exc. elif j==0 and pre_cell >= sum(self.simulation_params["population_sizes"]) and\ pre_cell < 2*sum(self.simulation_params["population_sizes"]): dict_syn = synapse_parameters['th_exc'] # External: Th. -> Inh. elif j==1 and pre_cell >= sum(self.simulation_params["population_sizes"]) and\ pre_cell < 2*sum(self.simulation_params["population_sizes"]): dict_syn = synapse_parameters['th_inh'] # External: CC. -> Exc. elif j==0 and pre_cell >= 2*sum(self.simulation_params["population_sizes"]): dict_syn = synapse_parameters['cc_exc'] # External: CC. -> Inh. elif j==1 and pre_cell >= 2*sum(self.simulation_params["population_sizes"]): dict_syn = synapse_parameters['cc_inh'] # Segment indices to locate the connection pos = dict_syn["position_parameters"] idx = post_cell.get_rand_idx_area_norm(section=['dend','apic','soma'],nidx=1,**pos) # Make a synapse and set the spike times for i in idx: syn = LFPy.Synapse(cell=post_cell, idx=i, syntype='Exp2Syn', weight=dict_syn['weight'],delay=1.0, **dict(tau1=dict_syn['tau1'], tau2=dict_syn['tau2'], e=dict_syn['e'])) syn.set_spike_times(np.array(spike_times[int(pre_cell)])) # Create spike-detecting NetCon object attached to the cell's soma # midpoint if self.simulation_params["record_all"]: for sec in post_cell.somalist: post_cell.netconlist.append(neuron.h.NetCon(sec(0.5)._ref_v, None,sec=sec)) post_cell.netconlist[-1].threshold = -52.0 # as in the LIF net. post_cell.netconlist[-1].weight[0] = 0.0 post_cell.netconlist[-1].delay = 0.0 # record spike events if self.simulation_params["record_all"]: spikes = neuron.h.Vector() post_cell.netconlist[-1].record(spikes) # Simulate post_cell.simulate(rec_imem=True, rec_current_dipole_moment=True) # Compute dipole P = post_cell.current_dipole_moment # Compute EEG eeg_top = [] if self.simulation_params["individual_EEG"]: somapos = np.array([x_cell_pos[j][cell_id], y_cell_pos[j][cell_id], 8500]) r_soma_syns = [post_cell.get_intersegment_vector(idx0=0, idx1=i) for i in post_cell.synidx] r_mid = np.average(r_soma_syns, axis=0) r_mid = somapos + r_mid/2. # Change position of the EEG electrode # print("Warning: The EEG electrode is not at the top!!!") # theta_r = np.pi * 0.5 # phi_angle_r = 0.0 # x_eeg = (radii[3] - rad_tol) * np.sin(theta_r) * np.cos(phi_angle_r) # y_eeg = (radii[3] - rad_tol) * np.sin(theta_r) * np.sin(phi_angle_r) # z_eeg = (radii[3] - rad_tol) * np.cos(theta_r) # eeg_coords = np.vstack((x_eeg, y_eeg, z_eeg)).T # EEG electrode at the top eeg_coords = np.array([[0., 0., radii[3] - rad_tol]]) # Four-Sphere method four_sphere_top = LFPy.FourSphereVolumeConductor(radii, sigmas, eeg_coords) pot_db_4s_top = four_sphere_top.calc_potential(P, r_mid) eeg_top = (np.array(pot_db_4s_top) * 1e6)[0] P = [] # Set up the extracellular electrode grid_electrode = LFPy.RecExtElectrode(post_cell, **electrode_parameters) # Compute LFP grid_electrode.calc_lfp() # send LFP/EEG of this cell to RANK 0 if RANK != 0: if self.simulation_params["individual_EEG"]: COMM.send([grid_electrode.LFP,eeg_top], dest=0) else: COMM.send([grid_electrode.LFP,P], dest=0) else: summed_LFP += grid_electrode.LFP if self.simulation_params["individual_EEG"]: if len(np.argwhere(np.isnan(eeg_top))) == 0: summed_EEG_top += eeg_top else: summed_dipole += P # Synapses if self.simulation_params["record_all"]: syns = [] for s in post_cell.synapses: syns.append([s.x,s.y,s.z,s.kwargs['e']]) # collect single LFP/EEG contributions on RANK 0 if RANK == 0: if cell_id % SIZE != RANK: data = COMM.recv(source = cell_id % SIZE) summed_LFP += data[0] if self.simulation_params["individual_EEG"]: if len(np.argwhere(np.isnan(data[1]))) == 0: summed_EEG_top += data[1] else: summed_dipole += data[1] # Save results to file if cell_id % SIZE == RANK: if self.simulation_params["record_all"]: if cell_id == 0: # Create dict results_dict = { "somav":post_cell.somav, "spikes":spikes, "syns":syns, "xyz_rotations":xyz_rotations, "x_cell_pos":x_cell_pos, "y_cell_pos":y_cell_pos, "z_cell_pos":z_cell_pos, "cell_params_ex":self.cell_params_ex, "cell_params_in": self.cell_params_in, "radii":radii, "sigmas":sigmas, "rad_tol":rad_tol } else: # Create dict results_dict = { "somav":post_cell.somav, "spikes":spikes, "syns":syns, } pickle.dump(results_dict, open('../results/'+self.simulation_params["experiment_id_3D"]+"/"+\ filename+str(cell_id+j*self.simulation_params["population_sizes"][0]), "wb")) else: if cell_id == 0: # Create dict results_dict = { "cell_params_ex":self.cell_params_ex, "cell_params_in": self.cell_params_in, "radii":radii, "sigmas":sigmas, "rad_tol":rad_tol } pickle.dump(results_dict, open('../results/'+self.simulation_params["experiment_id_3D"]+"/"+\ filename+str(cell_id+j*self.simulation_params["population_sizes"][0]), "wb")) # Resync MPI threads COMM.Barrier() if RANK == 0: # Save time vector pickle.dump(post_cell.tvec, open('../results/'+self.simulation_params["experiment_id_3D"]+"/"+\ filename+"tvec","wb")) # Save LFP,EEG,CDM if self.simulation_params["decimate"]: data_tofile = tools.decimate(summed_LFP,10) else: data_tofile = summed_LFP pickle.dump(data_tofile, open('../results/'+self.simulation_params["experiment_id_3D"]+"/"+\ filename+"_LFP","wb")) if self.simulation_params["individual_EEG"]: if self.simulation_params["decimate"]: data_tofile = tools.decimate(summed_EEG_top,10) else: data_tofile = summed_EEG_top pickle.dump(data_tofile, open('../results/'+self.simulation_params["experiment_id_3D"]+"/"+\ filename+"_EEG","wb")) else: if self.simulation_params["decimate"]: data_tofile = tools.decimate(np.transpose(np.array(summed_dipole)),10) else: data_tofile = np.transpose(np.array(summed_dipole)) pickle.dump(data_tofile, open('../results/'+self.simulation_params["experiment_id_3D"]+"/"+\ filename+"_CDM","wb")) # Print computation time end_c = time.time() print("\n\ntime elapsed: %s min" % str((end_c - start_c)/60.0)) # Cleanup of object references. It will allow the script # to be run in successive fashion post_cell = None grid_electrode = None syn = None four_sphere_top = None neuron.h('forall delete_section()')
for popName in dipole_names: dipole_recorders[popName] = [] for cell in getattr(h, popName): for dipole in cell.bd: dipole_recorders[popName].append(h.Vector().record( dipole._ref_Qsum)) # Define grid recording electrode gridLims = {'x': [-400, 1100], 'y': [-300, 1400]} X, Y = np.mgrid[gridLims['x'][0]:gridLims['x'][1]:25, gridLims['y'][0]:gridLims['y'][1]:25] Z = np.zeros(X.shape) grid_electrode = LFPy.RecExtElectrode( **{ 'sigma': 0.3, # extracellular conductivity 'x': X.flatten(), # electrode requires 1d vector of positions 'y': Y.flatten(), 'z': Z.flatten() }) # ---------------------------------------------------- # Run model! # ---------------------------------------------------- h('run()') # ---------------------------------------------------- # Create dummy cell and LFP/dipole information # ---------------------------------------------------- # Get segment positions in xyz space xyz_starts, xyz_ends = np.zeros(shape=(0, 3)), np.zeros(shape=(0, 3))
def simulate_spike_current_dipole_moment(): dt = 2**-5 cell_name = 'hay' jitter_std = 10 num_trials = 1000 # Create a grid of measurement locations, in (mum) grid_x, grid_z = np.mgrid[-750:751:25, -750:1301:25] # grid_x, grid_z = np.mgrid[-75:76:50, -75:76:50] # grid_x, grid_z = np.mgrid[-75:76:50, -75:251:50] grid_y = np.zeros(grid_x.shape) # Define electrode parameters grid_elec_params = { 'sigma': 0.3, # extracellular conductivity 'x': grid_x.flatten(), # electrode requires 1d vector of positions 'y': grid_y.flatten(), 'z': grid_z.flatten() } elec_x = np.array([ 30, ]) elec_y = np.array([ 0, ]) elec_z = np.array([ 0, ]) electrode_parameters = { 'sigma': 0.3, # extracellular conductivity 'x': elec_x, # x,y,z-coordinates of contact points 'y': elec_y, 'z': elec_z } elec_clr = 'r' cell_woca, idx_clr, plot_idxs = run_cell_simulation(make_ca_spike=False, dt=dt, cell_name=cell_name) cell_wca, idx_clr, plot_idxs = run_cell_simulation(make_ca_spike=True, dt=dt, cell_name=cell_name) fig = plt.figure(figsize=[8, 7]) fig.subplots_adjust(hspace=0.5, left=0.0, wspace=0.4, right=0.96, top=0.97, bottom=0.1) ax_m = fig.add_axes([-0.01, 0.05, 0.25, 0.97], aspect=1, frameon=False, xticks=[], yticks=[]) [ ax_m.plot([cell_wca.xstart[idx], cell_wca.xend[idx]], [cell_wca.zstart[idx], cell_wca.zend[idx]], c='k') for idx in range(cell_wca.totnsegs) ] [ ax_m.plot(cell_wca.xmid[idx], cell_wca.zmid[idx], 'o', c=idx_clr[idx], ms=13) for idx in plot_idxs ] ax_m.plot(elec_x, elec_z, elec_clr, marker='D') ax_top = 0.98 ax_h = 0.15 h_space = 0.1 ax_w = 0.17 ax_left = 0.37 num = 11 levels = np.logspace(-2.5, 0, num=num) scale_max = 100. levels_norm = scale_max * np.concatenate((-levels[::-1], levels)) bwr_cmap = plt.cm.get_cmap('bwr_r') # rainbow, spectral, RdYlBu colors_from_map = [ bwr_cmap(i * np.int(255 / (len(levels_norm) - 2))) for i in range(len(levels_norm) - 1) ] colors_from_map[num - 1] = (1.0, 1.0, 1.0, 1.0) spike_plot_time_idxs = [1030, 1151] summed_cdm_max = np.zeros(2) for plot_row, cell in enumerate([cell_woca, cell_wca]): ax_left += plot_row * 0.25 elec = LFPy.RecExtElectrode(cell, **electrode_parameters) elec.calc_lfp() elec.LFP -= elec.LFP[:, 0, None] time_idx = spike_plot_time_idxs[plot_row] print(cell.tvec[time_idx]) grid_electrode = LFPy.RecExtElectrode(cell, **grid_elec_params) grid_electrode.calc_lfp() grid_LFP = 1e3 * grid_electrode.LFP grid_LFP -= grid_LFP[:, 0, None] grid_LFP_ = grid_LFP[:, time_idx].reshape(grid_x.shape) ax_ = fig.add_axes([0.75, 0.55 - plot_row * 0.46, 0.3, 0.45], xticks=[], yticks=[], aspect=1, frameon=False) mark_subplots(ax_, [["D"], ["E"]][plot_row], ypos=0.95, xpos=0.35) [ ax_.plot([cell_wca.xstart[idx], cell_wca.xend[idx]], [cell.zstart[idx], cell.zend[idx]], c='k') for idx in range(cell_wca.totnsegs) ] ep_intervals = ax_.contourf(grid_x, grid_z, grid_LFP_, zorder=-2, colors=colors_from_map, levels=levels_norm, extend='both') ax_.contour(grid_x, grid_z, grid_LFP_, colors='k', linewidths=(1), zorder=-2, levels=levels_norm) if plot_row == 1: cax = fig.add_axes([0.82, 0.12, 0.16, 0.01]) cbar = fig.colorbar(ep_intervals, cax=cax, orientation='horizontal', format='%.0E', extend='max') cbar.set_ticks( np.array([-1, -0.1, -0.01, 0, 0.01, 0.1, 1]) * scale_max) cax.set_xticklabels(np.array( np.array([-1, -0.1, -0.01, 0, 0.01, 0.1, 1]) * scale_max, dtype=int), fontsize=11, rotation=45) cbar.set_label('$\phi$ ($\mu$V)', labelpad=-5) cell.current_dipole_moment -= cell.current_dipole_moment[0, :] sum_tvec, summed_cdm = sum_jittered_cdm( cell.current_dipole_moment[:, 2], dt, jitter_std, num_trials) summed_cdm_max[plot_row] = np.max(np.abs(summed_cdm)) ax_vm = fig.add_axes( [ax_left, ax_top - ax_h, ax_w, ax_h], ylim=[-80, 50], xlim=[0, 100], #xlabel="Time (ms)" ) ax_eap = fig.add_axes( [ax_left, ax_top - 2 * ax_h - h_space, ax_w, ax_h], ylim=[-120, 40], xlim=[0, 100], #xlabel="Time (ms)" ) ax_cdm = fig.add_axes( [ax_left, ax_top - 3 * ax_h - 2 * h_space, ax_w, ax_h], #xlabel="Time (ms)", ylim=[-0.5, 1], xlim=[0, 100], ) ax_cdm_sum = fig.add_axes( [ax_left, ax_top - 4 * ax_h - 3 * h_space, ax_w, ax_h], ylim=[-250, 100], xlabel="Time (ms)", xlim=[0, 140]) if plot_row == 0: ax_vm.set_ylabel("Membrane\npotential\n(mV)", labelpad=-3) ax_eap.set_ylabel("Extracellular\npotential\n($\mu$V)", labelpad=-3) ax_cdm.set_ylabel("Curent dipole\nmoment\n($\mu$A$\cdot \mu$m)", labelpad=-3) ax_cdm_sum.set_ylabel("Jittered sum\n($\mu$A$\cdot \mu$m)", labelpad=-3) elif plot_row == 1: ax_vm.text(65, -5, "Ca$^{2+}$ spike", fontsize=11, color='orange') ax_vm.arrow(80, -10, -10, -18, color='orange', head_width=4) mark_subplots(ax_vm, [["B1"], ["C1"]][plot_row], xpos=-0.3, ypos=0.93) mark_subplots(ax_eap, [["B2"], ["C2"]][plot_row], xpos=-0.3, ypos=0.93) mark_subplots(ax_cdm, [["B3"], ["C3"]][plot_row], xpos=-0.35, ypos=0.97) mark_subplots(ax_cdm_sum, [["B4"], ["C4"]][plot_row], xpos=-0.3, ypos=0.93) [ ax_vm.plot(cell.tvec, cell.vmem[idx], c=idx_clr[idx]) for idx in plot_idxs ] ax_vm.axvline(cell.tvec[time_idx], ls='--', c='gray') # ax_cdm_sum = fig.add_subplot(524, ylim=[-1.1, 1.1], xlim=[0, 80], # ylabel="Membrane\ncurrents\n(normalized)") # [ax_cdm_sum.plot(cell.tvec, cell.imem[idx] / np.max(np.abs(cell.imem[idx])), c=idx_clr[idx]) # for idx in plot_idxs] [ ax_eap.plot(cell.tvec, 1000 * elec.LFP[idx], c=elec_clr) for idx in range(len(elec_x)) ] ax_cdm.plot(cell.tvec, 1e-3 * cell.current_dipole_moment[:, 2], c='k') ax_cdm_sum.plot(sum_tvec, 1e-3 * summed_cdm, c='k') print( "Summed CDM max (abs), ratio", summed_cdm_max * 1e-3, ) mark_subplots([ax_m], xpos=0.1, ypos=0.95) simplify_axes(fig.axes) # plt.savefig(join("figures", 'ca_spike_{}_resim.png'.format(cell_name))) plt.savefig(join("figures", 'Figure5.pdf'))
def simulate_cells_serially(stimolo, cell_ids, data_name, population_parameters, cell_parameters, synapse_parameters, synapse_position_parameters, electrode_parameters): print('input' + str(stimolo)) # Load emitted spikes, 1st column: spike time, 2nd column: pre cell id # print "Loading locally emitted spikes" local_spikes_filename = population_parameters['input_dir'] + \ 'spiketimes_' + str(stimolo) + '.1.out' local_spikes = np.loadtxt(local_spikes_filename) local_sp_times = local_spikes[:, 0] local_sp_ids = local_spikes[:, 1] # Load connectivity, 1st column post id, 2nd column pre id connectivity_filename = population_parameters['input_dir'] \ + 'Cmatrix_' + str(stimolo) + '.1.out' connectivity_file = open(connectivity_filename, "r") lines = connectivity_file.readlines() incoming_connections = [] for line in lines: incoming_connections.append(np.array(line.split(), dtype='int')) connectivity_file.close() pre_cells = {} pre_cells['exc_exc'] = population_parameters['exc_ids'] pre_cells['exc_inh'] = population_parameters['exc_ids'] pre_cells['inh_exc'] = population_parameters['inh_ids'] pre_cells['inh_inh'] = population_parameters['inh_ids'] # n_thalamic_synapses = population_parameters['n_thalamic_synapses'] # n_external_synapses = population_parameters['n_external_synapses'] # setup data dictionary output_data = {} output_data['somav'] = {} output_data['LFP'] = {} output_data['somapos'] = {} output_data['tot_isyn'] = {} for i_cell, cell_id in enumerate(cell_ids): if cell_id in population_parameters['exc_ids']: print(str(cell_id)) cell_parameters.update({'morphology': 'pyr1.hoc'}) cell_parameters['passive_parameters'].update( {'g_pas': 1. / 20000.}) elif cell_id in population_parameters['inh_ids']: indin = int(cell_id - max(population_parameters['exc_ids'])) print(str(indin)) cell_parameters.update({'morphology': 'int1.hoc'}) cell_parameters['passive_parameters'].update( {'g_pas': 1. / 10000.}) print("Setting up cell " + str(cell_id)) cell_seed = population_parameters['global_seed'] + cell_id print("Setting random seed: " + str(cell_seed)) np.random.seed(cell_seed) neuron.h('forall delete_section()') # new cell = LFPy.Cell(**cell_parameters) # new # load true position if cell_id in population_parameters['exc_ids']: cell_pos = np.loadtxt('PCsXYZ.txt') x, y, z = cell_pos[cell_id] elif cell_id in population_parameters['inh_ids']: cell_pos = np.loadtxt('INTsXYZ.txt') x, y, z = cell_pos[int(cell_id - int(min(population_parameters['inh_ids'])))] cell.set_pos(x=x, y=y, z=z) if cell_id in population_parameters['exc_ids']: local_synapse_types = ['exc_exc', 'inh_exc'] # thalamic_synapse_type = 'thalamic_exc' # external_synapse_type = 'external_exc' elif cell_id in population_parameters['inh_ids']: local_synapse_types = ['exc_inh', 'inh_inh'] # thalamic_synapse_type = 'thalamic_inh' # external_synapse_type = 'external_inh' for synapse_type in local_synapse_types: print("Setting up local synapses: ", synapse_type) pre_ids = incoming_connections[cell_id] # n_synapses = len(pre_ids) for i_synapse, pre_id in enumerate(pre_ids): if pre_id in pre_cells[synapse_type]: syn_idx = int(cell.get_rand_idx_area_norm( **synapse_position_parameters[synapse_type])) synapse_parameters[synapse_type].update({'idx': syn_idx}) synapse = LFPy.Synapse(cell, **synapse_parameters[synapse_type]) spike_times =\ local_sp_times[np.where(local_sp_ids == pre_id)[0]] synapse.set_spike_times(spike_times) print("Setting up thalamic synapses") # Load thalamic input spike times, 1st column time, # 2nd column post cell id # print "Loading thalamic input spikes" # thalamic_spikes_filename = population_parameters['input_dir'] \ # +'ths/th_'+str(stimolo)+'_'+str(cell_id)+'.out' # print thalamic_spikes_filename # # thalamic_spike_times = np.loadtxt(thalamic_spikes_filename) # synapse_ids =\ # np.random.randint(0,n_thalamic_synapses,len(thalamic_spike_times)) # for i_synapse in xrange(n_thalamic_synapses): # syn_idx = int(cell.get_rand_idx_area_norm(\ # **synapse_position_parameters[thalamic_synapse_type])) # synapse_parameters[thalamic_synapse_type].update({'idx':syn_idx}) # synapse = LFPy.Synapse(cell, \ # **synapse_parameters[thalamic_synapse_type]) # spike_times = \ # thalamic_spike_times[np.where(synapse_ids==i_synapse)[0]] # synapse.set_spike_times(spike_times) print("Setting up external synapses") # Load external cortico-cortical input rate # print "Loading external input spikes" # external_spikes_filename = population_parameters['input_dir'] \ # + 'ccs/cc_'+str(stimolo)+'_'+str(cell_id)+'.out' # external_spike_times = np.loadtxt(external_spikes_filename) # # synapse_ids =\ # np.random.randint(0,n_external_synapses,len(external_spike_times)) # # for i_synapse in xrange(n_external_synapses): # syn_idx = int(cell.get_rand_idx_area_norm(\ # **synapse_position_parameters[external_synapse_type])) # # synapse_parameters[external_synapse_type].update({'idx':syn_idx}) # synapse = LFPy.Synapse(cell,\ # **synapse_parameters[external_synapse_type]) # spike_times =\ # external_spike_times[np.where(synapse_ids==i_synapse)[0]] # synapse.set_spike_times(spike_times) # Run simulation print("Running simulation...") cell.simulate(rec_imem=True) # Calculate LFP print("Calculating LFP") electrode = LFPy.RecExtElectrode(cell, **electrode_parameters) electrode.calc_lfp() # Store data print("Storing data") output_data['LFP'][cell_id] = electrode.LFP output_data['somav'][cell_id] = cell.somav output_data['somapos'][cell_id] = cell.somapos output_data['tvec'] = cell.tvec print("Saving data to file") if not os.path.isdir(population_parameters['save_to_dir']): os.mkdir(population_parameters['save_to_dir']) print(output_data) pickle.dump(output_data, open( population_parameters['save_to_dir'] + data_name + str(stimolo), "wb"))
#define parameters for extracellular recording electrode, using optional method electrodeParameters = { 'sigma': 0.3, # extracellular conductivity 'x': X.flatten(), # x,y,z-coordinates of contact points 'y': Y.flatten(), 'z': Z.flatten(), 'method': 'soma_as_point', #treat soma segment as sphere source } ################################################################################ # Main simulation procedure, setting up extracellular electrode, cell, synapse ################################################################################ #create extracellular electrode object electrode = LFPy.RecExtElectrode(**electrodeParameters) #Initialize cell instance, using the LFPy.Cell class cell = LFPy.Cell(**cellParameters) #set the position of midpoint in soma to Origo (not needed, this is the default) cell.set_pos(x=0, y=0, z=0) #rotate the morphology 90 degrees around z-axis cell.set_rotation(z=np.pi / 2) #attach synapse with parameters and set spike time synapse = LFPy.Synapse(cell, **synapseParameters) synapse.set_spike_times(np.array([1])) #perform NEURON simulation, results saved as attributes in the cell instance cell.simulate(electrode=electrode)
def compute_h(L_dend, r_dend, r_soma, cellParams, synParams, electrodeParams, section='soma'): # create ball soma and stick dendrite model soma = neuron.h.Section(name='soma') soma.diam = r_soma*2 soma.L = r_soma*2 # NOTE: Consider setting soma diameter and length by preserving # input impedance from network point neurons for a fixed width and length # dendrite section. dend = neuron.h.Section(name='dend') dend.diam = r_dend*2. dend.L = L_dend # connect dend.connect(soma(1.), 0.) # define SectionList morphology=neuron.h.SectionList() morphology.append(sec=soma) morphology.append(sec=dend) # instantiate LFPy.Cell class cell = LFPy.Cell(morphology=morphology, **cellParams) cell.set_pos(0, 0, 0) cell.set_rotation(y=-np.pi/2) # instantiate LFPy.Synapse class try: assert(hasattr(neuron.h, 'AlphaISyn')) except AttributeError: raise AttributeError('no AlphaISyn mech found, run nrnivmodl inside this folder') # create synapses, distribute across entire section so we divide # the total synapse input by number of segments in section idx = cell.get_idx(section=section) weight = synParams.pop('weight') for i in idx: syn = LFPy.Synapse(cell, idx=i, weight=weight / idx.size, **synParams) syn.set_spike_times(np.array([lag])) # run simulation of extracellular potentials cell.simulate(rec_imem=True) # instantiate RexExtElectrode class and compute the electrode signals electrode = LFPy.RecExtElectrode(cell=cell, **electrodeParams) electrode.calc_lfp() if test_plots: from matplotlib.animation import FuncAnimation electrode_xz = LFPy.RecExtElectrode(cell=cell, **electrodeParams_xz) electrode_xz.calc_lfp() absmax = abs(electrode_xz.LFP).max() / 2. fig, ax = plt.subplots(1,1) fig.suptitle(section) im = ax.imshow(electrode_xz.LFP[:, 250].reshape(X_xz.shape), cmap='PRGn', vmin=-absmax, vmax=absmax, interpolation='nearest', origin='lower', extent=[electrode_xz.x.min(), electrode_xz.x.max(), electrode_xz.z.min(), electrode_xz.z.max()]) plt.colorbar(im) def animate(i): im.set_data(electrode_xz.LFP[:, 250+i].reshape(X_xz.shape)) return im, anim = FuncAnimation(fig, animate, frames=100, interval=20) plt.show() electrode_xz.cell = None # clean up namespace, delete all section references electrode.cell = None syn = None cell = None morphology = None dend = None soma = None return electrode.LFP
# Define electrode parameters MEA_electrode_parameters = { 'sigma_T': 0.3, # extracellular conductivity 'sigma_G': 0.0, # MEA glass electrode plate conductivity 'sigma_S': 1.5, # Saline bath conductivity 'x': X.flatten(), # electrode requires 1d vector of positions 'y': Y.flatten(), 'z': Z.flatten(), "method": "soma_as_point", 'N': np.array([[0, 0, 1]] * X.size), #surface normals 'r': 50, # contact site radius 'n': 100, # datapoints for averaging, 'h': 300, "seedvalue": 12, "squeeze_cell_factor": 0.6, } # Run simulation, electrode object argument in cell.simulate print("running simulation...") cell.simulate(rec_imem=True, rec_vmem=True) # Create electrode objects electrode = LFPy.RecExtElectrode(cell, **grid_electrode_parameters) MEA = LFPy.RecMEAElectrode(cell, **MEA_electrode_parameters) # Calculate LFPs MEA.calc_lfp() electrode.calc_lfp() plot_results(cell, synapse, MEA, electrode) plt.show()
Ny = hstep.shape x_elec = np.tile(hstep, N) y_elec = np.sort(np.tile(vstep, Ny))[::-1] z_elec = np.zeros(x_elec.shape) meshgrid = { 'sigma':0.33, 'x': x_elec, 'y': y_elec, 'z': z_elec, } # Electrodes initialization meshgrid_electrodes = LFPy.RecExtElectrode(cell, **meshgrid) meshgrid_electrodes.calc_lfp() # ============================================================================= # ================================= plot and save =============================== # ============================================================================= timeind = (cell.tvec > np.argmax(cell.somav)*st-3) & (cell.tvec <= np.argmax(cell.somav)*st+5) fileout="Vlfpy_BS"+"_LA"+LA+"_DA"+DA+"_LD"+LD+"_DD"+DD+"demo.txt" np.savetxt(fileout,meshgrid_electrodes.LFP.T[timeind]) fileout2="Vm_BS"+"_LA"+LA+"_DA"+DA+"_LD"+LD+"_DD"+DD+"demo.txt"
def test_white_noise_input(): input = 'apic' timeres = 2**-4 cut_off = 0 tstopms = 1000 tstartms = 0 cellname = 'c12861' holding_potential = -60 model_path = cellname use_channels = ['Im'] lambda_f = 100 cell_params = { 'morphology': join(model_path, '%s.hoc' % cellname), #'rm' : 30000, # membrane resistance #'cm' : 1.0, # membrane capacitance #'Ra' : 100, # axial resistance 'v_init': holding_potential, # initial crossmembrane potential 'passive': False, # switch on passive mechs 'nsegs_method': 'lambda_f', # method for setting number of segments, 'lambda_f': lambda_f, # segments are isopotential at this frequency 'timeres_NEURON': timeres, # dt of LFP and NEURON simulation. 'timeres_python': timeres, 'tstartms': tstartms, # start time, recorders start at t=0 'tstopms': tstopms, 'custom_fun': [active_declarations], # will execute this function 'custom_fun_args': [{'use_channels': use_channels, 'cellname': cellname, 'hold_potential': holding_potential}], } cell = LFPy.Cell(**cell_params) apic_idx = cell.get_closest_idx(x=0, y=0, z=350) soma_idx = 0 if input is 'apic': input_idx = apic_idx else: input_idx = soma_idx plt.seed(1234) print input_idx, holding_potential sim_params = {'rec_vmem': True, 'rec_imem': True} import aLFP num_elecs = 5 electrode_parameters = { 'sigma': 0.3, 'x': np.ones(num_elecs) * 100, 'y': np.zeros(num_elecs), 'z': np.linspace(-200, 600, num_elecs) } electrode = LFPy.RecExtElectrode(**electrode_parameters) elec_clr = ['cyan', 'orange', 'pink', 'g', 'y'] cell, syn, noise_vec = _make_white_noise_stimuli(cell, input_idx) cell.simulate(electrode=electrode, **sim_params) freqs, [psd_s] = aLFP.return_freq_and_psd(cell.tvec, cell.imem[soma_idx, :]) freqs, [psd_a] = aLFP.return_freq_and_psd(cell.tvec, cell.imem[apic_idx, :]) freqs, psd_e = aLFP.return_freq_and_psd(cell.tvec, electrode.LFP) plt.subplot(121, title="Number of compartments: %d" % cell.totnsegs) [plt.plot([cell.xstart[idx], cell.xend[idx]], [cell.zstart[idx], cell.zend[idx]], c='k') for idx in xrange(cell.totnsegs)] plt.plot(cell.xmid[soma_idx], cell.zmid[soma_idx], 'rD') plt.plot(cell.xmid[apic_idx], cell.zmid[apic_idx], 'bD') [plt.plot(electrode.x[idx], electrode.z[idx], 'o', c=elec_clr[idx]) for idx in xrange(num_elecs)] plt.subplot(322, xlim=[1, 1000], title='Soma imem psd', ylim=[1e-8, 1e-4]) plt.loglog(freqs, psd_s) plt.grid(True) plt.subplot(324, xlim=[1, 1000], title='Apic imem psd', ylim=[1e-8, 1e-3]) plt.loglog(freqs, psd_a) plt.grid(True) plt.subplot(326, xlim=[1, 1000], title='LFP', ylim=[1e-10, 1e-5]) [plt.loglog(freqs, psd_e[idx], c=elec_clr[idx]) for idx in xrange(num_elecs)] plt.grid(True) plt.savefig('wn_test_Im_apic_whole.png')
cell.set_pos(x=x_loc, y=y_loc, z=np.random.normal( loc=parameters['heights']['soma'], scale=50)) insert_synapses(parameters['synapse_parameters'], synapse_positions[k], parameters['n_syn'], parameters['heights'], cell) cell.simulate(rec_imem=True, rec_vmem=True, rec_current_dipole_moment=True) v.append(cell.vmem[0]) #storing vmem in soma, not used im.append(cell.imem) #storing all imem, not used #calculate LFP elec = LFPy.RecExtElectrode(cell, **electrodeParameters) elec.calc_lfp() cell_LFP.append(elec.LFP) #calculate EEG (using 4-sphere) P = cell.current_dipole_moment somapos = np.array( [cell.xmid[0], cell.ymid[0], radii[0] + cell.zmid[0]]) r_soma_syns = [ cell.get_intersegment_vector(idx0=0, idx1=i) for i in cell.synidx ] r_mid = np.average(r_soma_syns, axis=0) r_mid = somapos + r_mid / 2. eeg_coords_top = np.array([[0., 0., radii[3] - rad_tol]]) four_sphere_top = LFPy.FourSphereVolumeConductor(
laminar_elec_params = { 'sigma': 0.3, # extracellular conductivity 'x': laminar_x, # electrode requires 1d vector of positions 'y': laminar_y, 'z': laminar_z } # Run simulation, electrode object argument in cell.simulate print("running simulation...") cell.simulate(rec_imem=True, rec_vmem=True) laminar_electrode = LFPy.RecExtElectrode(cell, **laminar_elec_params) laminar_electrode.calc_lfp() laminar_LFP = 1e3 * laminar_electrode.LFP grid_electrode = LFPy.RecExtElectrode(cell, **grid_elec_params) grid_electrode.calc_lfp() grid_LFP = 1e3 * grid_electrode.LFP grid_LFP -= grid_LFP[:, 0, None] max_elec, max_time_idx = np.unravel_index(np.abs(laminar_LFP).argmax(), grid_LFP.shape) # plot_EAP(cell, grid_LFP, laminar_LFP, None, # grid_x, grid_z, laminar_elec_params, sim_name, savefolder) plot_spatial_time_traces(cell, grid_LFP, grid_elec_params, sim_name, savefolder)
total_conncount += conncount total_syncount += syncount # tic-toc if RANK == 0: create_connections_time = time() - tic print('Network build finished with {} connections and {} synapses in {} seconds'.format( total_conncount, total_syncount, create_connections_time)) tic = time() ############################################################################ # Set up extracellular electrode ############################################################################ if PSET.COMPUTE_LFP: electrode = LFPy.RecExtElectrode(**PSET.electrodeParams) else: electrode = None if PSET.COMPUTE_ECOG: ecog_electrode = LFPy.RecMEAElectrode(**PSET.ecogParameters) electrode = [electrode, ecog_electrode] ############################################################################ # Recording of additional variables ############################################################################ if RANK == 0: network.t = neuron.h.Vector() network.t.record(neuron.h._ref_t) else:
def return_extracellular_spike(cell, cell_name, model_type,\ electrode_parameters, limits, rotation, pos=None): """ Calculate extracellular spike on MEA at random position relative to cell Parameters: ----------- cell: object cell object from LFPy cell_name: string name of cell model electrode_parameters: dict parameters to initialize LFPy.RecExtElectrode limits: array_like boundaries for neuron locations, shape=(3,2) rotation: string random rotation to apply to the neuron ('Norot', '3drot', 'physrot') pos: array_like, (optional, default None) Can be used to set the cell soma to a specific position. If ``None``, the random position is used. Returns: -------- Extracellular spike for each MEA contact site """ def get_xyz_angles(R): ''' Get rotation angles for each axis from rotation matrix Parameters; ----------- R : matrix 3x3 rotation matrix Returns: -------- R_z : float R_y : float R_x : float Three angles for rotations around axis, defined by R = R_z.R_y.R_x ''' rot_x = np.arctan2(R[2, 1], R[2, 2]) rot_y = np.arcsin(-R[2, 0]) rot_z = np.arctan2(R[1, 0], R[0, 0]) return rot_x, rot_y, rot_z def get_rnd_rot_Arvo(): """ Generate uniformly distributed random rotation matrices see: 'Fast Random Rotation Matrices' by Arvo (1992) Returns: -------- R : 3x3 matrix random rotation matrix """ gamma = np.random.uniform(0, 2. * np.pi) rotation_z = np.matrix([[np.cos(gamma), -np.sin(gamma), 0], [np.sin(gamma), np.cos(gamma), 0], [0, 0, 1]]) x = np.random.uniform(size=2) v = np.array([ np.cos(2. * np.pi * x[0]) * np.sqrt(x[1]), np.sin(2. * np.pi * x[0]) * np.sqrt(x[1]), np.sqrt(1 - x[1]) ]) H = np.identity(3) - 2. * np.outer(v, v) M = -np.dot(H, rotation_z) return M def check_solidangle(matrix, pre, post, polarlim): """ Check whether a matrix rotates the vector 'pre' into a region defined by 'polarlim' around the vector 'post' Parameters: ----------- matrix : matrix 3x3 rotation matrix pre : array_like 3-dim vector to be rotated post : array_like axis of the cones defining the post-rotation region polarlim : [float,float] Angles specifying the opening of the inner and outer cone (aperture = 2*polarlim), i.e. the angle between rotated pre vector and post vector has to ly within these polar limits. Returns: -------- test : bool True if the vector np.dot(matrix,pre) lies inside the specified region. """ postest = np.dot(matrix, pre) c = np.dot(post / np.linalg.norm(post), postest / np.linalg.norm(postest)) if np.cos(np.deg2rad(polarlim[1])) <= c <= np.cos( np.deg2rad(polarlim[0])): return True else: return False electrodes = LFPy.RecExtElectrode(cell, **electrode_parameters) '''Rotate neuron''' if rotation == 'Norot': # orientate cells in z direction if model_type == 'bbp': x_rot = np.pi / 2. y_rot = 0 z_rot = 0 elif rotation == '3drot': if model_type == 'bbp': x_rot_offset = np.pi / 2. # align neuron with z axis y_rot_offset = 0 # align neuron with z axis z_rot_offset = 0 # align neuron with z axis x_rot, y_rot, z_rot = get_xyz_angles(np.array(get_rnd_rot_Arvo())) x_rot = x_rot + x_rot_offset y_rot = y_rot + y_rot_offset z_rot = z_rot + z_rot_offset elif rotation == 'physrot': polarlim, pref_orient = get_physrot_specs(cell_name, model_type) if model_type == 'bbp': x_rot_offset = np.pi / 2. # align neuron with z axis y_rot_offset = 0 # align neuron with z axis z_rot_offset = 0 # align neuron with z axis while True: R = np.array(get_rnd_rot_Arvo()) if polarlim is None or pref_orient is None: valid = True else: valid = check_solidangle(R, [0., 0., 1.], pref_orient, polarlim) if valid: x_rot, y_rot, z_rot = get_xyz_angles(R) x_rot = x_rot + x_rot_offset y_rot = y_rot + y_rot_offset z_rot = z_rot + z_rot_offset break else: x_rot = 0 y_rot = 0 z_rot = 0 '''Move neuron randomly''' x_rand = np.random.uniform(limits[0][0], limits[0][1]) y_rand = np.random.uniform(limits[1][0], limits[1][1]) z_rand = np.random.uniform(limits[2][0], limits[2][1]) if pos == None: cell.set_pos(x_rand, y_rand, z_rand) else: cell.set_pos(pos[0], pos[1], pos[2]) cell.set_rotation(x=x_rot, y=y_rot, z=z_rot) pos = [x_rand, y_rand, z_rand] rot = [x_rot, y_rot, z_rot] electrodes.calc_lfp() # Reverse rotation to bring cell back into initial rotation state rev_rot = [-rot[e] for e in range(len(rot))] cell.set_rotation(rev_rot[0], rev_rot[1], rev_rot[2], rotation_order='zyx') return 1000 * electrodes.LFP, pos, rot, electrodes.offsets
def run_cell_simulation(make_ca_spike, dt, cell_name, grid_elec_params, elec_params): T = 100 if cell_name == 'almog': model_folder = join('cell_models', 'almog') neuron.load_mechanisms(model_folder) os.chdir(model_folder) cell_parameters = { 'morphology': join('A140612.hoc'), 'v_init': -62, 'passive': False, 'nsegs_method': None, 'dt': dt, # [ms] Should be a power of 2 'tstart': -200, # [ms] Simulation start time 'tstop': T, # [ms] Simulation end time 'custom_code': [join('cell_model.hoc')] # Loads model specific code } cell = LFPy.Cell(**cell_parameters) os.chdir(join('..', '..')) cell.set_rotation(x=np.pi / 2, y=0.1) elif cell_name == 'hay': model_folder = join('cell_models', 'hay', 'L5bPCmodelsEH') neuron.load_mechanisms(join(model_folder, "mod")) ##define cell parameters used as input to cell-class cellParameters = { 'morphology': join(model_folder, "morphologies", "cell1.asc"), 'templatefile': [ join(model_folder, "models", "L5PCbiophys3.hoc"), join(model_folder, "models", "L5PCtemplate.hoc") ], 'templatename': 'L5PCtemplate', 'templateargs': join(model_folder, "morphologies", "cell1.asc"), 'passive': False, 'nsegs_method': None, 'dt': dt, 'tstart': -200, 'tstop': T, 'v_init': -60, 'celsius': 34, 'pt3d': True, } cell = LFPy.TemplateCell(**cellParameters) cell.set_rotation(x=np.pi / 2, y=0.1) plot_idxs = [cell.somaidx[0], cell.get_closest_idx(z=500)] idx_clr = {idx: ['b', 'orange'][num] for num, idx in enumerate(plot_idxs)} if cell_name == 'hay': weights = [0.07, 0.15] elif cell_name == 'almog': weights = [0.05, 0.15] delay = 30 synapse_s = LFPy.Synapse(cell, idx=cell.get_closest_idx(z=0), syntype='Exp2Syn', weight=weights[0], tau1=0.1, tau2=1.) synapse_s.set_spike_times(np.array([delay])) synapse_a = None if make_ca_spike: synapse_a = LFPy.Synapse(cell, idx=cell.get_closest_idx(z=400), syntype='Exp2Syn', weight=weights[1], tau1=0.1, tau2=10.) synapse_a.set_spike_times(np.array([delay])) cell.simulate(rec_imem=True, rec_vmem=True) print("MAX |I_mem(soma, apic)|: ", np.max(np.abs(cell.imem[plot_idxs]), axis=1)) elec = LFPy.RecExtElectrode(cell, **elec_params) elec_LFP = 1e3 * elec.get_transformation_matrix() @ cell.imem elec_LFP -= elec_LFP[:, 0, None] grid_electrode = LFPy.RecExtElectrode(cell, **grid_elec_params) grid_LFP = 1e3 * grid_electrode.get_transformation_matrix() @ cell.imem grid_LFP -= grid_LFP[:, 0, None] cdm = LFPy.CurrentDipoleMoment(cell) cdm = cdm.get_transformation_matrix() @ cell.imem cdm -= cdm[:, 0, None] cell_data_dict = { "vmem": cell.vmem.copy(), "tvec": cell.tvec.copy(), "elec_LFP": elec_LFP.copy(), "grid_LFP": grid_LFP.copy(), "cdm": cdm.copy(), "cell_x": cell.x.copy(), "cell_z": cell.z.copy(), } synapse_s = None synapse_a = None cell.__del__() return cell_data_dict, idx_clr, plot_idxs
templatename=templatename, templateargs=1 if add_synapses else 0, tstop=tstop, dt=dt, nsegs_method=None) #set view as in most other examples cell.set_rotation(x=np.pi / 2) pointProcess = LFPy.StimIntElectrode(cell, **PointProcParams) electrode = LFPy.RecExtElectrode(x=np.array([-40, 40., 0, 0]), y=np.array([0, 0, -40, 40]), z=np.zeros(4), sigma=0.3, r=5, n=50, N=np.array([[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]), method='soma_as_point') #run simulation cell.simulate(electrode=electrode) #electrode.calc_lfp() LFP = electrode.LFP if apply_filter: LFP = ss.filtfilt(b, a, LFP, axis=-1) #detect action potentials from intracellular trace AP_train = np.zeros(cell.somav.size, dtype=int)
def animate_ca_spike(): # Deprecated, and not updated for LFPy2.2 and newer dt = 2**-5 cell_name = 'hay' jitter_std = 10 num_trials = 1000 # Create a grid of measurement locations, in (mum) grid_x, grid_z = np.mgrid[-750:751:25, -750:1301:25] grid_y = np.zeros(grid_x.shape) # Define electrode parameters grid_elec_params = { 'sigma': 0.3, # extracellular conductivity 'x': grid_x.flatten(), # electrode requires 1d vector of positions 'y': grid_y.flatten(), 'z': grid_z.flatten() } elec_x = np.array([ 30, ]) elec_y = np.array([ 0, ]) elec_z = np.array([ 0, ]) num = 11 levels = np.logspace(-2.5, 0, num=num) scale_max = 100. levels_norm = scale_max * np.concatenate((-levels[::-1], levels)) bwr_cmap = plt.cm.get_cmap('bwr_r') # rainbow, spectral, RdYlBu colors_from_map = [ bwr_cmap(i * np.int(255 / (len(levels_norm) - 2))) for i in range(len(levels_norm) - 1) ] colors_from_map[num - 1] = (1.0, 1.0, 1.0, 1.0) cell, idx_clr, plot_idxs = run_cell_simulation(make_ca_spike=False, dt=dt, cell_name=cell_name) grid_electrode = LFPy.RecExtElectrode(cell, **grid_elec_params) grid_electrode.calc_lfp() grid_LFP = 1e3 * grid_electrode.LFP grid_LFP -= grid_LFP[:, 0, None] for time_idx in range(len(cell.tvec))[2000:]: plt.close("all") fig = plt.figure(figsize=[5, 4]) fig.text(0.5, 0.95, "T={:1.1f} ms".format(cell.tvec[time_idx]), ha="center") ax_ = fig.add_axes([0.4, 0.14, 0.6, 0.88], xticks=[], yticks=[], aspect=1, frameon=False) cax = fig.add_axes([0.5, 0.15, 0.4, 0.01]) ax_vm = fig.add_axes([0.25, 0.65, 0.2, 0.3], ylabel="membrane\npotential\n(mV)", xlabel="time (ms)") ax_cdm = fig.add_axes([0.25, 0.2, 0.2, 0.3], ylabel="current dipole\nmoment\n(µA$\cdot$µm)", xlabel="time (ms)") grid_LFP_ = grid_LFP[:, time_idx].reshape(grid_x.shape) [ ax_.plot([cell.xstart[idx], cell.xend[idx]], [cell.zstart[idx], cell.zend[idx]], c='gray') for idx in range(cell.totnsegs) ] ax_.plot([350, 350], [-540, -640], c='k', lw=2) ax_.text(360, -590, "100 $\mu$m", va='center') ep_intervals = ax_.contourf(grid_x, grid_z, grid_LFP_, zorder=-2, colors=colors_from_map, levels=levels_norm, extend='both') ax_.contour(grid_x, grid_z, grid_LFP_, colors='k', linewidths=(1), zorder=-2, levels=levels_norm) cbar = fig.colorbar(ep_intervals, cax=cax, orientation='horizontal', format='%.0E', extend='max') cbar.set_ticks( np.array([-1, -0.1, -0.01, 0, 0.01, 0.1, 1]) * scale_max) cax.set_xticklabels(np.array( np.array([-1, -0.1, -0.01, 0, 0.01, 0.1, 1]) * scale_max, dtype=int), fontsize=7, rotation=45) cbar.set_label('$\phi$ (µV)', labelpad=-5) [ ax_vm.plot(cell.tvec, cell.vmem[idx], c=idx_clr[idx]) for idx in plot_idxs ] ax_cdm.plot(cell.tvec, cell.current_dipole_moment[:, 2], c='k') ax_vm.axvline(cell.tvec[time_idx], c='gray', lw=1, ls='--') ax_cdm.axvline(cell.tvec[time_idx], c='gray', lw=1, ls='--') simplify_axes([ax_vm, ax_cdm]) anim_fig_folder = "anim_no_ca" os.makedirs(anim_fig_folder, exist_ok=True) plt.savefig( join(anim_fig_folder, "cell_ca_cont_{:04d}.png".format(time_idx)))
#Have to position and rotate the cells! cell.set_rotation(z=z_rotation[cell_id], **xy_rotations) cell.set_pos(x=x_cell_pos[cell_id]) for i_syn in range(n_synapses): syn_idx = cell.get_rand_idx_area_norm() synapse_parameters.update({'idx': syn_idx}) synapse = LFPy.Synapse(cell, **synapse_parameters) synapse.set_spike_times(pre_syn_sptimes[pre_syn_ids[cell_id % SIZE][i_syn]]) #run the cell simulation cell.simulate(rec_imem=True) #set up the extracellular device point_electrode = LFPy.RecExtElectrode(cell, **point_electrode_parameters) point_electrode.calc_lfp() # sum LFP on this RANK summed_LFP += point_electrode.LFP[0] # send LFP of this cell to RANK 0 if RANK != 0: COMM.send(point_electrode.LFP[0], dest=0) else: single_LFPs += [point_electrode.LFP[0]] # collect single LFP contributions on RANK 0 if RANK == 0: if cell_id % SIZE != RANK: single_LFPs += [COMM.recv(source=cell_id % SIZE)]
def calc_extracellular(cell_model_folder, load_sim_folder, save_sim_folder=None, seed=0, verbose=False, position=None, save=True, custom_return_cell_function=None, **kwargs): """ Loads data from previous cell simulation, and use results to generate arbitrary number of spikes above a certain noise level. Parameters: ----------- cell_model_folder : string Path to folder where cell model is saved. model_type : string Cell model type (e.g. 'bbp') load_sim_folder : string Path to folder from which NEURON simulation results (currents, membrane potential) are loaded save_sim_folder : string Path to folder where to save EAP data position : array 3D position of the soma (optional, default is None and the cell is randomly located within specified limits) custom_return_cell_function : function Python function to to return an LFPy cell from the cell_model_folder save : bool If True eaps are saved in the 'save_sim_folder'. If False eaps, positions, and rotations are returned as arrays **kwargs: keyword arguments Template generation parameters (use mr.get_default_template_parameters() to retrieve the arguments) Returns: -------- nothing, but saves the result """ LFPy, neuron = import_LFPy_neuron() cell_model_folder = Path(cell_model_folder) cell_name = cell_model_folder.parts[-1] cell_save_name = cell_name load_sim_folder = Path(load_sim_folder) np.random.seed(seed) T = kwargs['sim_time'] * 1000 dt = kwargs['dt'] rotation = kwargs['rot'] nobs = kwargs['n'] ncontacts = kwargs['ncontacts'] overhang = kwargs['overhang'] x_lim = kwargs['xlim'] y_lim = kwargs['ylim'] z_lim = kwargs['zlim'] min_amp = kwargs['min_amp'] MEAname = kwargs['probe'] drifting = kwargs['drifting'] if drifting: max_drift = kwargs['max_drift'] min_drift = kwargs['min_drift'] drift_steps = kwargs['drift_steps'] drift_x_lim = kwargs['drift_xlim'] drift_y_lim = kwargs['drift_ylim'] drift_z_lim = kwargs['drift_zlim'] if custom_return_cell_function is None: return_function = return_bbp_cell model_type = 'bbp' else: return_function = custom_return_cell_function model_type = 'custom' cuts = kwargs['cut_out'] cut_out = [int(cuts[0] / dt), int(cuts[1] / dt)] cell = return_function(cell_model_folder, end_T=T, dt=dt, start_T=0) # Load data from previous cell simulation imem_file = [ f for f in load_sim_folder.iterdir() if cell_name in f.name and 'imem' in f.name ][0] vmem_file = [ f for f in load_sim_folder.iterdir() if cell_name in f.name and 'vmem' in f.name ][0] i_spikes = np.load(str(imem_file)) v_spikes = np.load(str(vmem_file)) cell.tvec = np.arange(i_spikes.shape[-1]) * dt save_spikes = [] save_pos = [] save_rot = [] save_offs = [] target_num_spikes = int(nobs) # load MEA info elinfo = mu.return_mea_info(electrode_name=MEAname) # Create save folder if save: assert save_sim_folder is not None, "Specify 'save_sim_folder' argument!" save_sim_folder = Path(save_sim_folder) sim_folder = save_sim_folder / rotation save_folder = sim_folder / f'tmp_{target_num_spikes}_{MEAname}' if not save_folder.is_dir(): os.makedirs(str(save_folder)) if verbose: print(f'Cell {cell_save_name} extracellular spikes to be simulated') mea = mu.return_mea(MEAname) if ncontacts > 1: electrodes = LFPy.RecExtElectrode(cell, probe=mea, n=ncontacts) else: electrodes = LFPy.RecExtElectrode(cell, probe=mea) pos = mea.positions elec_x = pos[:, 0] elec_y = pos[:, 1] elec_z = pos[:, 2] if x_lim is None: x_lim = [ float(np.min(elec_x) - overhang), float(np.max(elec_x) + overhang) ] if y_lim is None: y_lim = [ float(np.min(elec_y) - overhang), float(np.max(elec_y) + overhang) ] if z_lim is None: z_lim = [ float(np.min(elec_z) - overhang), float(np.max(elec_z) + overhang) ] ignored = 0 saved = 0 i = 0 while len(save_spikes) < target_num_spikes: if i > 1000 * target_num_spikes: if verbose: print("Gave up finding spikes above noise level for %s" % cell_name) break spike_idx = np.random.randint( 0, i_spikes.shape[0]) # Each cell has several spikes to choose from cell.imem = i_spikes[spike_idx, :, :] cell.somav = v_spikes[spike_idx, :] if not drifting: espikes, pos, rot, offs = return_extracellular_spike( cell=cell, cell_name=cell_name, model_type=model_type, electrodes=electrodes, limits=[x_lim, y_lim, z_lim], rotation=rotation, pos=position) # Method of Images for semi-infinite planes if elinfo['type'] == 'mea': espikes = espikes * 2 if check_espike(espikes, min_amp): espikes = center_espike(espikes, cut_out) save_spikes.append(espikes) save_pos.append(pos) save_rot.append(rot) save_offs.append(offs) plot_spike = False if verbose: print('Cell: ' + cell_name + ' Progress: [' + str(len(save_spikes)) + '/' + str(target_num_spikes) + ']') saved += 1 else: espikes, pos, rot, offs = return_extracellular_spike( cell=cell, cell_name=cell_name, model_type=model_type, electrodes=electrodes, limits=[x_lim, y_lim, z_lim], rotation=rotation, pos=position) # Method of Images for semi-infinite planes if elinfo['type'] == 'mea': espikes = espikes * 2 if x_lim[0] < pos[0] - drift_x_lim[0] < x_lim[1] and \ y_lim[0] < pos[1] - drift_y_lim[0] < y_lim[1] and \ z_lim[0] < pos[2] - drift_z_lim[0] < z_lim[1]: if check_espike(espikes, min_amp): drift_ok = False # fix rotation while drifting cell.set_rotation(rot[0], rot[1], rot[2]) max_trials = 100 tr = 0 while not drift_ok and tr < max_trials: init_pos = pos # find drifting final position within drift limits x_rand = np.random.uniform( init_pos[0] + drift_x_lim[0], init_pos[0] + drift_x_lim[1]) y_rand = np.random.uniform( init_pos[1] + drift_y_lim[0], init_pos[1] + drift_y_lim[1]) z_rand = np.random.uniform( init_pos[2] + drift_z_lim[0], init_pos[2] + drift_z_lim[1]) final_pos = [x_rand, y_rand, z_rand] drift_dist = np.linalg.norm( np.array(init_pos) - np.array(final_pos)) # check location and boundaries if max_drift > drift_dist > min_drift and \ x_lim[0] < x_rand < x_lim[1] and \ y_lim[0] < y_rand < y_lim[1] and \ z_lim[0] < z_rand < z_lim[1]: espikes, pos, rot_, offs = return_extracellular_spike( cell=cell, cell_name=cell_name, model_type=model_type, electrodes=electrodes, limits=[x_lim, y_lim, z_lim], rotation=None, pos=final_pos) # check final position spike amplitude if check_espike(espikes, min_amp): if verbose: print('Found final drifting position') drift_ok = True else: tr += 1 pass else: tr += 1 pass # now compute drifting templates if drift_ok: drift_spikes = [] drift_pos = [] drift_rot = [] drift_dist = np.linalg.norm( np.array(init_pos) - np.array(final_pos)) drift_dir = np.array(final_pos) - np.array(init_pos) for i, dp in enumerate(np.linspace(0, 1, drift_steps)): pos_drift = init_pos + dp * drift_dir espikes, pos, r_, offs = return_extracellular_spike( cell=cell, cell_name=cell_name, model_type=model_type, electrodes=electrodes, limits=[x_lim, y_lim, z_lim], rotation=None, pos=pos_drift) espikes = center_espike(espikes, cut_out) drift_spikes.append(espikes) drift_pos.append(pos) drift_rot.append(rot) # reverse rotation rev_rot = [-r for r in rot] cell.set_rotation(rev_rot[0], rev_rot[1], rev_rot[2], rotation_order='zyx') drift_spikes = np.array(drift_spikes) drift_pos = np.array(drift_pos) if verbose: print('Drift done from ', init_pos, ' to ', final_pos, ' with ', drift_steps, ' steps') save_spikes.append(drift_spikes) save_pos.append(drift_pos) save_rot.append(rot) save_offs.append(offs) if verbose: print('Cell: ' + cell_name + ' Progress: [' + str(len(save_spikes)) + '/' + str(target_num_spikes) + ']') saved += 1 else: if verbose: print('Discarded for trials') else: pass else: if verbose: print('Discarded position: ', pos) i += 1 save_spikes = np.array(save_spikes) save_pos = np.array(save_pos) save_rot = np.array(save_rot) if save: np.save(str(save_folder / f'eap-{cell_save_name}'), save_spikes) np.save(str(save_folder / f'pos-{cell_save_name}'), save_pos) np.save(str(save_folder / f'rot-{cell_save_name}'), save_rot) else: return save_spikes, save_pos, save_rot