def _create_NEURON(self, neuron_name): # ----------------------------------------------------------------- # Set up NEURON section # ----------------------------------------------------------------- self.nrn_cell_sec = neuron.h.Section() try: self.nrn_cell = eval( 'neuron.h.{}(0.5, sec=self.nrn_cell_sec)'.format(neuron_name)) except TypeError: self.nrn_cell_sec.insert(neuron_name) self.nrn_cell = getattr(self.nrn_cell_sec(0.5), neuron_name) self.nrn_cell_sec.L = 10 self.nrn_cell_sec.diam = 10 / numpy.pi self.nrn_cell_sec.cm = 1.0 for mech_name in self.extra_mechanisms: self.nrn_cell_sec.insert(mech_name) if self.extra_point_process is not None: MechClass = getattr(neuron.h, self.extra_point_process) self.extra_point_process = MechClass(self.nrn_cell_sec(0.5)) for prop in self.properties.properties: name = prop.name value = prop.value try: varname, scale = self.neuron_translations[name] value = value * scale except (ValueError, KeyError): varname = self.neuron_translations.get(name, name) if varname in self.specific_params: specific_value = UnitHandlerNEURON.to_pq_quantity( Quantity(value, prop.units)) / (100 * (pq.um ** 2)) value = UnitHandlerNEURON.scale_value(specific_value) else: value = UnitHandlerNEURON.scale_value( Quantity(value, prop.units)) if varname is not None: if '.' in varname: mech_name, vname = varname.split('.') try: setattr(getattr(self.nrn_cell_sec(0.5), mech_name), vname, value) except AttributeError: setattr(self.extra_point_process, vname, value) elif varname == 'cm': self.nrn_cell_sec.cm = value else: try: setattr(self.nrn_cell, varname, value) except AttributeError: setattr(self.nrn_cell_sec, varname, value) for name, value in self.initial_states.iteritems(): try: varname, scale = self.neuron_translations[name] value = value * scale except (ValueError, KeyError): varname = self.neuron_translations.get(name, name) value = UnitHandlerNEURON.scale_value( UnitHandlerNEURON.from_pq_quantity(value)) if varname is not None: if '.' in varname: try: setattr(getattr(self.nrn_cell_sec(0.5), mech_name), vname, value) except AttributeError: setattr(self.point_process, vname, value) else: try: setattr(self.nrn_cell, varname, value) except (AttributeError, LookupError): setattr(self.nrn_cell_sec, varname, value) # Specify current injection if self.input_signal is not None: _, signal = self.input_signal self._nrn_iclamp = neuron.h.IClamp(0.5, sec=self.nrn_cell_sec) self._nrn_iclamp.delay = 0.0 self._nrn_iclamp.dur = 1e12 self._nrn_iclamp.amp = 0.0 self._nrn_iclamp_amps = neuron.h.Vector(pq.Quantity(signal, 'nA')) self._nrn_iclamp_times = neuron.h.Vector(pq.Quantity(signal.times, 'ms')) self._nrn_iclamp_amps.play(self._nrn_iclamp._ref_amp, self._nrn_iclamp_times) if self.input_train is not None: port_name, train, connection_properties = self.input_train try: _, scale = self.neuron_translations[port_name] except KeyError: scale = 1.0 # FIXME: Should scale units weight = connection_properties[0].value * scale self._vstim = neuron.h.VecStim() self._vstim_times = neuron.h.Vector(pq.Quantity(train, 'ms')) self._vstim.play(self._vstim_times) target = (self.extra_point_process if self.extra_point_process is not None else self.nrn_cell) self._vstim_con = neuron.h.NetCon( self._vstim, target, sec=self.nrn_cell_sec) self._vstim_con.weight[0] = weight # Record Time from NEURON (neuron.h.._ref_t) self._nrn_rec = self.NEURONRecorder(self.nrn_cell_sec, self.nrn_cell) self._nrn_rec.record(self.neuron_state_variable)
def __init__(self, *properties, **kwprops): """ `propertes/kwprops` -- Can accept a single parameter, which is a dictionary of parameters or kwarg parameters, or a list of nineml.Property objects """ self._flag_created(False) # Construct all the NEURON structures self._sec = h.Section() # @UndefinedVariable # Insert dynamics mechanism (the built component class) HocClass = getattr(h, self.__class__.name) self._hoc = HocClass(0.5, sec=self._sec) # A recordable of 'spikes' is needed for PyNN compatibility self.recordable = {'spikes': None} # Add a recordable entry for each event send ports # TODO: These ports aren't able to be recorded from at present because # different event ports are not distinguishable in Neuron (well # not easily anyway). Users should use 'spikes' instead for now for port in chain(self.component_class.event_send_ports): self.recordable[port.name] = None for port in chain(self.component_class.analog_send_ports, self.component_class.state_variables): if port.name != self.component_class.annotations.get( PYPE9_NS, BUILD_TRANS, MEMBRANE_VOLTAGE, default=None): self.recordable[port.name] = getattr( self._hoc, '_ref_' + port.name) # Get the membrane capacitance property if not an artificial cell if self.build_component_class.annotations[ PYPE9_NS][BUILD_TRANS][MECH_TYPE] == ARTIFICIAL_CELL_MECH: self.cm_prop_name = None else: # In order to scale the distributed current to the same units as # point process current, i.e. mA/cm^2 -> nA the surface area needs # to be 100um. mA/cm^2 = -3-(-2^2) = 10^1, 100um^2 = 2 + -6^2 = # 10^(-10), nA = 10^(-9). 1 - 10 = - 9. (see PyNN Izhikevich neuron # implementation) self._sec.L = 10.0 self._sec.diam = 10.0 / pi self.cm_prop_name = self.build_component_class.annotations[ PYPE9_NS][BUILD_TRANS][MEMBRANE_CAPACITANCE] cm_prop = None try: try: cm_prop = properties[0][self.cm_prop_name] except IndexError: cm_prop = kwprops[self.cm_prop_name] * un.nF except KeyError: if self.build_properties is not None: cm_prop = self.build_properties.property(self.cm_prop_name) if cm_prop is not None: cm = pq.Quantity(UnitHandler.to_pq_quantity(cm_prop), 'nF') else: cm = 1.0 * pq.nF # Set capacitance in mechanism setattr(self._hoc, self.cm_prop_name, float(cm)) # Set capacitance in hoc specific_cm = pq.Quantity(cm / self.surface_area, 'uF/cm^2') self._sec.cm = float(specific_cm) self.recordable[ self.component_class.annotations[PYPE9_NS][BUILD_TRANS][ MEMBRANE_VOLTAGE]] = self.source_section(0.5)._ref_v # Set up members required for PyNN self.spike_times = h.Vector(0) self.traces = {} self.gsyn_trace = {} self.recording_time = 0 self.rec = h.NetCon(self.source, None, sec=self._sec) self._inputs = {} self._input_auxs = [] # self.initial_v = self.V_INIT_DEFAULT # Get a mapping of receptor names to NMODL indices for PyNN projection # connection assert (set(self.build_component_class.event_receive_port_names) == set(self.component_class.event_receive_port_names)) # Need to use the build_component_class to get the same index as was # used to construct the indices # FIXME: These indices will need to be saved somewhere in the # annotations of the build class so they can be reloaded if self.build_component_class.num_event_receive_ports: ports_n_indices = [ (self.build_component_class.index_of(p), p.name) for p in self.build_component_class.event_receive_ports] # Get event receive ports sorted by the indices sorted_ports = zip( *sorted(ports_n_indices, key=operator.itemgetter(0)))[1] else: sorted_ports = [] self.type = collections.namedtuple('Type', 'receptor_types')( sorted_ports) # Call base init (needs to be after 9ML init) super(Cell, self).__init__(*properties, **kwprops) self._flag_created(True)