def make_morphologies(self): """Creating a Morphology object for each biophysical model""" for node in self._local_nodes: if node.cell_type == CellTypes.Biophysical: node_type_id = node.node_type_id morphology_file = node.morphology_file if node_type_id in self.__morphologies_cache: # create a single morphology object for each model_group which share that morphology morph = self.__morphologies_cache[node_type_id] # associate morphology with a cell self._cells[node.node_id].set_morphology(morph) else: hobj = self._cells[ node. node_id].hobj # get hoc object (hobj) from the first cell with a new morphologys morph = Morphology(hobj) # associate morphology with a cell self._cells[node.node_id].set_morphology(morph) # create a single morphology object for each model_group which share that morphology self.__morphologies_cache[node_type_id] = morph io.print2log0(" Created morphologies") self._morphologies_built = True
def make_stims(self): """Create the stims/virtual/external nodes. Make sure spike trains have been set before calling, otherwise it will creating spiking cells with no spikes. """ for network in self._graph.external_networks(): io.print2log0(' %s cells' % network) if network not in self._stim_networks: continue self._stims[network] = {} # Get a list of the external gid's that connect to cells on this node. src_gids_set = set() for trg_gid, trg_cell in self._cells.items(): # TODO: Create a function that can return a list of all src_gids for trg_prop, src_prop, edge_prop in self._graph.edges_iterator( trg_gid, network): src_gids_set.add( src_prop.node_id) # TODO: just store the src_prop # Get the spike trains of each external node and create a Stim object for src_gid in src_gids_set: src_prop = self._graph.get_node(src_gid, network) spike_train = self._get_spike_trains(src_gid, network) self._stims[network][src_gid] = Stim(src_prop, spike_train)
def post_fadvance(self): ''' Runs after every execution of fadvance (see advance.hoc) Called after every time step to perform computation and save data to memory block or to disk. The initial condition tstep=0 is not being saved ''' self.tstep += 1 tstep_block = self.tstep - self.tstep_start_block # time step within a block self.save_data_to_block(tstep_block) if (self.tstep % self.conf["run"]["nsteps_block"] == 0) or self.tstep == self.nsteps: io.print2log0(' step:%d t_sim:%.3f ms' % (self.tstep, h.t)) self.tstep_end_block = self.tstep time_step_interval = (self.tstep_start_block, self.tstep_end_block) io.save_block_to_disk(self.conf, self.data_block, time_step_interval) # block save data self.set_spike_recording() self.tstep_start_block = self.tstep # starting point for the next block
def build_cells(self): """Instantiate cells based on parameters provided in the InternalCell table and Internal CellModel table""" self._select_local_nodes() for node in self._local_nodes: gid = node.node_id if node.cell_type == CellTypes.Biophysical: self._cells[gid] = BioCell(node, self.spike_threshold, self.dL, self.calc_ecp, self._save_connections) self._local_biophys_gids.append(gid) elif node.cell_type == CellTypes.Point: self._cells[gid] = LIFCell(node) elif node.cell_type == CellTypes.Virtual: # Just in case, should never see continue else: io.print2log0('ERROR: not implemented class') # raise NotImplementedError('not implemented cell class') nrn.quit_execution() # TODO: Add ability to easily extend the Cell-Types without hardcoding into this loop!! pc.barrier() # wait for all hosts to get to this point self.make_morphologies() self.set_seg_props() # set segment properties by creating Morphologies # self.set_tar_segs() # set target segments needed for computing the synaptic innervations self.calc_seg_coords() # use for computing the ECP self._cells_built = True
def calc_seg_coords(self): """Needed for the ECP calculations""" for node_type_id, morphology in self.__morphologies_cache.items(): morph_seg_coords = morphology.calc_seg_coords( ) # needed for ECP calculations for node in self._local_node_types[node_type_id]: self._cells[node.node_id].calc_seg_coords(morph_seg_coords) io.print2log0(" Set segment coordinates")
def set_recordings(self): """Set recordings of ECP, spikes and somatic traces""" io.print2log0('Setting up recordings...') if not self._start_from_state: # if starting from a new initial state io.create_output_files(self, self.gids) else: io.extend_output_files(self.gids) io.print2log0('Recordings are set!') pc.barrier()
def set_recurrent_connections(self): self._init_connections() syn_counter = 0 for src_network in self._graph.internal_networks(): io.print2log0( ' Setting connections from {}'.format(src_network)) for trg_gid, trg_cell in self._cells.items(): for trg_prop, src_prop, edge_prop in self._graph.edges_iterator( trg_gid, src_network): syn_counter += trg_cell.set_syn_connection( edge_prop, src_prop)
def set_external_connections(self, source_network): self._init_connections() io.print2log0(' Setting connections from {}'.format(source_network)) # TODO: skip if source_network is not in stims source_stims = self._stims[source_network] syn_counter = 0 for trg_gid, trg_cell in self._cells.items(): for trg_prop, src_prop, edge_prop in self._graph.edges_iterator( trg_gid, source_network): # TODO: reimplement weight function if needed stim = source_stims[src_prop.node_id] syn_counter += trg_cell.set_syn_connection( edge_prop, src_prop, stim) self._total_synapses += syn_counter
def _set_init_conditions(self): """Set up the initial conditions: either read from the h.SaveState or from config["condidtions"]""" pc.set_maxstep(10) h.stdinit() self.tstep = int(round(h.t / h.dt)) self.tstep_start_block = self.tstep if self._start_from_state: # io.read_state() io.print2log0( 'Read the initial state saved at t_sim: {} ms'.format(h.t)) else: h.v_init = self.v_init h.celsius = self.celsius
def set_external_connections(self, source_network): self._init_connections() io.print2log0(' Setting connections from {}'.format(source_network)) source_stims = self._stims[source_network] syn_counter = 0 for trg_gid, trg_cell in self._cells.items(): for trg_prop, src_prop, edge_prop in self._graph.edges_iterator( trg_gid, source_network): # TODO: reimplement weight function if needed stim = source_stims[src_prop.node_id] syn_counter += trg_cell.set_syn_connection( edge_prop, src_prop, stim) for gid in self._local_biophys_gids: print gid print self._cells[gid].print_synapses()
def attach_current_clamp(self, amplitude, delay, duration, gids=None): # TODO: verify current clamp works with MPI if gids is None: gids = self.gids['biophysical'] if isinstance(gids, int): gids = [gids] elif isinstance(gids, basestring): gids = [int(gids)] for gid in gids: if gid not in self.gids['biophysical']: io.print2log0( "Warning: attempting to attach current clamp to non-biophysical gid {}." .format(gid)) cell = self.net.cells[gid] Ic = IClamp(amplitude, delay, duration) Ic.attach_current(cell) self._iclamps.append(Ic)
def set_init_conditions(self): ''' Set up the initial conditions: either read from the h.SaveState or from config["condidtions"] ''' pc.set_maxstep(10) h.stdinit() self.tstep = int(round(h.t / h.dt)) self.tstep_start_block = self.tstep if self._start_from_state == True: io.read_state() io.print2log0('Read the initial state saved at t_sim: %.2f ms' % (h.t)) else: h.v_init = self.conf["conditions"]["v_init"] h.celsius = self.conf["conditions"]["celsius"]
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: 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.print2log0( 'Running simulation for {:.3f} ms with the time step {:.3f} ms'. format(self.tstop, self.dt)) io.print2log0('Starting timestep: {} at t_sim: {:.3f} ms'.format( self.tstep, h.t)) io.print2log0('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.print2log0now('Simulation completed in {} '.format(sim_time))
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() ''' self.start_time = h.startsw() s_time = time.time() pc.timeout(0) # pc.barrier() # wait for all hosts to get to this point io.print2log0( 'Running simulation until tstop: %.3f ms with the time step %.3f ms' % (self.conf["run"]['tstop'], self.conf["run"]['dt'])) io.print2log0('Starting timestep: %d at t_sim: %.3f ms' % (self.tstep, h.t)) io.print2log0('Block save every %d steps' % (self.conf["run"]['nsteps_block'])) if self._start_from_state: h.continuerun(h.tstop) else: h.run(h.tstop) # <- runs simuation: works in parallel pc.barrier() # end_time = time.time() sim_time = self.__elapsed_time(end_time - s_time) io.print2log0now('Simulation completed in {} '.format(sim_time))
def set_recordings(self): ''' Set recordings of ECP, spikes and somatic traces ''' io.print2log0('Setting up recordings...') if self.conf["run"]["calc_ecp"]: self.set_ecp_recording() if not (self._start_from_state ): # if starting from a new initial state io.create_output_files(self.conf, self.gids) else: io.extend_output_files(self.gids) self.create_data_block() self.set_spike_recording() io.print2log0('Recordings are set!') pc.barrier()
def report_load_balance(self): comptime = pc.step_time() print('comptime: ', comptime, pc.allreduce(comptime, 1)) avgcomp = pc.allreduce(comptime, 1) / pc.nhost() maxcomp = pc.allreduce(comptime, 2) io.print2log0('Maximum compute time is {} seconds.'.format(maxcomp)) io.print2log0( 'Approximate exchange time is {} seconds.'.format(comptime - maxcomp)) if maxcomp != 0.0: io.print2log0('Load balance is {}.'.format(avgcomp / maxcomp))
def set_seg_props(self): """Set morphological properties for biophysically (morphologically) detailed cells""" for _, morphology in self.__morphologies_cache.items(): morphology.set_seg_props() io.print2log0(" Set segment properties")
def run(config_file): conf = config.from_json(config_file) # build configuration io.setup_output_dir(conf) # set up output directories nrn.load_neuron_modules(conf) # load NEURON modules and mechanisms nrn.load_py_modules( cell_models=set_cell_params, # load custom Python modules syn_models=set_syn_params, syn_weights=set_weights) graph = BioGraph.from_config( conf, # create network graph containing parameters of the model network_format=TabularNetwork_AI, property_schema=AIPropertySchema) net = BioNetwork.from_config( conf, graph ) # create netwosim = Simulation.from_config(conf, network=net) rk of in NEURON sim = Simulation.from_config(conf, network=net) # initialize a simulation sim.run() # run simulation if MPI_RANK == 0: try: # Check spikes print2log0('Checking spike times') assert (os.path.exists(conf['output']['spikes_ascii_file'])) assert (spike_files_equal(conf['output']['spikes_ascii_file'], 'expected/spikes.txt')) print2log0('Spikes passed!') # Check extracellular recordings print2log0('Checking ECP output') check_ecp() print2log0('ECP passed!') # Check saved variables print2log0('Checking NEURON saved variables') for saved_gids in conf['node_id_selections']['save_cell_vars']: check_cellvars(saved_gids, conf) print2log0('variables passed!') except AssertionError: _, _, tb = sys.exc_info() traceback.print_tb(tb) pc.barrier() nrn.quit_execution() # exit
def _init_connections(self): if not self._connections_initialized: io.print2log0('Initializing connections...') for gid, cell in self._cells.items(): cell.init_connections() self._connections_initialized = True
def from_config(cls, config_file, graph): """A method for building a network from a config file. :param config_file: A json file (or object) with simulation parameters for loading NEURON network. :param graph: A BioGraph object that has already been loaded. :return: A BioNetwork object with nodes and connections that can be ran in a NEURON simulator. """ io.print2log0('Number of processors: {}'.format(nhost)) io.print2log0('Setting up network...') # load the json file or object if isinstance(config_file, basestring): config = cfg.from_json(config_file, validate=True) elif isinstance(config_file, dict): config = config_file else: raise Exception('Could not convert {} (type "{}") to json.'.format( config_file, type(config_file))) network = cls(graph) if 'run' not in config: raise Exception( 'Json file is missing "run" entry. Unable to build Bionetwork.' ) run_dict = config['run'] # Overwrite default network parameters if they exists in the config file if 'spike_threshold' in run_dict: network.spike_threshold = run_dict['spike_threshold'] if 'dL' in run_dict: network.dL = run_dict['dL'] if 'calc_ecp' in run_dict: network.calc_ecp = run_dict['calc_ecp'] # build the cells network.save_connections = config['output'].get('save_synapses', False) io.print2log('Building cells...') network.build_cells() # list of cells who parameters will be saved to h5 if 'node_id_selections' in config and 'save_cell_vars' in config[ 'node_id_selections']: network.save_gids(config['node_id_selections']['save_cell_vars']) # Find and save network stimulation. Do this before loading external/internal connections. if 'input' in config: for netinput in config['input']: if netinput['type'] == 'external_spikes' and netinput[ 'format'] == 'nwb': # Load external network spike trains from an NWB file. # io.print2log0('Load input for {}'.format(netinput['network'])) network.add_spikes_nwb(netinput['source_nodes'], netinput['file'], netinput['trial']) elif netinput['type'] == 'external_spikes' and netinput[ 'format'] == 'csv': network.add_spikes_csv(netinput['source_nodes'], netinput['file']) # TODO: Allow for external spike trains from csv file or user function # TODO: Add Iclamp code. io.print2log0(' Setting up external cells...') network.make_stims() io.print2log0('Cells are built!') for netname in graph.external_networks(): network.set_external_connections(netname) network.set_recurrent_connections() io.print2log0('Network is built!') if network.save_connections: io.print2log0('Saving synaptic connections:') network.write_connections(config['output']['output_dir']) io.print2log0(' Synaptic connections saved to {}.'.format( config['output']['output_dir'])) return network
def scale_weights(self, factor): io.print2log0('Scaling all connection weights') for gid, cell in self.cells.items(): cell.scale_weights(factor)