Changeset 1025
- Timestamp:
- 12/07/11 17:21:15 (6 months ago)
- Location:
- branches/neo_output
- Files:
-
- 10 modified
-
examples/IF_cond_exp.py (modified) (1 diff)
-
src/common/procedural_api.py (modified) (2 diffs)
-
src/nest/__init__.py (modified) (2 diffs)
-
src/nest/recording.py (modified) (3 diffs)
-
src/nest/simulator.py (modified) (4 diffs)
-
src/neuron/__init__.py (modified) (4 diffs)
-
src/neuron/simulator.py (modified) (3 diffs)
-
src/recording/__init__.py (modified) (2 diffs)
-
src/standardmodels/cells.py (modified) (7 diffs)
-
test/unittests/test_lowlevelapi.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/neo_output/examples/IF_cond_exp.py
r917 r1025 36 36 37 37 record_v(ifcell, "Results/IF_cond_exp_%s.v" % simulator_name) 38 try:39 record_gsyn(ifcell, "Results/IF_cond_exp_%s.gsyn" % simulator_name)40 except (NotImplementedError, RecordingError):41 pass38 #try: 39 record_gsyn(ifcell, "Results/IF_cond_exp_%s.gsyn" % simulator_name) 40 #except (NotImplementedError, RecordingError): 41 # pass 42 42 run(200.0) 43 43 -
branches/neo_output/src/common/procedural_api.py
r999 r1025 51 51 52 52 def build_record(variable, simulator): 53 if variable == "gsyn": # will be removed in PyNN 0.9 54 variable_list = ['gsyn_exc', 'gsyn_inh'] 55 else: 56 variable_list = [variable] 53 57 def record(source, filename): 54 58 """ … … 60 64 if not isinstance(source, (BasePopulation, Assembly)): 61 65 source = source.parent 62 source. _record(variable, to_file=filename)63 # recorder _listis used by end()66 source.record(variable_list) #, to_file=filename) 67 # recorders_autowrite is used by end() 64 68 if isinstance(source, BasePopulation): 65 simulator.recorder_list.append(source.recorders[variable]) # this is a bit hackish - better to add to Population.__del__? 66 if isinstance(source, Assembly): 67 for population in source.populations: 68 simulator.recorder_list.append(population.recorders[variable]) 69 populations = [source] 70 elif isinstance(source, Assembly): 71 populations = source.populations 72 for population in populations: 73 simulator.write_on_end.append((population, variable_list, filename)) 74 # NEED TO HANDLE DEPRECATION OF record_v() and record_gsyn() 69 75 if variable == 'v': 70 76 record.__name__ = "record_v" -
branches/neo_output/src/nest/__init__.py
r1001 r1025 20 20 import logging 21 21 import tempfile 22 from pyNN.recording import files23 22 from pyNN.nest.cells import NativeCellType, native_cell_type 24 23 from pyNN.nest.synapses import NativeSynapseDynamics, NativeSynapseMechanism … … 135 134 return rank() 136 135 137 def end( compatible_output=True):136 def end(): 138 137 """Do any necessary cleaning up before exiting.""" 139 138 global tempdirs 140 # And we postprocess the low level files opened by record() 141 # and record_v() method 142 for recorder in simulator.recorder_list: 143 recorder.write(gather=True, compatible_output=compatible_output) 139 for (population, variables, filename) in simulator.write_on_end: 140 io = recording.get_io(filename) 141 population.write_data(io, variables) 144 142 for tempdir in tempdirs: 145 143 shutil.rmtree(tempdir) 146 144 tempdirs = [] 147 simulator. recorder_list= []145 simulator.write_on_end = [] 148 146 149 147 def run(simtime): -
branches/neo_output/src/nest/recording.py
r1006 r1025 1 """ 2 3 :copyright: Copyright 2006-2011 by the PyNN team, see AUTHORS. 4 :license: CeCILL, see LICENSE for details. 5 """ 6 1 7 import tempfile 2 8 import os … … 7 13 from pyNN import recording, errors 8 14 from pyNN.nest import simulator 9 10 VARIABLE_MAP = {'v': ['V_m'], 'gsyn': ['g_ex', 'g_in']} 11 REVERSE_VARIABLE_MAP = {'V_m': 'v'} 15 import neo 16 from datetime import datetime 17 import quantities as pq 18 19 VARIABLE_MAP = {'v': 'V_m', 'gsyn_exc': 'g_ex', 'gsyn_inh': 'g_in'} 20 REVERSE_VARIABLE_MAP = dict((v,k) for k,v in VARIABLE_MAP.items()) 12 21 13 22 logger = logging.getLogger("PyNN") 14 23 15 # --- For implementation of record_X()/get_X()/print_X() ----------------------- 24 25 def _set_status(obj, parameters): 26 """Wrapper around nest.SetStatus() to add a more informative error message.""" 27 try: 28 nest.SetStatus(obj, parameters) 29 except nest.hl_api.NESTError, e: 30 raise nest.hl_api.NESTError("%s. Parameter dictionary was: %s" % (e, parameters)) 31 16 32 17 33 class RecordingDevice(object): 18 """ 19 Now that NEST introduced the multimeter, and does not allow a node to be 20 connected to multiple multimeters, most of the functionality of `Recorder` 21 has been moved to this class, while `Recorder` is a wrapper to maintain the 22 fiction that each recorder only records a single variable. 23 """ 24 scale_factors = {'V_m': 1, 'g_ex': 0.001, 'g_in': 0.001} 25 26 def __init__(self, device_type, to_memory=False): 27 assert device_type in ("multimeter", "spike_detector") 28 self.type = device_type 29 self.device = nest.Create(device_type) 30 self.to_memory = to_memory 31 device_parameters = {"withgid": True, "withtime": True} 32 if self.type is 'multimeter': 33 device_parameters["interval"] = simulator.state.dt 34 else: 35 device_parameters["precise_times"] = True 36 device_parameters["precision"] = simulator.state.default_recording_precision 34 """Base class for SpikeDetector and Multimeter""" 35 36 def __init__(self, device_parameters, to_memory=True): 37 # to be called at the end of the subclass __init__ 38 device_parameters.update(withgid=True, withtime=True) 37 39 if to_memory: 38 40 device_parameters.update(to_file=False, to_memory=True) 39 41 else: 40 42 device_parameters.update(to_file=True, to_memory=False) 41 try: 42 nest.SetStatus(self.device, device_parameters) 43 except nest.hl_api.NESTError, e: 44 raise nest.hl_api.NESTError("%s. Parameter dictionary was: %s" % (e, device_parameters)) 43 self._all_ids = set([]) 44 self._connected = False 45 simulator.recording_devices.append(self) 46 _set_status(self.device, device_parameters) 47 48 def add_ids(self, new_ids): 49 assert not self._connected 50 self._all_ids = self._all_ids.union(new_ids) 51 52 def get_data(self, variable, desired_ids): 53 """ 54 Return recorded data as a dictionary containing one numpy array for 55 each neuron, ids as keys. 56 """ 57 events = nest.GetStatus(self.device,'events')[0] 58 ids = events['senders'] 59 values = events[variable] 60 data = {} 61 for id in desired_ids: 62 data[id] = values[ids==id] 63 return data 64 65 66 class SpikeDetector(RecordingDevice): 67 """A wrapper around the NEST spike_detector device""" 68 _nest_connect = lambda device, ids: nest.ConvergentConnect() 69 70 def __init__(self, to_memory=True): 71 self.device = nest.Create('spike_detector') 72 device_parameters = { 73 "precise_times": True, 74 "precision": simulator.state.default_recording_precision 75 } 76 super(SpikeDetector, self).__init__(device_parameters, to_memory) 77 78 def connect_to_cells(self): 79 assert not self._connected 80 nest.ConvergentConnect(list(self._all_ids), self.device, model='static_synapse') 81 self._connected = True 82 83 def get_spiketimes(self, desired_ids): 84 """ 85 Return spike times as a dictionary containing one numpy array for 86 each neuron, ids as keys. 45 87 46 self.record_from = [] 47 self._local_files_merged = False 48 self._gathered = False 49 self._connected = False 50 self._all_ids = set([]) 51 simulator.recording_devices.append(self) 52 logger.debug("Created %s with parameters %s" % (device_type, device_parameters)) 53 54 def __del__(self): 55 for name in "_merged_file", "_gathered_file": 56 if hasattr(self, name): 57 getattr(self, name).close() 58 59 def add_variables(self, *variables): 60 assert self.type is "multimeter", "Can't add variables to a spike detector" 61 self.record_from.extend(variables) 62 nest.SetStatus(self.device, {'record_from': self.record_from}) 63 64 def add_cells(self, new_ids): 65 self._all_ids = self._all_ids.union(new_ids) 88 Equivalent to `get_data('times', desired_ids)` 89 """ 90 return self.get_data('times', desired_ids) 66 91 92 93 class Multimeter(RecordingDevice): 94 """A wrapper around the NEST multimeter device""" 95 _nest_connect = nest.ConvergentConnect 96 97 def __init__(self, to_memory=True): 98 self.device = nest.Create('multimeter') 99 device_parameters = { 100 "interval": simulator.state.dt, 101 } 102 super(Multimeter, self).__init__(device_parameters, to_memory) 103 67 104 def connect_to_cells(self): 68 if not self._connected: 69 ids = list(self._all_ids) 70 if self.type is "spike_detector": 71 nest.ConvergentConnect(ids, self.device, model='static_synapse') 72 else: 73 nest.DivergentConnect(self.device, ids, model='static_synapse') 74 self._connected = True 75 76 def in_memory(self): 77 """Determine whether data is being recorded to memory.""" 78 return nest.GetStatus(self.device, 'to_memory')[0] 79 80 def events_to_array(self, events): 81 """ 82 Transform the NEST events dictionary (when recording to memory) to a 83 Numpy array. 84 """ 85 ids = events['senders'] 86 times = events['times'] 87 if self.type == 'spike_detector': 88 data = numpy.array((ids, times)).T 89 else: 90 data = [ids, times] 91 for var in self.record_from: 92 data.append(events[var]) 93 data = numpy.array(data).T 94 return data 95 96 def scale_data(self, data): 97 """ 98 Scale the data to give appropriate units. 99 """ 100 scale_factors = [RecordingDevice.scale_factors.get(var, 1) 101 for var in self.record_from] 102 for i, scale_factor in enumerate(scale_factors): 103 column = i+2 # first two columns are id and t, which should not be scaled. 104 if scale_factor != 1: 105 data[:, column] *= scale_factor 106 return data 107 108 def add_initial_values(self, data): 109 """ 110 Add initial values (NEST does not record the value at t=0). 111 """ 112 logger.debug("Prepending initial values to recorded data") 113 initial_values = [] 114 for id in self._all_ids: 115 initial = [id, 0.0] 116 for variable in self.record_from: 117 variable = REVERSE_VARIABLE_MAP.get(variable, variable) 118 try: 119 initial.append(id.get_initial_value(variable)) 120 except KeyError: 121 initial.append(0.0) # unsatisfactory 122 initial_values.append(initial) 123 if initial_values: 124 data = numpy.concatenate((initial_values, data)) 125 return data 126 127 def read_data_from_memory(self, gather, compatible_output): 128 """ 129 Return memory-recorded data. 130 131 `gather` -- if True, gather data from all MPI nodes. 132 `compatible_output` -- if True, transform the data into the PyNN 133 standard format. 134 """ 135 data = nest.GetStatus(self.device,'events')[0] 136 if compatible_output: 137 data = self.events_to_array(data) 138 data = self.scale_data(data) 139 if gather and simulator.state.num_processes > 1: 140 data = recording.gather(data) 141 self._gathered_file = tempfile.TemporaryFile() 142 numpy.save(self._gathered_file, data) 143 self._gathered = True 144 return data 145 146 def read_local_data(self, compatible_output): 147 """ 148 Return file-recorded data from the local MPI node, merging data from 149 different threads if applicable. 150 151 The merged data is cached, to avoid the overhead of re-merging if the 152 method is called again. 153 """ 154 # what if the method is called with different values of 155 # `compatible_output`? Need to cache these separately. 156 if self._local_files_merged: 157 self._merged_file.seek(0) 158 data = numpy.load(self._merged_file) 159 else: 160 d = nest.GetStatus(self.device)[0] 161 if "filenames" in d: 162 nest_files = d['filenames'] 163 else: # indicates that run() has not been called. 164 raise errors.NothingToWriteError("No recorder data. Have you called run()?") 165 # possibly we can just keep on saving to the end of self._merged_file, instead of concatenating everything in memory 166 logger.debug("Concatenating data from the following files: %s" % ", ".join(nest_files)) 167 non_empty_nest_files = [filename for filename in nest_files if os.stat(filename).st_size > 0] 168 if len(non_empty_nest_files) > 0: 169 data = numpy.concatenate([numpy.loadtxt(nest_file, dtype=float) for nest_file in non_empty_nest_files]) 170 if len(non_empty_nest_files) == 0 or data.size == 0: 171 if self.type is "spike_detector": 172 ncol = 2 173 else: 174 ncol = 2 + len(self.record_from) 175 data = numpy.empty([0, ncol]) 176 if compatible_output and self.type is not "spike_detector": 177 data = self.scale_data(data) 178 data = self.add_initial_values(data) 179 self._merged_file = tempfile.TemporaryFile() 180 numpy.save(self._merged_file, data) 181 self._local_files_merged = True 182 return data 183 184 def read_data(self, gather, compatible_output, always_local=False): 185 """ 186 Return file-recorded data. 187 188 `gather` -- if True, gather data from all MPI nodes. 189 `compatible_output` -- if True, transform the data into the PyNN 190 standard format. 191 192 Gathered data is cached, so the MPI communication need only be done 193 once, even if the method is called multiple times. 194 """ 195 # what if the method is called with different values of 196 # `compatible_output`? Need to cache these separately. 197 if not self.to_memory: 198 if gather and simulator.state.num_processes > 1: 199 if self._gathered: 200 logger.debug("Loading previously gathered data from cache") 201 self._gathered_file.seek(0) 202 data = numpy.load(self._gathered_file) 203 else: 204 local_data = self.read_local_data(compatible_output) 205 if always_local: 206 data = local_data # for always_local cells, no need to gather 207 else: 208 logger.debug("Gathering data") 209 data = recording.gather(local_data) 210 logger.debug("Caching gathered data") 211 self._gathered_file = tempfile.TemporaryFile() 212 numpy.save(self._gathered_file, data) 213 self._gathered = True 214 else: 215 data = self.read_local_data(compatible_output) 216 if len(data.shape) == 1: 217 data = data.reshape((1, data.size)) 218 return data 219 else: 220 return self.read_data_from_memory(gather, compatible_output) 221 222 def read_subset(self, variables, gather, compatible_output, always_local=False): 223 if self.in_memory(): 224 data = self.read_data_from_memory(gather, compatible_output) 225 else: # in file 226 data = self.read_data(gather, compatible_output, always_local) 227 indices = [] 228 for variable in variables: 229 try: 230 indices.append(self.record_from.index(variable)) 231 except ValueError: 232 raise Exception("%s not recorded" % variable) 233 columns = tuple([0, 1] + [index + 2 for index in indices]) 234 return data[:, columns] 105 assert not self._connected 106 nest.DivergentConnect(self.device, list(self._all_ids), model='static_synapse') 107 self._connected = True 108 109 @property 110 def variables(self): 111 return set(nest.GetStatus(self.device, 'record_from')[0]) 112 113 def add_variable(self, variable): 114 current_variables = self.variables 115 current_variables.add(VARIABLE_MAP.get(variable, variable)) 116 _set_status(self.device, {'record_from': list(current_variables)}) 117 118 119 120 121 #class RecordingDevice(object): 122 # scale_factors = {'V_m': 1, 'g_ex': 0.001, 'g_in': 0.001} 123 # 124 # def __init__(self, device_type, to_memory=False): 125 # assert device_type in ("multimeter", "spike_detector") 126 # self.type = device_type 127 # self.device = nest.Create(device_type) 128 # self.to_memory = to_memory 129 # device_parameters = {"withgid": True, "withtime": True} 130 # if self.type is 'multimeter': 131 # device_parameters["interval"] = simulator.state.dt 132 # else: 133 # device_parameters["precise_times"] = True 134 # device_parameters["precision"] = simulator.state.default_recording_precision 135 # if to_memory: 136 # device_parameters.update(to_file=False, to_memory=True) 137 # else: 138 # device_parameters.update(to_file=True, to_memory=False) 139 # try: 140 # nest.SetStatus(self.device, device_parameters) 141 # except nest.hl_api.NESTError, e: 142 # raise nest.hl_api.NESTError("%s. Parameter dictionary was: %s" % (e, device_parameters)) 143 # 144 # self.record_from = [] 145 # self._local_files_merged = False 146 # self._gathered = False 147 # self._connected = False 148 # self._all_ids = set([]) 149 # simulator.recording_devices.append(self) 150 # logger.debug("Created %s with parameters %s" % (device_type, device_parameters)) 151 # 152 # def __del__(self): 153 # for name in "_merged_file", "_gathered_file": 154 # if hasattr(self, name): 155 # getattr(self, name).close() 156 # 157 # def add_variables(self, *variables): 158 # assert self.type is "multimeter", "Can't add variables to a spike detector" 159 # self.record_from.extend(variables) 160 # nest.SetStatus(self.device, {'record_from': self.record_from}) 161 # 162 # def add_cells(self, new_ids): 163 # self._all_ids = self._all_ids.union(new_ids) 164 # 165 # def connect_to_cells(self): 166 # if not self._connected: 167 # ids = list(self._all_ids) 168 # if self.type is "spike_detector": 169 # nest.ConvergentConnect(ids, self.device, model='static_synapse') 170 # else: 171 # nest.DivergentConnect(self.device, ids, model='static_synapse') 172 # self._connected = True 173 # 174 # def in_memory(self): 175 # """Determine whether data is being recorded to memory.""" 176 # return nest.GetStatus(self.device, 'to_memory')[0] 177 # 178 # def events_to_array(self, events): 179 # """ 180 # Transform the NEST events dictionary (when recording to memory) to a 181 # Numpy array. 182 # """ 183 # ids = events['senders'] 184 # times = events['times'] 185 # if self.type == 'spike_detector': 186 # data = numpy.array((ids, times)).T 187 # else: 188 # data = [ids, times] 189 # for var in self.record_from: 190 # data.append(events[var]) 191 # data = numpy.array(data).T 192 # return data 193 # 194 # def scale_data(self, data): 195 # """ 196 # Scale the data to give appropriate units. 197 # """ 198 # scale_factors = [RecordingDevice.scale_factors.get(var, 1) 199 # for var in self.record_from] 200 # for i, scale_factor in enumerate(scale_factors): 201 # column = i+2 # first two columns are id and t, which should not be scaled. 202 # if scale_factor != 1: 203 # data[:, column] *= scale_factor 204 # return data 205 # 206 # def add_initial_values(self, data): 207 # """ 208 # Add initial values (NEST does not record the value at t=0). 209 # """ 210 # logger.debug("Prepending initial values to recorded data") 211 # initial_values = [] 212 # for id in self._all_ids: 213 # initial = [id, 0.0] 214 # for variable in self.record_from: 215 # variable = REVERSE_VARIABLE_MAP.get(variable, variable) 216 # try: 217 # initial.append(id.get_initial_value(variable)) 218 # except KeyError: 219 # initial.append(0.0) # unsatisfactory 220 # initial_values.append(initial) 221 # if initial_values: 222 # data = numpy.concatenate((initial_values, data)) 223 # return data 224 # 225 # def read_data_from_memory(self, gather, compatible_output): 226 # """ 227 # Return memory-recorded data. 228 # 229 # `gather` -- if True, gather data from all MPI nodes. 230 # `compatible_output` -- if True, transform the data into the PyNN 231 # standard format. 232 # """ 233 # data = nest.GetStatus(self.device,'events')[0] 234 # if compatible_output: 235 # data = self.events_to_array(data) 236 # data = self.scale_data(data) 237 # if gather and simulator.state.num_processes > 1: 238 # data = recording.gather(data) 239 # self._gathered_file = tempfile.TemporaryFile() 240 # numpy.save(self._gathered_file, data) 241 # self._gathered = True 242 # return data 243 # 244 # def read_local_data(self, compatible_output): 245 # """ 246 # Return file-recorded data from the local MPI node, merging data from 247 # different threads if applicable. 248 # 249 # The merged data is cached, to avoid the overhead of re-merging if the 250 # method is called again. 251 # """ 252 # # what if the method is called with different values of 253 # # `compatible_output`? Need to cache these separately. 254 # if self._local_files_merged: 255 # self._merged_file.seek(0) 256 # data = numpy.load(self._merged_file) 257 # else: 258 # d = nest.GetStatus(self.device)[0] 259 # if "filenames" in d: 260 # nest_files = d['filenames'] 261 # else: # indicates that run() has not been called. 262 # raise errors.NothingToWriteError("No recorder data. Have you called run()?") 263 # # possibly we can just keep on saving to the end of self._merged_file, instead of concatenating everything in memory 264 # logger.debug("Concatenating data from the following files: %s" % ", ".join(nest_files)) 265 # non_empty_nest_files = [filename for filename in nest_files if os.stat(filename).st_size > 0] 266 # if len(non_empty_nest_files) > 0: 267 # data = numpy.concatenate([numpy.loadtxt(nest_file, dtype=float) for nest_file in non_empty_nest_files]) 268 # if len(non_empty_nest_files) == 0 or data.size == 0: 269 # if self.type is "spike_detector": 270 # ncol = 2 271 # else: 272 # ncol = 2 + len(self.record_from) 273 # data = numpy.empty([0, ncol]) 274 # if compatible_output and self.type is not "spike_detector": 275 # data = self.scale_data(data) 276 # data = self.add_initial_values(data) 277 # self._merged_file = tempfile.TemporaryFile() 278 # numpy.save(self._merged_file, data) 279 # self._local_files_merged = True 280 # return data 281 # 282 # def read_data(self, gather, compatible_output, always_local=False): 283 # """ 284 # Return file-recorded data. 285 # 286 # `gather` -- if True, gather data from all MPI nodes. 287 # `compatible_output` -- if True, transform the data into the PyNN 288 # standard format. 289 # 290 # Gathered data is cached, so the MPI communication need only be done 291 # once, even if the method is called multiple times. 292 # """ 293 # # what if the method is called with different values of 294 # # `compatible_output`? Need to cache these separately. 295 # if not self.to_memory: 296 # if gather and simulator.state.num_processes > 1: 297 # if self._gathered: 298 # logger.debug("Loading previously gathered data from cache") 299 # self._gathered_file.seek(0) 300 # data = numpy.load(self._gathered_file) 301 # else: 302 # local_data = self.read_local_data(compatible_output) 303 # if always_local: 304 # data = local_data # for always_local cells, no need to gather 305 # else: 306 # logger.debug("Gathering data") 307 # data = recording.gather(local_data) 308 # logger.debug("Caching gathered data") 309 # self._gathered_file = tempfile.TemporaryFile() 310 # numpy.save(self._gathered_file, data) 311 # self._gathered = True 312 # else: 313 # data = self.read_local_data(compatible_output) 314 # if len(data.shape) == 1: 315 # data = data.reshape((1, data.size)) 316 # return data 317 # else: 318 # return self.read_data_from_memory(gather, compatible_output) 319 # 320 # def read_subset(self, variables, gather, compatible_output, always_local=False): 321 # if self.in_memory(): 322 # data = self.read_data_from_memory(gather, compatible_output) 323 # else: # in file 324 # data = self.read_data(gather, compatible_output, always_local) 325 # indices = [] 326 # for variable in variables: 327 # try: 328 # indices.append(self.record_from.index(variable)) 329 # except ValueError: 330 # raise Exception("%s not recorded" % variable) 331 # columns = tuple([0, 1] + [index + 2 for index in indices]) 332 # return data[:, columns] 235 333 236 334 … … 242 340 'gsyn': 0.001} # units conversion 243 341 244 def __init__(self, variable, population=None, file=None):342 def __init__(self, population, file=None): 245 343 __doc__ = recording.Recorder.__doc__ 246 recording.Recorder.__init__(self, variable, population, file) 247 self._create_device() 344 recording.Recorder.__init__(self, population, file) 345 self._multimeter = Multimeter() 346 self._spike_detector = SpikeDetector() 347 # self._create_device() 348 349 # def _create_device(self, variable): 350 # to_memory = (self.file is False) # note file=None means we save to a temporary file, not to memory 351 # if variable is "spikes": 352 # self._device = RecordingDevice("spike_detector", to_memory) 353 # else: 354 # self._device = None 355 # for recorder in self.population.recorders.values(): 356 # if hasattr(recorder, "_device") and recorder._device is not None and recorder._device.type == 'multimeter': 357 # self._device = recorder._device 358 # break 359 # if self._device is None: 360 # self._device = RecordingDevice("multimeter", to_memory) 361 # self._device.add_variables(*VARIABLE_MAP.get(self.variable, [self.variable])) 362 363 def _record(self, variable, new_ids): 364 """ 365 Add the cells in `new_ids` to the set of recorded cells for the given 366 variable. Since a given node can only be recorded from by one multimeter 367 (http://www.nest-initiative.org/index.php/Analog_recording_with_multimeter, 14/11/11) 368 we record all analog variables for all requested cells. 369 """ 370 if variable == 'spikes': 371 self._spike_detector.add_ids(new_ids) 372 else: 373 self._multimeter.add_variable(variable) 374 self._multimeter.add_ids(new_ids) 375 376 #def _reset(self): 377 # """ """ 378 # try: 379 # simulator.recording_devices.remove(self._device) 380 # except ValueError: 381 # pass 382 # 383 # if self._device != None: 384 # recorders_to_reset=[] 385 # for recorder in self.population.recorders.values(): 386 # if hasattr(recorder, "_device") and recorder._device == self._device: 387 # recorders_to_reset.append(recorder) 388 # for recorder in recorders_to_reset: 389 # recorder._device = None 390 # self._create_device() 391 392 def _get(self, variables, gather=False, filter_ids=None): 393 """Return the recorded data as a Neo `Block`.""" 394 always_local = (hasattr(self.population.celltype, 'always_local') and self.population.celltype.always_local) 395 data = neo.Block() 396 # TODO: add cached data from previous runs 397 data.segments.append(self._get_current_segment(filter_ids=filter_ids, variables=variables)) 398 return data 248 399 249 def _create_device(self): 250 to_memory = (self.file is False) # note file=None means we save to a temporary file, not to memory 251 if self.variable is "spikes": 252 self._device = RecordingDevice("spike_detector", to_memory) 253 else: 254 self._device = None 255 for recorder in self.population.recorders.values(): 256 if hasattr(recorder, "_device") and recorder._device is not None and recorder._device.type == 'multimeter': 257 self._device = recorder._device 258 break 259 if self._device is None: 260 self._device = RecordingDevice("multimeter", to_memory) 261 self._device.add_variables(*VARIABLE_MAP.get(self.variable, [self.variable])) 262 263 def _record(self, new_ids): 264 """Called by record().""" 265 self._device.add_cells(new_ids) 266 267 def _reset(self): 268 """ """ 269 try: 270 simulator.recording_devices.remove(self._device) 271 except ValueError: 272 pass 273 274 if self._device != None: 275 recorders_to_reset=[] 276 for recorder in self.population.recorders.values(): 277 if hasattr(recorder, "_device") and recorder._device == self._device: 278 recorders_to_reset.append(recorder) 279 for recorder in recorders_to_reset: 280 recorder._device = None 281 self._create_device() 282 283 def _get(self, gather=False, compatible_output=True, filter=None): 284 """Return the recorded data as a Numpy array.""" 285 if self._device is None: 286 raise errors.NothingToWriteError("No cells recorded, so no data to return") 287 always_local = (hasattr(self.population.celltype, 'always_local') and self.population.celltype.always_local) 288 if self.variable is "spikes": 289 data = self._device.read_data(gather, compatible_output, always_local) 290 else: 291 variables = VARIABLE_MAP.get(self.variable, [self.variable]) 292 data = self._device.read_subset(variables, gather, compatible_output, always_local) 293 assert len(data.shape) == 2 294 if not self._device._gathered: 295 filtered_ids = self.filter_recorded(filter) 296 mask = reduce(numpy.add, (data[:,0]==id for id in filtered_ids)) 297 if len(data) > 0: 298 data = data[mask] 299 return data 400 def _get_current_segment(self, filter_ids=None, variables='all'): 401 segment = neo.Segment(name=self.population.label, 402 description=self.population.describe(), 403 rec_datetime=datetime.now()) # would be nice to get the time at the start of the recording, not the end 404 variables_to_include = set(self.recorded.keys()) 405 if variables is not 'all': 406 variables_to_include = variables_to_include.intersection(set(variables)) 407 for variable in variables_to_include: 408 if variable == 'spikes': 409 spike_times = self._spike_detector.get_spiketimes(self.filter_recorded('spikes', filter_ids)) 410 segment.spiketrains = [ 411 neo.SpikeTrain(spike_times[id], 412 t_stop=simulator.state.t*pq.ms, 413 units='ms', 414 source_population=self.population.label, 415 source_id=int(id)) # index? 416 for id in self.filter_recorded('spikes', filter_ids)] 417 else: 418 data = self._multimeter.get_data(VARIABLE_MAP.get(variable, variable), 419 self.filter_recorded(variable, filter_ids)) 420 segment.analogsignals = [ 421 neo.AnalogSignal(data[id], 422 units=recording.UNITS_MAP.get(variable, 'dimensionless'), 423 t_start=simulator.state.t_start*pq.ms, 424 sampling_period=simulator.state.dt*pq.ms, 425 name=variable, 426 source_population=self.population.label, 427 source_id=int(id)) 428 for id in self.filter_recorded(variable, filter_ids)] 429 return segment 300 430 301 431 def _local_count(self, filter): -
branches/neo_output/src/nest/simulator.py
r998 r1025 16 16 Attributes: 17 17 state -- a singleton instance of the _State class. 18 recorder_list19 18 20 19 All other functions and classes are private, and should not be used by other … … 35 34 36 35 CHECK_CONNECTIONS = False 37 recorder_list = [] 36 write_on_end = [] # a list of (population, variable, filename) combinations that should be written to file on end() 38 37 recording_devices = [] 39 38 … … 56 55 self._cache_num_processes = nest.GetKernelStatus()['num_processes'] # avoids blocking if only some nodes call num_processes 57 56 # do the same for rank? 57 self.t_start = 0.0 58 58 59 59 @property … … 99 99 nest.SetKernelStatus({'time': 0.0}) 100 100 state.running = False 101 state.t_start = 0.0 101 102 102 103 # --- For implementation of access to individual neurons' parameters ----------- -
branches/neo_output/src/neuron/__init__.py
r1001 r1025 11 11 12 12 from pyNN.random import * 13 from pyNN import common, core, space, __doc__, standardmodels 14 from pyNN.recording import get_io 13 15 from pyNN.neuron import simulator 14 from pyNN import common, core, space, __doc__15 16 16 from pyNN.neuron.standardmodels.cells import * 17 17 from pyNN.neuron.connectors import * … … 19 19 from pyNN.neuron.electrodes import * 20 20 from pyNN.neuron.recording import Recorder 21 from pyNN import standardmodels 21 22 22 import numpy 23 23 import logging … … 26 26 27 27 logger = logging.getLogger("PyNN") 28 29 28 30 29 31 # ============================================================================== … … 71 73 def end(compatible_output=True): 72 74 """Do any necessary cleaning up before exiting.""" 73 for recorder in simulator.recorder_list: 74 recorder.write(gather=True, compatible_output=compatible_output) 75 simulator.recorder_list = [] 75 for (population, variables, filename) in simulator.write_on_end: 76 io = get_io(filename) 77 population.write_data(io, variables) 78 simulator.write_on_end = [] 76 79 #simulator.finalize() 77 80 -
branches/neo_output/src/neuron/simulator.py
r1006 r1025 17 17 Attributes: 18 18 state -- a singleton instance of the _State class. 19 recorder_list20 19 21 20 All other functions and classes are private, and should not be used by other … … 38 37 # Global variables 39 38 nrn_dll_loaded = [] 40 recorder_list= []39 write_on_end = [] 41 40 gid_sources = [] 42 41 logger = logging.getLogger("PyNN") … … 191 190 assert local_minimum_delay >= state.min_delay, \ 192 191 "There are connections with delays (%g) shorter than the minimum delay (%g)" % (local_minimum_delay, state.min_delay) 193 state.t_start = state.t194 192 state.tstop += simtime 195 193 logger.info("Running the simulation for %g ms" % simtime) -
branches/neo_output/src/recording/__init__.py
r1008 r1025 19 19 from collections import defaultdict 20 20 from pyNN import errors 21 from pyNN.recording import files 21 import neo.io 22 22 try: 23 23 from mpi4py import MPI … … 94 94 else: 95 95 return variables 96 97 def get_io(filename): 98 """ 99 Return a Neo IO instance, guessing the type based on the filename suffix. 100 """ 101 if os.path.splitext(filename)[0] in ('.txt', '.ras', '.v', '.gsyn'): 102 return neo.io.PyNNTextIO(filename) 103 else: # function to be improved later 104 return neo.io.PyNNTextIO(filename) 96 105 97 106 -
branches/neo_output/src/standardmodels/cells.py
r957 r1025 98 98 'i_offset' : 0.0, # Offset current in nA 99 99 } 100 recordable = ['spikes', 'v', 'gsyn ']100 recordable = ['spikes', 'v', 'gsyn_exc', 'gsyn_inh'] 101 101 default_initial_values = { 102 102 'v': -65.0, #'v_rest', … … 122 122 'i_offset' : 0.0, # Offset current in nA 123 123 } 124 recordable = ['spikes', 'v', 'gsyn ']124 recordable = ['spikes', 'v', 'gsyn_exc', 'gsyn_inh'] 125 125 default_initial_values = { 126 126 'v': -65.0, #'v_rest', … … 159 159 'q_rr' : 3000.0 # Quantal relative refractory conductance increase in nS 160 160 } 161 recordable = ['spikes', 'v', 'gsyn ']161 recordable = ['spikes', 'v', 'gsyn_exc', 'gsyn_inh'] 162 162 default_initial_values = { 163 163 'v': -65.0, #'v_rest', … … 184 184 'v_thresh' : -55.0 # mV 185 185 } 186 recordable = ['spikes', 'v', 'gsyn ']186 recordable = ['spikes', 'v', 'gsyn_exc', 'gsyn_inh'] 187 187 default_initial_values = { 188 188 'v': -65.0, #'v_rest', … … 210 210 'i_offset' : 0.0, # nA 211 211 } 212 recordable = ['spikes', 'v', 'gsyn ']212 recordable = ['spikes', 'v', 'gsyn_exc', 'gsyn_inh'] 213 213 default_initial_values = { 214 214 'v': -65.0, #'v_rest', … … 244 244 'tau_syn_I' : 5.0, # Rise time of the inhibitory synaptic conductance in ms (alpha function). 245 245 } 246 recordable = ['spikes', 'v', 'w', 'gsyn ']246 recordable = ['spikes', 'v', 'w', 'gsyn_exc', 'gsyn_inh'] 247 247 default_initial_values = { 248 248 'v': -65.0, #'v_rest', … … 279 279 'tau_syn_I' : 5.0, # Decay time constant of the inhibitory synaptic conductance in ms. 280 280 } 281 recordable = ['spikes', 'v', 'w', 'gsyn ']281 recordable = ['spikes', 'v', 'w', 'gsyn_exc', 'gsyn_inh'] 282 282 default_initial_values = { 283 283 'v': -65.0, #'v_rest', -
branches/neo_output/test/unittests/test_lowlevelapi.py
r999 r1025 39 39 def test_build_record(): 40 40 simulator = Mock() 41 simulator. recorder_list= []41 simulator.write_on_end = [] 42 42 record_function = common.build_record("foo", simulator) 43 43 assert isfunction(record_function) 44 44 45 45 source = BasePopulation() 46 source._record = Mock() 47 source.recorders = {'foo': Mock()} 46 source.record = Mock() 48 47 record_function(source, "filename") 49 source. _record.assert_called_with("foo", to_file="filename")50 assert_equal(simulator. recorder_list, [source.recorders['foo']])48 source.record.assert_called_with(["foo"]) #, to_file="filename") 49 assert_equal(simulator.write_on_end, [(source, ['foo'], "filename")]) 51 50 52 51 def test_build_record_with_assembly(): 53 52 simulator = Mock() 54 simulator. recorder_list= []53 simulator.write_on_end = [] 55 54 record_function = common.build_record("foo", simulator) 56 55 assert isfunction(record_function) … … 59 58 p2 = BasePopulation() 60 59 source = common.Assembly(p1, p2) 61 source._record = Mock() 62 for p in p1, p2: 63 p.recorders = {'foo': Mock()} 60 source.record = Mock() 64 61 record_function(source, "filename") 65 source. _record.assert_called_with("foo", to_file="filename")66 assert_equal(simulator. recorder_list, [p1.recorders['foo'], p2.recorders['foo']])62 source.record.assert_called_with(["foo"]) #, to_file="filename") 63 assert_equal(simulator.write_on_end, [(p1, ['foo'], "filename"), (p2, ['foo'], "filename")]) # not sure this is what we want - won't file get over-written?
