Changeset 1032

Show
Ignore:
Timestamp:
12/14/11 09:58:04 (5 months ago)
Author:
apdavison
Message:

In neo_output branch, refactoring to move shared code to pyNN.recording, and support for multiple Segments (each reset() creates a new Segment

Location:
branches/neo_output
Files:
1 added
8 modified

Legend:

Unmodified
Added
Removed
  • branches/neo_output/src/common/control.py

    r1000 r1032  
    4141 
    4242def build_reset(simulator): 
    43     def reset(): 
     43    def reset(annotations={}): 
    4444        """ 
    4545        Reset the time to zero, neuron membrane potentials and synaptic weights to 
     
    4747        is not changed, nor is the specification of which neurons to record from. 
    4848        """ 
     49        for recorder in simulator.recorders: 
     50            recorder.store_to_cache(annotations) 
    4951        simulator.reset() 
    5052    return reset 
  • branches/neo_output/src/common/populations.py

    r1030 r1032  
    622622        self._positions = None 
    623623        self._is_sorted = True 
     624        self.annotations = {} 
    624625        # Build the arrays of cell ids 
    625626        # Cells on the local node are represented as ID objects, other cells by integers 
     
    713714                         case of non-point models).""") 
    714715 
     716    def annotate(self, **annotations): 
     717        self.annotations.update(annotations) 
     718 
    715719    def describe(self, template='population_default.txt', engine='default'): 
    716720        """ 
     
    732736            "last_id": self.last_id, 
    733737        } 
     738        context.update(self.annotations) 
    734739        if len(self.local_cells) > 0: 
    735740            first_id = self.local_cells[0] 
  • branches/neo_output/src/nest/recording.py

    r1031 r1032  
    394394    #    self._create_device() 
    395395 
    396     def _get(self, variables, gather=False, filter_ids=None): 
    397         """Return the recorded data as a Neo `Block`.""" 
    398         always_local = (hasattr(self.population.celltype, 'always_local') and self.population.celltype.always_local) 
    399         data = neo.Block() 
    400         # TODO: add cached data from previous runs 
    401         data.segments.append(self._get_current_segment(filter_ids=filter_ids, variables=variables)) 
    402         return data 
    403          
    404396    def _get_current_segment(self, filter_ids=None, variables='all'): 
    405397        segment = neo.Segment(name=self.population.label, 
  • branches/neo_output/src/nest/simulator.py

    r1026 r1032  
    3636write_on_end = [] # a list of (population, variable, filename) combinations that should be written to file on end() 
    3737recording_devices = [] 
     38recorders = set([]) 
    3839 
    3940global net 
  • branches/neo_output/src/neuron/electrodes.py

    r957 r1032  
    1313 
    1414from neuron import h 
     15 
     16def _iclamp_property(local_name, hoc_name): 
     17    """ 
     18    Returns a new property for getting/setting iclamp attributes 
     19    """ 
     20    def get(self): 
     21        return getattr(self, local_name) 
     22    def set(self, value): 
     23        setattr(self, local_name, value) 
     24        for iclamp in self._devices: 
     25            setattr(iclamp, hoc_name, value) 
     26    return property(fget=get, fset=set) 
    1527 
    1628 
     
    3143            amplitude -- pulse amplitude in nA 
    3244        """ 
    33         self.amplitude = amplitude 
    34         self.start = start 
    35         self.stop = stop or 1e12 
     45        self._amplitude = amplitude 
     46        self._start = start 
     47        self._stop = stop or 1e12 
    3648        self._devices = [] 
    3749     
     
    4153            if id.local: 
    4254                iclamp = h.IClamp(0.5, sec=id._cell.source_section) 
    43                 iclamp.delay = self.start 
    44                 iclamp.dur = self.stop-self.start 
    45                 iclamp.amp = self.amplitude 
     55                iclamp.delay = self._start 
     56                iclamp.dur = self._stop-self._start 
     57                iclamp.amp = self._amplitude 
    4658                self._devices.append(iclamp) 
     59 
     60    amplitude = _iclamp_property("_amplitude", "amp") 
     61     
     62    def _set_start(self, value): 
     63        self._start = value 
     64        for iclamp in self._devices: 
     65            iclamp.delay = value 
     66            iclamp.dur = self._stop - value 
     67    start = property(fget=lambda self: self._start, 
     68                     fset=_set_start) 
     69     
     70    def _set_stop(self, value): 
     71        self._stop = value 
     72        for iclamp in self._devices: 
     73            iclamp.dur = value - self._start 
     74    stop = property(fget=lambda self: self._start, 
     75                    fset=_set_stop) 
    4776 
    4877 
     
    79108                self.amplitudes.play(iclamp._ref_amp, self.times) 
    80109                 
     110    # need to make times and amplitudes properties so they can be modified 
     111     
  • branches/neo_output/src/neuron/recording.py

    r1031 r1032  
    1919# --- For implementation of record_X()/get_X()/print_X() ----------------------- 
    2020 
    21 def filter_variables(segment, variables): 
    22     """ 
    23     Return a new `Segment` containing only recordings of the variables given in 
    24     the list `variables` 
    25     """ 
    26     if variables == 'all': 
    27         return segment 
    28     else: 
    29         new_segment = copy(segment) # shallow copy 
    30         if 'spikes' not in variables: 
    31             new_segment.spiketrains = [] 
    32         new_segment.analogsignals = [sig for sig in segment.analogsignals if sig.name in variables] 
    33         # also need to handle Units, RecordingChannels 
    34         return new_segment 
    35  
    36  
    37 class DataCache(object): 
    38     # primitive implementation for now, storing in memory - later can consider caching to disk 
    39     def __init__(self): 
    40         self._data = [] 
    41  
    42     def __iter__(self): 
    43         return iter(self._data) 
    44      
    45     def store(self, obj): 
    46         self._data.append(obj) 
    47          
    48  
    4921 
    5022class Recorder(recording.Recorder): 
    5123    """Encapsulates data and functions related to recording model variables.""" 
    52     _simulator = simulator 
    53      
    54     def __init__(self, population, file=None): 
    55         __doc__ = super(Recorder, self).__init__.__doc__ 
    56         super(Recorder, self).__init__(population, file) 
    57         self.cache = DataCache() 
     24    _simulator = simulator  
    5825     
    5926    def _record(self, variable, new_ids): 
     
    10774        else: 
    10875            raise Exception("Recording of %s not implemented." % variable) 
    109      
    110     def _get(self, variables, gather=False, filter_ids=None): 
    111         """Return the recorded data as a Neo `Block`.""" 
    112         data = neo.Block() 
    113         data.segments = [filter_variables(segment, variables) for segment in self.cache] 
    114         data.segments.append(self._get_current_segment(filter_ids=filter_ids, variables=variables)) 
    115         if gather and simulator.state.num_processes > 1: 
    116             data = recording.gather(data) 
    117         return data 
    11876     
    11977    def _get_current_segment(self, filter_ids=None, variables='all'): 
  • branches/neo_output/src/neuron/simulator.py

    r1025 r1032  
    3939write_on_end = [] 
    4040gid_sources = [] 
     41recorders = set([]) 
    4142logger = logging.getLogger("PyNN") 
    4243 
  • branches/neo_output/src/recording/__init__.py

    r1030 r1032  
    107107        raise Exception("file extension %s not supported" % extension) 
    108108 
     109def filter_by_variables(segment, variables): 
     110    """ 
     111    Return a new `Segment` containing only recordings of the variables given in 
     112    the list `variables` 
     113    """ 
     114    if variables == 'all': 
     115        return segment 
     116    else: 
     117        new_segment = copy(segment) # shallow copy 
     118        if 'spikes' not in variables: 
     119            new_segment.spiketrains = [] 
     120        new_segment.analogsignals = [sig for sig in segment.analogsignals if sig.name in variables] 
     121        # also need to handle Units, RecordingChannels 
     122        return new_segment 
     123 
     124 
     125class DataCache(object): 
     126    # primitive implementation for now, storing in memory - later can consider caching to disk 
     127    def __init__(self): 
     128        self._data = [] 
     129 
     130    def __iter__(self): 
     131        return iter(self._data) 
     132     
     133    def store(self, obj): 
     134        if obj not in self._data: 
     135            self._data.append(obj) 
     136 
    109137 
    110138class Recorder(object): 
     
    125153        self.population = population # needed for writing header information 
    126154        self.recorded = defaultdict(set) 
     155        self.cache = DataCache() 
     156        self._simulator.recorders.add(self) 
    127157         
    128158    def record(self, variables, ids): 
     
    153183        """Return the recorded data as a Neo `Block`.""" 
    154184        variables = normalize_variables_arg(variables) 
    155         data = self._get(variables, gather, filter_ids) 
     185        data = neo.Block() 
     186        data.segments = [filter_by_variables(segment, variables) 
     187                         for segment in self.cache] 
     188        if self._simulator.state.running: # reset() has not been called, so current segment is not in cache 
     189            data.segments.append(self._get_current_segment(filter_ids=filter_ids, variables=variables)) 
    156190        data.name = self.population.label 
    157191        data.description = self.population.describe() 
    158192        data.rec_datetime = data.segments[0].rec_datetime 
    159193        data.annotate(**self.metadata) 
     194        if gather and self._simulator.state.num_processes > 1: 
     195            data = recording.gather(data) 
    160196        return data 
    161197     
     
    183219                'label': self.population.label, 
    184220            } 
     221        metadata.update(self.population.annotations) 
    185222        metadata['dt'] = self._simulator.state.dt # note that this has to run on all nodes (at least for NEST) 
    186223        return metadata 
     
    199236        return N 
    200237     
     238    def store_to_cache(self, annotations={}): 
     239        segment = self._get_current_segment() 
     240        segment.annotate(**annotations) 
     241        self.cache.store(segment)