def test_calc_potential_from_multi_dipoles01(self): neuron.h('forall delete_section()') soma = neuron.h.Section(name='soma') dend1 = neuron.h.Section(name='dend1') dend2 = neuron.h.Section(name='dend2') dend1.connect(soma(0.5), 0) dend2.connect(dend1(1.0), 0) morphology = neuron.h.SectionList() morphology.wholetree() radii = [300, 400, 500, 600] sigmas = [0.3, 1.5, 0.015, 0.3] electrode_locs = np.array([[0., 0., 290.], [10., 90., 300.], [-90, 50., 400.], [110.3, -100., 500.]]) cell = cell_w_synapse_from_sections(morphology) t_point = -1 MD_4s = LFPy.FourSphereVolumeConductor(radii, sigmas, electrode_locs) dipoles, dipole_locs = cell.get_multi_current_dipole_moments() p = dipoles[:, t_point, :] Np = p.shape[0] Nt = 1 Ne = electrode_locs.shape[0] pot_MD = MD_4s.calc_potential_from_multi_dipoles(cell)[:, t_point] pot_sum = np.zeros((Ne, Nt)) for i in range(Np): dip = np.array([p[i]]) dip_loc = dipole_locs[i] fs = LFPy.FourSphereVolumeConductor(radii, sigmas, electrode_locs) pot = fs.calc_potential(dip, dip_loc) pot_sum += pot pot_sum = pot_sum.reshape(4) np.testing.assert_almost_equal(pot_MD, pot_sum) np.testing.assert_allclose(pot_MD, pot_sum, rtol=1E-4)
def test_calc_potential_from_multi_dipoles00(self): """test comparison between multi-dipoles and single dipole approach""" neuron.h('forall delete_section()') soma = neuron.h.Section(name='soma') dend1 = neuron.h.Section(name='dend1') dend2 = neuron.h.Section(name='dend2') dend1.connect(soma(0.5), 0) dend2.connect(dend1(1.0), 0) morphology = neuron.h.SectionList() morphology.wholetree() radii = [300, 400, 500, 600] sigmas = [0.3, 1.5, 0.015, 0.3] electrode_locs = np.array([[0., 0., 290.], [10., 90., 300.], [-90, 50., 400.], [110.3, -100., 500.]]) cell = cell_w_synapse_from_sections(morphology) cell.set_pos(x=0, y=0, z=100) t_point = [1, 100, -1] MD_4s = LFPy.FourSphereVolumeConductor(radii, sigmas, electrode_locs) p, dipole_locs = cell.get_multi_current_dipole_moments(t_point) Np, Nt, Nd = p.shape Ne = electrode_locs.shape[0] pot_MD = MD_4s.calc_potential_from_multi_dipoles(cell, t_point) pot_sum = np.zeros((Ne, Nt)) for i in range(Np): dip = p[i] dip_loc = dipole_locs[i] fs = LFPy.FourSphereVolumeConductor(radii, sigmas, electrode_locs) pot = fs.calc_potential(dip, dip_loc) pot_sum += pot np.testing.assert_almost_equal(pot_MD, pot_sum) np.testing.assert_allclose(pot_MD, pot_sum, rtol=1E-4)
def test_check_params02(self): '''Test that ValueError is raised if electrode outside head''' radii = [1., 2., 4., 10.] sigmas = [1., 2., 4., 8.] r_el1 = np.array([[0., 0., 15.]]) r_el2 = np.array([[0., 0., 1.5], [12., 0., 0.]]) with np.testing.assert_raises(ValueError): LFPy.FourSphereVolumeConductor(radii, sigmas, r_el1) with np.testing.assert_raises(ValueError): LFPy.FourSphereVolumeConductor(radii, sigmas, r_el2)
def test_check_params01(self): '''Test that Error is raised if invalid entries in sigmas''' radii = [1., 2., 4., 10.] sigmas1 = [1., 'str', 4., 8.] sigmas2 = [-1., 2., 4., 8.] sigmas3 = [1., 2., -4., 8.] sigmas4 = [1., 2., 4., -8.] r_el = np.array([[0., 0., 1.5]]) with np.testing.assert_raises(ValueError): LFPy.FourSphereVolumeConductor(radii, sigmas1, r_el) with np.testing.assert_raises(RuntimeError): LFPy.FourSphereVolumeConductor(radii, sigmas2, r_el) with np.testing.assert_raises(RuntimeError): LFPy.FourSphereVolumeConductor(radii, sigmas3, r_el) with np.testing.assert_raises(RuntimeError): LFPy.FourSphereVolumeConductor(radii, sigmas4, r_el)
def test_check_params00(self): '''Test that invalid radius values raises RuntimeError''' radii1 = [-1., 2., 4., 8.] radii2 = [1., .5, 4., 8.] radii3 = [1., 2., 1.1, 8.] radii4 = [1., 2., 4., 1.] sigmas = [1., 2., 4., 8.] r_el = np.array([[0., 0., 1.5]]) with np.testing.assert_raises(RuntimeError): LFPy.FourSphereVolumeConductor(radii1, sigmas, r_el) with np.testing.assert_raises(RuntimeError): LFPy.FourSphereVolumeConductor(radii2, sigmas, r_el) with np.testing.assert_raises(RuntimeError): LFPy.FourSphereVolumeConductor(radii3, sigmas, r_el) with np.testing.assert_raises(RuntimeError): LFPy.FourSphereVolumeConductor(radii4, sigmas, r_el)
def make_class_object(rz, r_el): '''Return class object fs''' radii = [79., 80., 85., 90.] sigmas = [0.3, 0.015, 15, 0.3] fs = LFPy.FourSphereVolumeConductor(radii, sigmas, r_el) fs._rz_params(rz) return fs
def return_eeg(cell, radii, sigmas, eeg_coords, morph_type): # compute current dipole moment P = cell.current_dipole_moment # set dipole position 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) if morph_type == 'l5i': somapos = np.array([0., 0., radii[0] - 1200]) else: somapos = np.array([0., 0., radii[0] - np.max(cell.zend) - 50]) dipole_pos = r_mid + somapos cell.set_pos(x=somapos[0], y=somapos[1], z=somapos[2]) # multi_dipoles, dipole_locs = cell.get_multi_current_dipole_moments() # t_point = 800 # P_from_multi_dipoles = np.sum(multi_dipoles[:,t_point,:],axis=0) # print('single dipole:', P[t_point]) # print('sum of multi-dipoles', P_from_multi_dipoles) # compute eeg with 4S model fs_eeg = LFPy.FourSphereVolumeConductor(radii, sigmas, eeg_coords) eeg = fs_eeg.calc_potential(P, dipole_pos) eeg_multidip = fs_eeg.calc_potential_from_multi_dipoles(cell) eeg_avg = np.average(eeg, axis=0) eeg_multidip_avg = np.average(eeg_multidip, axis=0) # convert from mV to pV: eeg_avg = eeg_avg * 1e9 eeg_multidip_avg = eeg_multidip_avg * 1e9 return eeg_avg, eeg_multidip_avg
def test_calc_potential02(self): '''Test radial and tangential parts of dipole sums to dipole''' radii = [88000, 90000, 95000, 100000] sigmas = [0.3, 1.5, 0.015, 0.3] dips = np.array([[[1000., 0., 0.]], [[-1000., 0., 0.]], [[0., 1000., 0.]], [[0., -1000., 0.]], [[0., 0., 1000.]], [[0., 0., -1000.]]]) p_locs = np.array([[87000., 0., 0.], [-87000., 0., 0.], [0., 87000., 0.], [0., -87000., 0.], [0., 0., 87000], [0., 0., -87000]]) el_locs = np.array([[[99000., 0., 0.]], [[-99000., 0., 0.]], [[0., 99000., 0.]], [[0., -99000., 0.]], [[0., 0., 99000.]], [[0., 0., -99000.]]]) for i in range(len(p_locs)): fs = LFPy.FourSphereVolumeConductor(radii, sigmas, el_locs[i]) phi = fs.calc_potential(dips[i], p_locs[i]) if i == 0: phi0 = phi[0][0] else: np.testing.assert_equal(phi0, phi[0][0])
def make_simple_class_object(): '''Return class object fs''' radii = [1., 2., 4., 8.] sigmas = [1., 2., 4., 8.] rz1 = np.array([0., 0., .9]) r_el = np.array([[0., 0., 1.5]]) fs = LFPy.FourSphereVolumeConductor(radii, sigmas, r_el) fs._rz_params(rz1) return fs
def loadResults(experiment_id, filename, population_sizes, Z, tstop, dt, individual_EEG): print("\nLoading results...") # Summed current dipole moments and EEG summed_EEG_top = np.zeros(int(tstop / dt + 1)) if individual_EEG == False: summed_dipole = np.zeros((int(tstop / dt + 1), 3)) # CDM / EEG if individual_EEG: summed_EEG_top = pickle.load(open( '../multicompartment_network/results/' + experiment_id + "/" + filename + "_EEG", "rb"), encoding='latin1') summed_dipole = [] else: summed_dipole = np.array( pickle.load(open( '../multicompartment_network/results/' + experiment_id + "/" + filename + "_CDM", "rb"), encoding='latin1')) # Backward compatibility if len(summed_dipole[0]) > 3: summed_dipole = np.transpose(summed_dipole) # tvec tvec = pickle.load(open( '../multicompartment_network/results/' + experiment_id + "/" + filename + "tvec", "rb"), encoding='latin1') # Sum all CDMs and compute the EEG if individual_EEG == False: import LFPy print("\nComputing EEG...") # Simulation parameters sim_params = pickle.load(open( '../multicompartment_network/results/'+\ experiment_id+"/"+filename+str(0),"rb") ,encoding='latin1') # EEG: four_sphere parameters radii = sim_params["radii"] sigmas = sim_params["sigmas"] rad_tol = sim_params["rad_tol"] r_mid = np.array([0., 0., 8500]) eeg_coords_top = np.array([[0., 0., radii[3] - rad_tol]]) four_sphere_top = LFPy.FourSphereVolumeConductor( radii, sigmas, eeg_coords_top) pot_db_4s_top = four_sphere_top.calc_potential(summed_dipole, r_mid) summed_EEG_top = (np.array(pot_db_4s_top) * 1e6)[0] # Return results return [summed_dipole, summed_EEG_top, tvec]
def test_rz_params(self): radii = [1., 2., 4., 8.] sigmas = [1., 2., 4., 8.] r_el = np.array([[1., 0., 7.]]) fs = LFPy.FourSphereVolumeConductor(radii, sigmas, r_el) rz1 = np.array([0., 0., 0.]) with np.testing.assert_raises(RuntimeError): fs._rz_params(rz1) rz2 = np.array([0., 0., 1.]) with np.testing.assert_raises(RuntimeError): fs._rz_params(rz2) rz3 = np.array([0., 0., 1.2]) with np.testing.assert_raises(RuntimeError): fs._rz_params(rz3)
def test_calc_potential(self): '''test comparison between four-sphere model and model for infinite homogeneous space when sigma is constant and r4 goes to infinity''' sigmas = [0.3, 0.3, 0.3 + 1e-16, 0.3] radii = [10., 20 * 1e6, 30. * 1e6, 40. * 1e6] rz = np.array([0., 0., 3.]) p = np.array([[0., 0., 100.], [50., 50., 0.]]) r_elec = np.array([[0., 0., 9.], [0., 0., 15.], [0., 0., 25.], [0., 0., 40.], [0., 9., 0.], [0., 15., 0.], [0., 25., 0.], [0., 40., 0.]]) four_s = LFPy.FourSphereVolumeConductor(radii, sigmas, r_elec) pots_4s = four_s.calc_potential(p, rz) inf_s = LFPy.InfiniteVolumeConductor(0.3) pots_inf = inf_s.get_dipole_potential(p, r_elec - rz) np.testing.assert_allclose(pots_4s, pots_inf, rtol=1e-6)
def test_decompose_dipole02(self): '''Test radial and tangential parts of dipole sums to dipole''' radii = [88000, 90000, 95000, 100000] sigmas = [0.3, 1.5, 0.015, 0.3] ps = np.array([[1000., 0., 0.], [-1000., 0., 0.], [0., 1000., 0.], [0., -1000., 0.], [0., 0., 1000.], [0., 0., -1000.], [10., 20., 30.], [-10., -20., -30.]]) p_locs = np.array([[87000., 0., 0.], [-87000., 0., 0.], [0., 87000., 0.], [0., -87000., 0.], [0., 0., 87000.], [0., 0., -87000.], [80000., 2000., 3000.], [-2000., -80000., -3000.]]) el_locs = np.array([[90000., 5000., -5000.]]) fs = LFPy.FourSphereVolumeConductor(radii, sigmas, el_locs) for p_loc in p_locs: fs._rz_params(p_loc) p_rads, p_tans = fs._decompose_dipole(ps) np.testing.assert_equal(p_rads + p_tans, ps)
def test_calc_potential01(self): '''test comparison between analytical 4S-model and FEM simulation''' # load data fem_sim = np.load( os.path.join(LFPy.__path__[0], 'test', 'fem_mix_dip.npz')) pot_fem = fem_sim['pot_fem'] # [µV] p = fem_sim['p'] # [nAµm] rz = fem_sim['rz'] # [µm] radii = fem_sim['radii'] # [µm] sigmas = fem_sim['sigmas'] # [S/cm] ele_coords = fem_sim['ele_coords'] # [µm] fs = LFPy.FourSphereVolumeConductor(radii, sigmas, ele_coords) k_mV_to_muV = 1e3 pot_analytical = fs.calc_potential(p, rz).reshape( (len(ele_coords), )).reshape(pot_fem.shape) * k_mV_to_muV global_error = np.abs(pot_analytical - pot_fem) / (np.max( np.abs(pot_fem))) np.testing.assert_array_less(global_error, 0.01)
def test_calc_phi02(self): '''Test phi: azimuthal angle between rx and rxy, check that theta is not NaN, due to round-off errors''' radii = [79000., 80000., 85000., 100000.] sigmas = [0.3, 0.015, 15, 0.3] rz = np.array([0., 0., 76500.]) r_el = np.array([[1e-5, 0, 99999.], [0, 0.000123, 99998.9], [-5.59822325e3, -9.69640709e3, -9.93712111e4], [99990., 0., 0.001]]) fs = LFPy.FourSphereVolumeConductor(radii, sigmas, r_el) fs._rz_params(rz) P1 = np.array([[0., 0., 123456789.], [0., 0., 0.05683939], [89892340., 0., -123456789], [0.00004, 0.002, .0987654321], [0., 0., 0.05683939], [0.0003, 0.001, 123456789.], [1e-11, 1e-12, 1000.], [1e-15, 0, 1000.]]) p_rad, p_tan = fs._decompose_dipole(P1) phi = fs.calc_phi(p_tan) np.testing.assert_equal(np.isnan(phi).any(), False)
def test_get_transformation_matrix_00(self): '''Test radial and tangential parts of dipole sums to dipole''' radii = [88000, 90000, 95000, 100000] sigmas = [0.3, 1.5, 0.015, 0.3] dips = np.array([[[1000., 0., 0.]], [[-1000., 0., 0.]], [[0., 1000., 0.]], [[0., -1000., 0.]], [[0., 0., 1000.]], [[0., 0., -1000.]]]) p_locs = np.array([[87000., 0., 0.], [-87000., 0., 0.], [0., 87000., 0.], [0., -87000., 0.], [0., 0., 87000], [0., 0., -87000]]) el_locs = np.array([[[99000., 0., 0.]], [[-99000., 0., 0.]], [[0., 99000., 0.]], [[0., -99000., 0.]], [[0., 0., 99000.]], [[0., 0., -99000.]]]) for i in range(len(p_locs)): fs = LFPy.FourSphereVolumeConductor(el_locs[i], radii, sigmas) phi = fs.get_dipole_potential(dips[i].T, p_locs[i]) M = fs.get_transformation_matrix(p_locs[i]) np.testing.assert_allclose(M @ dips[i].T, phi)
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()')
# if x >= 0: # ax3.text(x, z+5000, r'${}\pi$'.format(theta / np.pi)) # else: # ax3.text(x, z+5000, r'${}\pi$'.format(theta / np.pi), ha='right') ax3.text(x, z + 2500, r'{}'.format(i + 1), ha='center') # dipole location ax3.plot([0], [dipole_position[-1]], 'k.', label='dipole site') ax3.axis('equal') ax3.set_xticks(np.r_[-np.array(foursphereParams['radii']), 0, foursphereParams['radii']]) ax3.set_xticklabels([]) ax3.legend(loc=(0.25, 0.15), frameon=False) # four-sphere volume conductor sphere = LFPy.FourSphereVolumeConductor(**foursphereParams) phi_p = sphere.calc_potential(cell.current_dipole_moment, rz=dipole_position) # import example_parallel_network_plotting as plotting vlimround = draw_lineplot( ax=ax4, data=phi_p * 1E9, unit=r'pV', #mV -> pV unit conversion dt=cell.dt, ztransform=False, T=(0, cell.tstop), color='k', scalebarbasis='log10') # ax4.set_xticklabels([]) ax4.set_yticklabels([r'{}'.format(i + 1) for i in range(phi_p.shape[0])]) ax4.set_ylabel('position')
'record_current': True # syn. current record } synapse = LFPy.Synapse(cell, **synapseParameters) synapse.set_spike_times(np.array([1.])) cell.set_pos(z=somapos[2]) cell.simulate(rec_imem=True, rec_vmem=True, rec_current_dipole_moment=True) # Setting up recording positions elec_z = np.array( [radii[0], (radii[0] + radii[1]) / 2, radii[1], radii[1] + 500]) elec_x = np.zeros(elec_z.shape) elec_y = np.zeros(elec_x.shape) eeg_coords = np.array([elec_x.flatten(), elec_y.flatten(), elec_z.flatten()]).T MD_4s = LFPy.FourSphereVolumeConductor(radii, sigmas, eeg_coords) phi = MD_4s.calc_potential_from_multi_dipoles(cell) * 1e6 # from mV to nV # Plotting results plt.close('all') fig = plt.figure(figsize=[8, 10]) fig.subplots_adjust(left=0.02, hspace=0.5, right=0.98, top=0.95) ax = fig.add_subplot(111, aspect=1, frameon=False, xlim=xlim, ylim=ylim, xticks=[], yticks=[])
import LFPy from plotting_convention import simplify_axes sim_folder = "evoked_cdm" populations = [f for f in os.listdir(join(sim_folder, "cdm")) if os.path.isdir(join(sim_folder, "cdm", f))] # four_sphere properties # From Huang et al. (2013): 10.1088/1741-2560/10/6/066004 sigmas = [0.276, 1.65, 0.01, 0.465] radii = [89000., 90000., 95000., 100000.] rad_tol = 1e-2 eeg_coords_top = np.array([[0., 0., radii[3] - rad_tol]]) four_sphere_top = LFPy.FourSphereVolumeConductor(eeg_coords_top, radii, sigmas) plt.close("all") fig = plt.figure(figsize=[4, 4]) fig.subplots_adjust(hspace=0.4, top=0.8, left=0.2, bottom=0.15, right=0.98) ax1 = fig.add_subplot(111, xlabel="Time (ms)", xlim=[875, 950], ylim=[-0.7, 0.7]) ax1.set_ylabel("$\mu$V", labelpad=-3) ax1.axvline(900, color='gray', lw=0.2) dominating_pops = ["p5(L56)", "p5(L23)", "p6(L4)", "p6(L56)", "p4", "p23" ] sub_pop_groups_dict = {"L5E": ["p5(L56)", "p5(L23)"],
synapse = LFPy.Synapse(cell, **synapse_params) synapse.set_spike_times(np.array([5.])) cell.simulate(rec_imem=True, rec_current_dipole_moment=True) # compute dipole P = cell.current_dipole_moment somapos = np.array([0., 0., 77500]) 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(radii, sigmas, eeg_coords_top) pot_db_4s_top = four_sphere_top.calc_potential(P, r_mid) eeg_top = np.array(pot_db_4s_top) * 1e9 #measurement points # for nice plot use theta_step = 1 and phi_step = 1. NB: Long computation time. theta_step = 5 phi_step = 5 theta, phi_angle = np.mgrid[0.:180.:theta_step, 0.:360.+phi_step:phi_step] num_theta = theta.shape[0] num_phi = theta.shape[1] theta = theta.flatten() phi_angle = phi_angle.flatten() theta_r = np.deg2rad(theta)
def generate_eegs_nyh_n_4s(dip_loc): # get population dipole from hybrid simulation: cdm_file = join('..', "hybrid_EEG_evoked", "evoked_cdm", "summed_cdm.npy") # Only interested in time around evoked potential (875 - 951 ms) P = np.load(cdm_file).T[:, 875:951] # Load New York Head model nyh = LFPy.NYHeadModel() # place dipole and find normal vector P_loc_nyh = nyh.dipole_pos_dict[dip_loc] nyh.set_dipole_pos(dipole_pos=P_loc_nyh) P_loc_idx = nyh.return_closest_idx(P_loc_nyh) norm_vec = nyh.cortex_normals[:, P_loc_idx] # set four-sphere properties # From Huang et al. (2013): 10.1088/1741-2560/10/6/066004 sigmas = [0.276, 1.65, 0.01, 0.465] radii = [89000., 90000., 95000., 100000.] rad_tol = 1e-2 x_eeg, y_eeg, z_eeg = return_equidistal_xyz(224, r=radii[-1] - rad_tol) eeg_coords_4s = np.array([x_eeg, y_eeg, z_eeg]).T # Place the dipole 1000 µm down into cortex dipole_radial_pos = radii[0] - 1000 # find location on 4S # want to find position on brain, such that the location vector is # parallel to norm_vec from nyh. dipole_loc_4s = norm_vec*dipole_radial_pos # Rotate dipole to be aligned with cortex normal P_rot = nyh.rotate_dipole_to_surface_normal(P) elec_dists_4s = np.sqrt(np.sum((eeg_coords_4s - dipole_loc_4s)**2, axis=1)) elec_dists_4s *= 1e-3 # convert from um to mm min_dist_idx = np.argmin(elec_dists_4s) print("Minimum 4o distance {:2.02f} mm".format(elec_dists_4s[min_dist_idx])) time_idx = np.argmax(np.linalg.norm(P_rot, axis=0)) four_sphere = LFPy.FourSphereVolumeConductor(eeg_coords_4s, radii, sigmas) start_4s = time.time() eeg_4s = four_sphere.get_dipole_potential(P_rot, dipole_loc_4s) end_4s = time.time() time_4s = end_4s - start_4s print('execution time 4S:', time_4s) # subtract DC-component dc_comp_4s = np.mean(eeg_4s[:, 0:25], axis=1) dc_comp_4s = np.expand_dims(dc_comp_4s, 1) eeg_4s -= dc_comp_4s eeg_4s *= 1e3 # from mV to uV # calculate EEGs with NYHeadModel start_nyh = time.time() eeg_nyh = nyh.get_transformation_matrix() @ P_rot # pV end_nyh = time.time() time_nyh = end_nyh - start_nyh print('execution time NYH:', time_nyh) # subtract DC-component dc_comp_nyh = np.mean(eeg_nyh[:, 0:25], axis=1) dc_comp_nyh = np.expand_dims(dc_comp_nyh, 1) eeg_nyh -= dc_comp_nyh # from mV to uV eeg_nyh *= 1e3 elec_dists_nyh = (np.sqrt(np.sum((np.array(nyh.dipole_pos)[:, None] - np.array(nyh.elecs[:3, :]))**2, axis=0))) eeg_coords_nyh = nyh.elecs dist, closest_elec_idx = nyh.find_closest_electrode() print("Closest electrode to dipole: {:1.2f} mm".format(dist)) tvec = np.arange(P.shape[1]) + 875 np.savez('../data/figure7_%s.npz' % dip_loc, radii = radii, p_rot = P_rot, p_loc_4s = dipole_loc_4s, p_loc_nyh = P_loc_nyh, eeg_coords_4s = eeg_coords_4s, eeg_coords_nyh = eeg_coords_nyh, elec_dists_4s = elec_dists_4s, elec_dists_nyh = elec_dists_nyh, eeg_4s = eeg_4s, eeg_nyh = eeg_nyh, time_idx = time_idx, tvec= tvec, )
def make_data(morphology, cell_model, rot, rz, radii, sigmas, electrode_locs, syn_idcs, spiking, syn_input_time): # set cell and synapse parameters cell_parameters, synapse_parameters = set_parameters( morphology, cell_model, spiking) [xrot, yrot, zrot] = rot # create four-sphere class instance fs = LFPy.FourSphereVolumeConductor(electrode_locs, radii=radii, sigmas=sigmas) # lists for storing data: p_list = [] t_max_list = [] p_loc_list = [] lfp_single_dip_list = [] lfp_multi_dip_list = [] RE_list = [] synlocs = [] pz_traces = [] # get data from num_syns simulations num_syns = len(syn_idcs) for j in range(num_syns): cell = create_cell(cell_parameters, active=spiking, x_rot=xrot, y_rot=yrot, z_rot=zrot) ## if you know synidx: syn_idx = syn_idcs[j] # if you only know synapse location: # syn_loc = syn_idcs[j] # syn_idx = cell.get_closest_idx(x=syn_loc[0], y=syn_loc[1], z=syn_loc[2]) # print('syn_idx:', syn_idx) cell, synapse = simulate(cell, synapse_parameters, [syn_idx], syn_input_time) # print('cell simulated') cell.set_pos(x=rz[0], y=rz[1], z=rz[2]) syn_loc = (cell.x[syn_idx].mean(), cell.y[syn_idx].mean(), cell.z[syn_idx].mean()) synlocs.append((syn_loc[0], syn_loc[1], syn_loc[2])) # compute current dipole moment and subtract DC-component cdm = LFPy.CurrentDipoleMoment(cell) dipoles = cdm.get_transformation_matrix() @ cell.imem input_idx_before_input = np.argmin( np.abs(cell.tvec - syn_input_time)) - 1 p_dc = dipoles[:, input_idx_before_input] dipoles -= p_dc[:, None] pz_traces.append(dipoles[2, :]) # compute timepoint with biggest dipole timemax = [np.argmax(np.linalg.norm(np.abs(dipoles), axis=0))] t_max_list.append(timemax) p = dipoles[:, timemax] # compute LFP with single dipole # dip_loc = get_mass_center(cell, timemax) dip_loc = get_dipole_loc(rz, syn_loc) lfp_single_dip = fs.get_transformation_matrix(dip_loc) @ p # print('pot from single dip computed') # compute LFP with multi-dipole # subtract DC-component multi_p_319, multi_p_locs = cell.get_multi_current_dipole_moments( [input_idx_before_input]) multi_p_dc = multi_p_319 multi_p, multi_p_locs = cell.get_multi_current_dipole_moments(timemax) multi_p -= multi_p_dc Ni, Nd, Nt = multi_p.shape lfp_multi_dip = np.zeros((len(electrode_locs), Nt)) for num in range(Ni): pot = fs.get_transformation_matrix( multi_p_locs[num]) @ multi_p[num] # fs.calc_potential(multi_p[num], multi_p_locs[num]) lfp_multi_dip += pot # print('pot from multi dip computed') # compute relative errors RE = np.abs((lfp_single_dip - lfp_multi_dip) / lfp_multi_dip) print('syn number: {}; syn dist from soma: {}; RE_EEG: {}'.format( syn_idx, syn_loc[2] - rz[2], RE[-1])) #add data to lists for storage p_list.append(p) p_loc_list.append(dip_loc) lfp_single_dip_list.append(lfp_single_dip) lfp_multi_dip_list.append(lfp_multi_dip) RE_list.append(RE) # Do this for only one cell for plotting zips = [] for x, z in cell.get_idx_polygons(): zips.append(list(zip(x, z))) zmax = np.max(cell.z) soma_vmem = cell.vmem[0] tvec = cell.tvec return (p_list, pz_traces, lfp_multi_dip_list, lfp_single_dip_list, synlocs, zips, zmax, tvec, soma_vmem)
def generate_eegs_nyh_n_4s(dip_loc): # set 4S properties # From Huang et al. (2013): 10.1088/1741-2560/10/6/066004 sigmas = [0.276, 1.65, 0.01, 0.465] radii = [89000., 90000., 95000., 100000.] print('sigmas:', sigmas) rad_tol = 1e-2 P_loc_4s_length = radii[0] - 1000 x_eeg, y_eeg, z_eeg = return_equidistal_xyz(224, r=radii[-1] - rad_tol) eeg_coords_4s = np.array([x_eeg, y_eeg, z_eeg]).T # get population dipole nyh = NYHeadModel() # hybrid current dipole moment nyh.load_hybrid_current_dipole() P = nyh.dipole_moment.T[875:951, :] # place dipole and find normal vector P_loc_nyh = nyh.dipole_pos_dict[dip_loc] nyh.set_dipole_pos(dipole_pos_0=P_loc_nyh) P_loc_idx = nyh.return_closest_idx(P_loc_nyh) norm_vec = nyh.cortex_normals[:, P_loc_idx] # find location on 4S # want to find position on brain, such that the location vector is # parallel to norm_vec from nyh. # length of position vector P_loc_4s = norm_vec * P_loc_4s_length P_rot = nyh.rotate_dipole_moment().T[875:951, :] # use this when comparing execution times elec_dists_4s = np.sqrt(np.sum((eeg_coords_4s - P_loc_4s)**2, axis=1)) elec_dists_4s *= 1e-3 # convert from um to mm min_dist_idx = np.argmin(elec_dists_4s) print("Minimum 4o distance {:2.02f} mm".format( elec_dists_4s[min_dist_idx])) time_idx = np.argmax(np.linalg.norm(P_rot, axis=1)) # if execution times: # time_idx = np.argmax(np.linalg.norm(P_rot[875:951,:], axis=1)) # potential in 4S with db four_sphere = LFPy.FourSphereVolumeConductor(radii, sigmas, eeg_coords_4s) start_4s = time.time() eeg_4s = four_sphere.calc_potential(P_rot, P_loc_4s) #[:,0] end_4s = time.time() time_4s = end_4s - start_4s # when comparing execution times: # eeg_4s = eeg_4s[:, 875:951] print('execution time 4S:', time_4s) # subtract DC-component dc_comp_4s = np.mean(eeg_4s[:, 0:25], axis=1) dc_comp_4s = np.expand_dims(dc_comp_4s, 1) eeg_4s -= dc_comp_4s eeg_4s *= 1e3 # from mV to uV # calculate EEGs with NYHeadModel start_nyh = time.time() nyh.calculate_eeg_signal(normal=True) end_nyh = time.time() time_nyh = end_nyh - start_nyh print('execution time NYH:', time_nyh) eeg_nyh = nyh.eeg[:, 875:951] # pV # subtract DC-component dc_comp_nyh = np.mean(eeg_nyh[:, 0:25], axis=1) dc_comp_nyh = np.expand_dims(dc_comp_nyh, 1) eeg_nyh -= dc_comp_nyh # from pV to uV eeg_nyh *= 1e-6 elec_dists_nyh = (np.sqrt( np.sum((np.array(nyh.dipole_pos)[:, None] - np.array(nyh.elecs[:3, :]))**2, axis=0))) eeg_coords_nyh = nyh.elecs # some info # max_eeg = np.max(np.abs(eeg_nyh[:, time_idx])) # max_eeg_idx = np.argmax(np.abs(eeg_nyh[:, time_idx])) # max_eeg_pos = eeg_coords_nyh[:3, max_eeg_idx] dist, closest_elec_idx = nyh.find_closest_electrode() print("Closest electrode to dipole: {:1.2f} mm".format(dist)) tvec = np.arange(P.shape[0]) + 875 np.savez( '../data/figure7_%s.npz' % dip_loc, radii=radii, p_rot=P_rot, p_loc_4s=P_loc_4s, p_loc_nyh=P_loc_nyh, eeg_coords_4s=eeg_coords_4s, eeg_coords_nyh=eeg_coords_nyh, elec_dists_4s=elec_dists_4s, elec_dists_nyh=elec_dists_nyh, eeg_4s=eeg_4s, eeg_nyh=eeg_nyh, time_idx=time_idx, tvec=tvec, )