def run(self): """Run the simulation: if beginning from a blank state, then will use h.run(), if continuing from the saved state, then will use h.continuerun() """ for mod in self._sim_mods: if isinstance(mod, mods.ClampReport): if mod.variable == "se": mod.initialize(self, self._seclamps) elif mod.variable == "ic": mod.initialize(self, self._iclamps) elif mod.variable == "f_ic": mod.initialize(self, self._f_iclamps) else: mod.initialize(self) self.start_time = h.startsw() s_time = time.time() pc.timeout(0) pc.barrier() # wait for all hosts to get to this point io.log_info('Running simulation for {:.3f} ms with the time step {:.3f} ms'.format(self.tstop, self.dt)) io.log_info('Starting timestep: {} at t_sim: {:.3f} ms'.format(self.tstep, h.t)) io.log_info('Block save every {} steps'.format(self.nsteps_block)) if self._start_from_state: h.continuerun(h.tstop) else: h.run(h.tstop) # <- runs simuation: works in parallel pc.barrier() for mod in self._sim_mods: mod.finalize(self) pc.barrier() end_time = time.time() sim_time = self.__elapsed_time(end_time - s_time) io.log_info('Simulation completed in {} '.format(sim_time))
def from_config(cls, config, network, set_recordings=True): # TODO: convert from json to sonata config if necessary sim = cls(network=network, dt=config.dt, tstop=config.tstop, v_init=config.v_init, celsius=config.celsius, cao0=config.cao0, optocell=config.optocell, nsteps_block=config.block_step) network.io.log_info('Building cells.') network.build_nodes() network.io.log_info('Building recurrent connections') network.build_recurrent_edges() # TODO: Need to create a gid selector for sim_input in inputs.from_config(config): node_set = network.get_node_set(sim_input.node_set) if sim_input.input_type == 'spikes': spikes = spike_trains.SpikesInput.load( name=sim_input.name, module=sim_input.module, input_type=sim_input.input_type, params=sim_input.params) io.log_info('Build virtual cell stimulations for {}'.format( sim_input.name)) network.add_spike_trains(spikes, node_set) elif sim_input.module == 'IClamp': # TODO: Parse from csv file amplitude = sim_input.params['amp'] delay = sim_input.params['delay'] duration = sim_input.params['duration'] gids = sim_input.params['node_set'] sim.attach_current_clamp(amplitude, delay, duration, node_set) elif sim_input.module == 'xstim': sim.add_mod(mods.XStimMod(**sim_input.params)) else: io.log_exception('Can not parse input format {}'.format( sim_input.name)) if config.calc_ecp: for gid, cell in network.cell_type_maps('biophysical').items(): cell.setup_ecp() sim.h.cvode.use_fast_imem(1) # Parse the "reports" section of the config and load an associated output module for each report sim_reports = reports.from_config(config) for report in sim_reports: if isinstance(report, reports.SpikesReport): mod = mods.SpikesMod(**report.params) elif isinstance(report, reports.SectionReport): mod = mods.SectionReport(**report.params) elif isinstance(report, reports.MembraneReport): if report.params['sections'] == 'soma': mod = mods.SomaReport(**report.params) else: mod = mods.MembraneReport(**report.params) elif isinstance(report, reports.ECPReport): assert config.calc_ecp mod = mods.EcpMod(**report.params) # Set up the ability for ecp on all relevant cells # TODO: According to spec we need to allow a different subset other than only biophysical cells # for gid, cell in network.cell_type_maps('biophysical').items(): # cell.setup_ecp() elif report.module == 'save_synapses': mod = mods.SaveSynapses(**report.params) else: # TODO: Allow users to register customized modules using pymodules io.log_warning('Unrecognized module {}, skipping.'.format( report.module)) continue sim.add_mod(mod) return sim
def from_config(cls, config, network, set_recordings=True): # TODO: convert from json to sonata config if necessary #The network must be built before initializing the simulator because #gap junctions must be set up before the simulation is initialized. network.io.log_info('Building cells.') network.build_nodes() network.io.log_info('Building recurrent connections') network.build_recurrent_edges() sim = cls(network=network, dt=config.dt, tstop=config.tstop, v_init=config.v_init, celsius=config.celsius, nsteps_block=config.block_step) # TODO: Need to create a gid selector for sim_input in inputs.from_config(config): try: network.get_node_set(sim_input.node_set) except: print( "Parameter node_set must be given in inputs module of simulation_config file. If unsure of what node_set should be, set it to 'all'." ) node_set = network.get_node_set(sim_input.node_set) if sim_input.input_type == 'spikes': io.log_info('Building virtual cell stimulations for {}'.format( sim_input.name)) path = sim_input.params['input_file'] spikes = SpikeTrains.load(path=path, file_type=sim_input.module, **sim_input.params) network.add_spike_trains(spikes, node_set) elif sim_input.module == "FileIClamp": sim.attach_file_current_clamp(sim_input.params["input_file"]) elif sim_input.module == 'IClamp': # TODO: Parse from csv file try: len(sim_input.params['amp']) except: sim_input.params['amp'] = [float(sim_input.params['amp'])] if len(sim_input.params['amp']) > 1: sim_input.params['amp'] = [ float(i) for i in sim_input.params['amp'] ] try: len(sim_input.params['delay']) except: sim_input.params['delay'] = [ float(sim_input.params['delay']) ] if len(sim_input.params['delay']) > 1: sim_input.params['delay'] = [ float(i) for i in sim_input.params['delay'] ] try: len(sim_input.params['duration']) except: sim_input.params['duration'] = [ float(sim_input.params['duration']) ] if len(sim_input.params['duration']) > 1: sim_input.params['duration'] = [ float(i) for i in sim_input.params['duration'] ] amplitude = sim_input.params['amp'] delay = sim_input.params['delay'] duration = sim_input.params['duration'] try: sim_input.params['gids'] except: sim_input.params['gids'] = None if sim_input.params['gids'] is not None: gids = sim_input.params['gids'] else: gids = list(node_set.gids()) sim.attach_current_clamp(amplitude, delay, duration, gids) elif sim_input.module == "SEClamp": try: len(sim_input.params['amps']) except: sim_input.params['amps'] = [ float(sim_input.params['amps']) ] try: len(sim_input.params['durations']) except: sim_input.params['durations'] = [ float(sim_input.params['durations']) ] amplitudes = sim_input.params['amps'] durations = sim_input.params['durations'] rs = None if "rs" in sim_input.params.keys(): try: len(sim_input.params['rs']) except: sim_input.params['rs'] = [ float(sim_input.params['rs']) ] if len(sim_input.params['rs']) > 1: sim_input.params['rs'] = [ float(i) for i in sim_input.params['rs'] ] rs = sim_input.params["rs"] try: sim_input.params['gids'] except: sim_input.params['gids'] = None if sim_input.params['gids'] is not None: gids = sim_input.params['gids'] else: gids = list(node_set.gids()) sim.attach_se_voltage_clamp(amplitudes, durations, gids, rs) elif sim_input.module == 'xstim': sim.add_mod(mods.XStimMod(**sim_input.params)) else: io.log_exception('Can not parse input format {}'.format( sim_input.name)) # Parse the "reports" section of the config and load an associated output module for each report sim_reports = reports.from_config(config) for report in sim_reports: if isinstance(report, reports.SpikesReport): mod = mods.SpikesMod(**report.params) elif report.module == 'netcon_report': mod = mods.NetconReport(**report.params) elif isinstance(report, reports.MembraneReport): if report.params['sections'] == 'soma': mod = mods.SomaReport(**report.params) else: mod = mods.MembraneReport(**report.params) elif isinstance(report, reports.ClampReport): mod = mods.ClampReport(**report.params) elif isinstance(report, reports.ECPReport): mod = mods.EcpMod(**report.params) # Set up the ability for ecp on all relevant cells # TODO: According to spec we need to allow a different subset other than only biophysical cells for gid, cell in network.cell_type_maps('biophysical').items(): cell.setup_ecp() elif report.module == 'save_synapses': mod = mods.SaveSynapses(**report.params) else: # TODO: Allow users to register customized modules using pymodules io.log_warning('Unrecognized module {}, skipping.'.format( report.module)) continue sim.add_mod(mod) return sim
def _activate_hln(self, sim, block_interval, firing_rate): block_length = sim.nsteps_block * sim.dt / 1000.0 next_block_tstart = (block_interval[1] + 1) * sim.dt / 1000.0 # The next time-step next_block_tstop = next_block_tstart + block_length # The time-step when the next block ends # This is where you can use the firing-rate of the low-level neurons to generate a set of spike times for the # next block if firing_rate > 0.0: psg = PoissonSpikeGenerator() # # Use homogeneous input # psg.add(node_ids=[0], firing_rate=firing_rate, times=(next_block_tstart, next_block_tstop)) # sec # spikes = psg.get_times([0])*1000 # convert sec to ms # n_spikes = len(spikes) # io.log_info(' _activate_hln firing rate: {:.2f} Hz'.format(n_spikes/block_length)) # if n_spikes > 0: # # Update firing rate of bladder afferent neurons # for gid in self._high_level_neurons: # self._spike_events[gid] = np.concatenate((self._spike_events[gid],spikes)) # nc = self._netcons[gid] # for t in spikes: # nc.event(t) # io.log_info('Last spike: {:.1f} ms'.format(spikes[-1])) # Use inhomogeneous input n = len(self._high_level_neurons) psg.add(node_ids=self._high_level_neurons, firing_rate=firing_rate, times=(next_block_tstart, next_block_tstop)) n_spikes = np.zeros(n) last_spike = 0.0 for i, gid in enumerate(self._high_level_neurons): spikes = psg.get_times(gid) * 1000 n_spikes[i] = len(spikes) if n_spikes[i] > 0: self._spike_events[gid] = np.concatenate( (self._spike_events[gid], spikes)) nc = self._netcons[gid] for t in spikes: nc.event(t) last_spike = max(last_spike, spikes[-1]) io.log_info( ' _activate_hln firing rate: ' + ','.join(["%.2f" % (ns / block_length) for ns in n_spikes]) + ' Hz') if last_spike > 0: io.log_info('Last spike: {:.1f} ms'.format(last_spike)) else: io.log_info(' _activate_hln firing rate: 0') # If pressure is maxxed, update firing rate of EUS motor neurons # Guarding reflex # press_change = self._prev_glob_press - self._glob_press # if self._glob_press > press_thres or press_change > change_thres: # psg = PoissonSpikeGenerator() # eus_fr = self._glob_press*10 + press_change*10 # Assumption: guarding reflex # # depends on current pressure # # and change from last pressure # psg.add(node_ids=[0], firing_rate=eus_fr, times=(next_block_tstart, next_block_tstop)) # self._spike_events = psg.get_times(0) # for gid in self._eus_neurons: # nc = self._netcons[gid] # for t in self._spike_events: # nc.event(t) ################ Activate higher order based on pressure threshold ############################## # if block_interval[1] % 2000 == 1000: # For fast testing, only add events to every other block # if False: # For testing # if self._glob_press > self.press_thres: # io.log_info(' updating pag input') # psg = PoissonSpikeGenerator() # print(self.press_thres) # # pag_fr = self.press_thres #change # psg.add(node_ids=[0], firing_rate=pag_fr, times=(next_block_tstart/1000.0, next_block_tstop/1000.0)) # if psg.n_spikes() <= 0: # io.log_info(' no psg spikes generated by Poisson distritubtion') # self._spike_events = psg.get_times(0) # for gid in self._pag_neurons: # nc = self._netcons[gid] # for t in self._spike_events: # nc.event(t) ################ Activate higher order based on afferent firing rate ############################## if firing_rate > 10: pag_fr = 15 psg = PoissonSpikeGenerator() # # Use homogeneous input # psg.add(node_ids=[0], firing_rate=pag_fr, times=(next_block_tstart, next_block_tstop)) # spikes = psg.get_times([0])*1000 # n_spikes = len(spikes) # io.log_info(' pag firing rate: {:.2f} Hz'.format(n_spikes/block_length)) # if n_spikes>0: # io.log_info('Last spike: {:.1f} ms'.format(spikes[-1])) # for gid in self._pag_neurons: # self._spike_events[gid] = np.concatenate((self._spike_events[gid],spikes)) # nc = self._netcons[gid] # for t in spikes: # nc.event(t) # Use inhomogeneous input n = len(self._pag_neurons) psg.add(node_ids=self._pag_neurons, firing_rate=pag_fr, times=(next_block_tstart, next_block_tstop)) n_spikes = np.zeros(n) last_spike = 0.0 for i, gid in enumerate(self._pag_neurons): spikes = psg.get_times(gid) * 1000 n_spikes[i] = len(spikes) if n_spikes[i] > 0: self._spike_events[gid] = np.concatenate( (self._spike_events[gid], spikes)) nc = self._netcons[gid] for t in spikes: nc.event(t) last_spike = max(last_spike, spikes[-1]) io.log_info( ' pag firing rate: ' + ','.join(["%.2f" % (ns / block_length) for ns in n_spikes]) + ' Hz') if last_spike > 0: io.log_info('Last spike: {:.1f} ms'.format(last_spike)) io.log_info('\n')
def block(self, sim, block_interval): """This function is called every n steps during the simulation, as set in the config.json file (run/nsteps_block). We can use this to get the firing rate of PGN during the last block and use it to calculate firing rate for bladder afferent neuron """ # Calculate the avg number of spikes per neuron block_length = sim.nsteps_block * sim.dt / 1000.0 # time length of previous block of simulation TODO: precalcualte /1000 n_gids = 0 n_spikes = 0 for gid, tvec in self._spike_records.items(): n_gids += 1 n_spikes += len( list(tvec) ) # use tvec generator. Calling this deletes the values in tvec # Calculate the firing rate the the low-level neuron(s) avg_spikes = n_spikes / (float(n_gids) * 1.0) fr = avg_spikes / float(block_length) # Grill function for polynomial fit according to PGN firing rate # Grill, et al. 2016 def pgn_fire_rate(x): f = 2.0E-03 * x**3 - 3.3E-02 * x**2 + 1.8 * x - 0.5 f = max(f, 0.0) return f # Grill function for polynomial fit according to bladder volume # Grill, et al. 2016 def blad_vol(vol): f = 1.5 * 20 * vol - 10 #1.5*20*vol-10 return f # Grill function returning pressure in units of cm H20 # Grill, et al. 2016 def pressure(fr, v): p = 0.2 * fr + 1.0 * v p = max(p, 0.0) return p # Grill function returning bladder afferent firing rate in units of Hz # Grill, et al. 2016 def blad_aff_fr(p): fr1 = -3.0E-08 * p**5 + 1.0E-5 * p**4 - 1.5E-03 * p**3 + 7.9E-02 * p**2 - 0.6 * p fr1 = max(fr1, 0.0) return fr1 # Using scaling factor of 5 here to get the correct firing rate range # Calculate bladder volume using Grill's polynomial fit equation v_init = 0.05 # TODO: get biological value for initial bladder volume fill = 0.05 # ml/min (Asselt et al. 2017) fill /= (1000 * 60) # Scale from ml/min to ml/ms void = 4.6 # ml/min (Streng et al. 2002) void /= (1000 * 60) # Scale from ml/min to ml/ms max_v = 1.5 # ml (Grill et al. 2019) #0.76 vol = v_init # Update blad aff firing rate t = sim.h.t - block_length * 1000.0 PGN_fr = pgn_fire_rate(fr) # Filling: 0 - 7000 ms # if t < 7000 and vol < max_v: # vol = fill*t*150 + v_init # Filling: 0 - 54000 ms if t < 60000 and vol < max_v: vol = fill * t * 20 + v_init # # Voiding: 7000 - 10,000 ms # else: # vol = max_v - void*(10000-t)*100 # Voiding: 54000 - 60000 ms # else: # vol = max_v - void*(60000-t)*100 # Maintain minimum volume if vol < v_init: vol = v_init grill_vol = blad_vol(vol) # Calculate pressure using Grill equation p = pressure(PGN_fr, grill_vol) # Update global pressure (to be used to determine if EUS motor # needs to be updated for guarding reflex) self._prev_glob_press = self._glob_press self._glob_press = p # Calculate bladder afferent firing rate using Grill equation bladaff_fr = blad_aff_fr(p) io.log_info('PGN firing rate = %.2f Hz' % fr) io.log_info('Volume = %.2f ml' % vol) io.log_info('Pressure = %.2f cm H20' % p) io.log_info( 'Bladder afferent firing rate = {:.2f} Hz'.format(bladaff_fr)) # Save values in appropriate lists self.times.append(t) self.b_vols.append(vol) self.b_pres.append(p) # b_aff.append(bladaff_fr) # pgn_fir.append(fr) # Set the activity of high-level neuron self._activate_hln(sim, block_interval, bladaff_fr) # NEURON requires resetting NetCon.record() every time we read the tvec. pc.barrier() self._set_spike_detector(sim)
def from_config(cls, config, network, set_recordings=True): simulation_inputs = inputs.from_config(config) # Special case for setting synapses to spontaneously (for a given set of pre-synaptic cell-types). Using this # input will change the way the network builds cells/connections and thus needs to be set first. for sim_input in simulation_inputs: if sim_input.input_type == 'syn_activity': network.set_spont_syn_activity( precell_filter=sim_input.params['precell_filter'], timestamps=sim_input.params['timestamps'] ) # The network must be built before initializing the simulator because # gap junctions must be set up before the simulation is initialized. network.io.log_info('Building cells.') network.build_nodes() network.io.log_info('Building recurrent connections') network.build_recurrent_edges() sim = cls(network=network, dt=config.dt, tstop=config.tstop, v_init=config.v_init, celsius=config.celsius, nsteps_block=config.block_step) # TODO: Need to create a gid selector for sim_input in inputs.from_config(config): try: network.get_node_set(sim_input.node_set) except: print("Parameter node_set must be given in inputs module of simulation_config file. If unsure of what node_set should be, set it to 'all'.") node_set = network.get_node_set(sim_input.node_set) if sim_input.input_type == 'spikes': io.log_info('Building virtual cell stimulations for {}'.format(sim_input.name)) path = sim_input.params['input_file'] spikes = SpikeTrains.load(path=path, file_type=sim_input.module, **sim_input.params) network.add_spike_trains(spikes, node_set) elif sim_input.module == "FileIClamp": sim.attach_file_current_clamp(sim_input.params["input_file"]) elif sim_input.module == 'IClamp': # TODO: Parse from csv file try: len(sim_input.params['amp']) except: sim_input.params['amp']=[float(sim_input.params['amp'])] if len(sim_input.params['amp'])>1: sim_input.params['amp']=[float(i) for i in sim_input.params['amp']] try: len(sim_input.params['delay']) except: sim_input.params['delay']=[float(sim_input.params['delay'])] if len(sim_input.params['delay'])>1: sim_input.params['delay']=[float(i) for i in sim_input.params['delay']] try: len(sim_input.params['duration']) except: sim_input.params['duration']=[float(sim_input.params['duration'])] if len(sim_input.params['duration'])>1: sim_input.params['duration']=[float(i) for i in sim_input.params['duration']] amplitude = sim_input.params['amp'] delay = sim_input.params['delay'] duration = sim_input.params['duration'] # specificed for location to place iclamp hobj.<section_name>[<section_index>](<section_dist>). The # default is hobj.soma[0](0.5), the center of the soma section_name = sim_input.params.get('section_name', 'soma') section_index = sim_input.params.get('section_index', 0) section_dist = sim_input.params.get('section_dist', 0.5) # section_name = section_name if isinstance(section_name, (list, tuple)) else [section_name] # section_index = section_index if isinstance(section_index, (list, tuple)) else [section_index] # section_dist = section_dist if isinstance(section_dist, (list, tuple)) else [section_dist] try: sim_input.params['gids'] except: sim_input.params['gids'] = None if sim_input.params['gids'] is not None: gids = sim_input.params['gids'] else: gids = list(node_set.gids()) sim.attach_current_clamp(amplitude, delay, duration, gids, section_name, section_index, section_dist) elif sim_input.module == "SEClamp": try: len(sim_input.params['amps']) except: sim_input.params['amps']=[float(sim_input.params['amps'])] try: len(sim_input.params['durations']) except: sim_input.params['durations']=[float(sim_input.params['durations'])] amplitudes = sim_input.params['amps'] durations = sim_input.params['durations'] rs = None if "rs" in sim_input.params.keys(): try: len(sim_input.params['rs']) except: sim_input.params['rs']=[float(sim_input.params['rs'])] if len(sim_input.params['rs'])>1: sim_input.params['rs']=[float(i) for i in sim_input.params['rs']] rs = sim_input.params["rs"] try: sim_input.params['gids'] except: sim_input.params['gids'] = None if sim_input.params['gids'] is not None: gids = sim_input.params['gids'] else: gids = list(node_set.gids()) sim.attach_se_voltage_clamp(amplitudes, durations, gids, rs) elif sim_input.module == 'xstim': sim.add_mod(mods.XStimMod(**sim_input.params)) elif sim_input.module == 'syn_activity': pass else: io.log_exception('Can not parse input format {}'.format(sim_input.name)) # Parse the "reports" section of the config and load an associated output module for each report sim_reports = reports.from_config(config) for report in sim_reports: if isinstance(report, reports.SpikesReport): mod = mods.SpikesMod(**report.params) elif report.module == 'netcon_report': mod = mods.NetconReport(**report.params) elif isinstance(report, reports.MembraneReport): if report.params['sections'] == 'soma': mod = mods.SomaReport(**report.params) else: mod = mods.MembraneReport(**report.params) elif isinstance(report, reports.ClampReport): mod = mods.ClampReport(**report.params) elif isinstance(report, reports.ECPReport): mod = mods.EcpMod(**report.params) # Set up the ability for ecp on all relevant cells # TODO: According to spec we need to allow a different subset other than only biophysical cells for gid, cell in network.cell_type_maps('biophysical').items(): cell.setup_ecp() elif report.module == 'save_synapses': mod = mods.SaveSynapses(**report.params) else: # TODO: Allow users to register customized modules using pymodules io.log_warning('Unrecognized module {}, skipping.'.format(report.module)) continue sim.add_mod(mod) return sim
def __del__(self): io.log_info('Cleaning up simulation.')
def _activate_hln(self, sim, block_interval, firing_rate): next_block_tstart = (block_interval[1] + 1) * sim.dt # The next time-step next_block_tstop = next_block_tstart + sim.nsteps_block * sim.dt # The time-step when the next block ends # This is where you can use the firing-rate of the low-level neurons to generate a set of spike times for the # next block if firing_rate != 0.0: psg = PoissonSpikeGenerator() psg.add(node_ids=[0], firing_rate=firing_rate, times=(next_block_tstart, next_block_tstop)) if psg.n_spikes() <= 0: io.log_info( ' _activate_hln: firing rate {} did not produce any spikes' .format(firing_rate)) else: self._spike_events = psg.get_times(0) # Update firing rate of bladder afferent neurons for gid in self._high_level_neurons: nc = self._netcons[gid] for t in self._spike_events: nc.event(t) else: io.log_info(' _activate_hln: firing rate 0') # If pressure is maxxed, update firing rate of EUS motor neurons # Guarding reflex # press_change = self._prev_glob_press - self._glob_press # if self._glob_press > press_thres or press_change > change_thres: # psg = PoissonSpikeGenerator() # eus_fr = self._glob_press*10 + press_change*10 # Assumption: guarding reflex # # depends on current pressure # # and change from last pressure # psg.add(node_ids=[0], firing_rate=eus_fr, times=(next_block_tstart, next_block_tstop)) # self._spike_events = psg.get_times(0) # for gid in self._eus_neurons: # nc = self._netcons[gid] # for t in self._spike_events: # nc.event(t) ################ Activate higher order based on pressure threshold ############################## # if block_interval[1] % 2000 == 1000: # For fast testing, only add events to every other block # if False: # For testing if self._glob_press > press_thres: io.log_info(' updating pag input') psg = PoissonSpikeGenerator() print(press_thres) pag_fr = press_thres #change psg.add(node_ids=[0], firing_rate=pag_fr, times=(next_block_tstart / 1000.0, next_block_tstop / 1000.0)) if psg.n_spikes() <= 0: io.log_info( ' no psg spikes generated by Poisson distritubtion') self._spike_events = psg.get_times(0) for gid in self._pag_neurons: nc = self._netcons[gid] for t in self._spike_events: nc.event(t)
def initialize(self, sim): network = sim.net ##### Make sure to save spikes vector and vector stim object # Attach a NetCon/synapse on the high-level neuron(s) soma. We can use the NetCon.event(time) method to send # a spike to the synapse. Which, is a spike occurs, the high-level neuron will inhibit the low-level neuron. self._spikes = h.Vector(np.array([])) # start off with empty input vec_stim = h.VecStim() vec_stim.play(self._spikes) self._vect_stim = vec_stim self._high_level_neurons = list( sim.net.get_node_set('high_level_neurons').gids()) self._pag_neurons = list(sim.net.get_node_set('pag_neurons').gids()) # self._pag_neurons = [i for i in np.arange(50,75)] for gid in self._high_level_neurons: cell = sim.net.get_cell_gid(gid) # Create synapse # These values will determine how the high-level neuron behaves with the input new_syn = h.Exp2Syn(0.5, cell.hobj.soma[0]) new_syn.e = 0.0 new_syn.tau1 = 0.1 new_syn.tau2 = 0.3 nc = h.NetCon(self._vect_stim, new_syn) ##nc = h.NetCon(vec_stim, new_syn) nc.weight[0] = 0.5 nc.delay = 1.0 self._synapses[gid] = new_syn self._netcons[gid] = nc io.log_info('Found {} PAG neurons'.format(len(self._pag_neurons))) for gid in self._pag_neurons: trg_cell = network.get_cell_gid( gid) # network._rank_node_ids['LUT'][51] syn = h.Exp2Syn(0.5, sec=trg_cell.hobj.soma[0]) syn.e = 0.0 syn.tau1 = 0.1 syn.tau2 = 0.3 self._synapses[gid] = syn nc = h.NetCon(self._vect_stim, syn) nc.weight[0] = 0.5 nc.delay = 1.0 self._netcons[gid] = nc # Attach another netcon to the low-level neuron(s) that will record self._low_level_neurons = list( sim.net.get_node_set('low_level_neurons').gids()) for gid in self._low_level_neurons: cell = sim.net.get_cell_gid(gid) # NOTE: If you set the segment to 0.5 it will interfere with the record_spikes module. Neuron won't let # us record from the same place multiple times, so for now just set to 0.0. TODO: read and save spikes in biosimulator. nc = h.NetCon(cell.hobj.soma[0](0.0)._ref_v, None, sec=cell.hobj.soma[0]) self._netcons[gid] = nc self._set_spike_detector(sim)