| | 292 | |
|---|
| | 293 | |
|---|
| | 294 | class Recorder(object): |
|---|
| | 295 | """Encapsulates data and functions related to recording model variables.""" |
|---|
| | 296 | |
|---|
| | 297 | def __init__(self, variable, population=None, file=None): |
|---|
| | 298 | """ |
|---|
| | 299 | `file` should be one of: |
|---|
| | 300 | a file-name, |
|---|
| | 301 | `None` (write to a temporary file) |
|---|
| | 302 | `False` (write to memory). |
|---|
| | 303 | """ |
|---|
| | 304 | assert variable in RECORDING_VECTOR_NAMES |
|---|
| | 305 | self.variable = variable |
|---|
| | 306 | self.filename = file or None |
|---|
| | 307 | self.population = population # needed for writing header information |
|---|
| | 308 | self.recorded = Set([]) |
|---|
| | 309 | |
|---|
| | 310 | def record(self, ids): |
|---|
| | 311 | """Add the cells in `ids` to the set of recorded cells.""" |
|---|
| | 312 | ids = Set([id for id in ids if id in self.population.gidlist]) |
|---|
| | 313 | new_ids = list( ids.difference(self.recorded) ) |
|---|
| | 314 | self.recorded = self.recorded.union(ids) |
|---|
| | 315 | if self.population is None: |
|---|
| | 316 | cell_template = "cell%d" |
|---|
| | 317 | id_list = new_ids |
|---|
| | 318 | else: |
|---|
| | 319 | cell_template = "%s.object(%s)" % (self.population.hoc_label, "%d") |
|---|
| | 320 | id_list = self.population.gidlist |
|---|
| | 321 | if self.variable == 'spikes': |
|---|
| | 322 | template = 'tmp = %s.record(1)' % cell_template |
|---|
| | 323 | elif self.variable == 'v': |
|---|
| | 324 | template = 'tmp = %s.record_v(1,%g)' % (cell_template, get_time_step()) |
|---|
| | 325 | hoc_commands = [] |
|---|
| | 326 | for src in new_ids: |
|---|
| | 327 | hoc_commands += [template % id_list.index(src)] |
|---|
| | 328 | hoc_execute(hoc_commands, "---Recorder.record() ---") |
|---|
| | 329 | |
|---|
| | 330 | def get(self, gather=False): |
|---|
| | 331 | """Returns the recorded data.""" |
|---|
| | 332 | data = recording.readArray(filename, sepchar=None) |
|---|
| | 333 | data = recording.convert_compatible_output(data, self.population, variable) |
|---|
| | 334 | return data |
|---|
| | 335 | |
|---|
| | 336 | def write(self, file=None, gather=False, compatible_output=True): |
|---|
| | 337 | hoc_execute(['objref gathered_vec_list', |
|---|
| | 338 | 'gathered_vec_list = new List()']) |
|---|
| | 339 | vector_operation = '' |
|---|
| | 340 | if self.variable == 'spikes': |
|---|
| | 341 | vector_operation = '.where("<=", tstop)' |
|---|
| | 342 | header = "# dt = %g\\n# n = %d\\n" % (get_time_step(), int(h.tstop/get_time_step())) |
|---|
| | 343 | if self.population is None: |
|---|
| | 344 | cell_template = "cell%d" |
|---|
| | 345 | post_label = "node%d: post cellX.%s" % (myid, self.variable) |
|---|
| | 346 | id_list = gidlist |
|---|
| | 347 | padding = 0 |
|---|
| | 348 | else: |
|---|
| | 349 | cell_template = "%s.object(%s)" % (self.population.hoc_label, "%d") |
|---|
| | 350 | post_label = 'node%d: post_%s.%s' % (myid, self.population.hoc_label, self.variable) |
|---|
| | 351 | id_list = self.population.gidlist |
|---|
| | 352 | padding = self.population.gid_start |
|---|
| | 353 | |
|---|
| | 354 | def post_data(): |
|---|
| | 355 | pack_template = 'tmp = pc.pack(%s.%s%s)' % (cell_template, |
|---|
| | 356 | RECORDING_VECTOR_NAME[self.variable], |
|---|
| | 357 | vector_operation) |
|---|
| | 358 | for cell in self.recorded: |
|---|
| | 359 | hoc_commands += ['tmp = pc.pack(%d)' % id_list.index(cell), |
|---|
| | 360 | pack_template % id_list.index(cell)] |
|---|
| | 361 | hoc_commands += ['tmp = pc.post("%s")' % post_label] |
|---|
| | 362 | hoc_execute(hoc_commands,"--- Population[%s].__print()__ --- [Post objects to master]" %self.label) |
|---|
| | 363 | def take_data(): |
|---|
| | 364 | hoc_commands = ['tmp = pc.take(post_label)'] |
|---|
| | 365 | for node in range(1, num_processes()): |
|---|
| | 366 | hoc_commands += ['gathered_vec_list.append(pc.upkscalar())', |
|---|
| | 367 | 'gathered_vec_list.append(pc.upkvec())'] |
|---|
| | 368 | def write_data(): |
|---|
| | 369 | if self.population is None: |
|---|
| | 370 | header = "# first_id = %d\\n# last_id = %d\\n" % (min(self.recorded), max(self.recorded)) |
|---|
| | 371 | else: |
|---|
| | 372 | header = "# %d" % self.population.dim[0] |
|---|
| | 373 | for dimension in list(self.population.dim)[1:]: |
|---|
| | 374 | header = "%s\t%d" % (header, dimension) |
|---|
| | 375 | header += "\\n# first_id = %d\\n# last_id = %d\\n" % (self.population.gid_start, self.population.gid_start+self.population.size-1) |
|---|
| | 376 | |
|---|
| | 377 | if self.variable == 'v': |
|---|
| | 378 | header += "# dt = %g\\n# n = %d\\n" % (get_time_step(), int(h.tstop/get_time_step())) |
|---|
| | 379 | num_format = "%.6g" |
|---|
| | 380 | elif self.variable == 'spikes': |
|---|
| | 381 | header += "# dt = %g\\n"% get_time_step() |
|---|
| | 382 | num_format = "%.2f" |
|---|
| | 383 | filename = file or self.filename |
|---|
| | 384 | hoc_commands = ['objref fileobj', |
|---|
| | 385 | 'fileobj = new File()', |
|---|
| | 386 | 'tmp = fileobj.wopen("%s")' % filename, |
|---|
| | 387 | 'tmp = fileobj.printf("%s")' % header, |
|---|
| | 388 | 'i = 0'] |
|---|
| | 389 | write_template = 'tmp = %s.%s%s.printf(fileobj, fmt)' % (cell_template, |
|---|
| | 390 | RECORDING_VECTOR_NAMES[self.variable], |
|---|
| | 391 | vector_operation) |
|---|
| | 392 | for cell in self.recorded: |
|---|
| | 393 | hoc_commands += ['fmt = "%s\\t%d\\n"' % (num_format, cell-padding), |
|---|
| | 394 | write_template % id_list.index(cell)] |
|---|
| | 395 | # writing gathered data is currently broken |
|---|
| | 396 | #hoc_commands += ['while i < gathered_vec_list.count()-2 { gathered_vec_list.o(i+1).printf(fileobj, "%s broken") ' % num_format] |
|---|
| | 397 | hoc_commands += ['tmp = fileobj.close()'] |
|---|
| | 398 | hoc_execute(hoc_commands, "Recorder.write()") |
|---|
| | 399 | |
|---|
| | 400 | if gather: |
|---|
| | 401 | if myid != 0: # on slave nodes, post data |
|---|
| | 402 | post_data() |
|---|
| | 403 | else: |
|---|
| | 404 | take_data() |
|---|
| | 405 | write_data() |
|---|
| | 406 | else: |
|---|
| | 407 | filename += ".%d" % myid |
|---|
| | 408 | write_data() |
|---|
| 374 | | if len(vfilelist) > 0: |
|---|
| 375 | | hoc_commands = ['objref fileobj', |
|---|
| 376 | | 'fileobj = new File()'] |
|---|
| 377 | | while len(vfilelist): |
|---|
| 378 | | filename, cell_list = vfilelist.popitem() |
|---|
| 379 | | #tstop = HocToPy.get('tstop','float') |
|---|
| 380 | | tstop = h.tstop |
|---|
| 381 | | header = "# dt = %g\\n# n = %d\\n" % (get_time_step(), int(tstop/get_time_step())) |
|---|
| 382 | | header += "# first_id = %d\\n# last_id = %d\\n" % (cell_list[0], cell_list[-1]) |
|---|
| 383 | | hoc_commands += ['tmp = fileobj.wopen("%s")' % filename, |
|---|
| 384 | | 'tmp = fileobj.printf("%s")' % header] |
|---|
| 385 | | for cell in cell_list: |
|---|
| 386 | | hoc_commands += ['fmt = "%s\\t%d\\n"' % ("%.6g", cell), |
|---|
| 387 | | 'tmp = cell%d.vtrace.printf(fileobj, fmt)' % cell] |
|---|
| 388 | | hoc_commands += ['tmp = fileobj.close()'] |
|---|
| 389 | | if len(spikefilelist) > 0: |
|---|
| 390 | | hoc_commands += ['objref fileobj', |
|---|
| 391 | | 'fileobj = new File()'] |
|---|
| 392 | | header = "# dt = %g\\n"% get_time_step() |
|---|
| 393 | | header += "# first_id = %d\\n #last_id = %d\\n" % (cell_list[0], cell_list[-1]) |
|---|
| 394 | | while len(spikefilelist): |
|---|
| 395 | | filename, cell_list = spikefilelist.popitem() |
|---|
| 396 | | hoc_commands += ['tmp = fileobj.wopen("%s")' % filename, |
|---|
| 397 | | 'tmp = fileobj.printf("%s")' % header] |
|---|
| 398 | | for cell in cell_list: |
|---|
| 399 | | hoc_commands += ['fmt = "%s\\t%d\\n"' % ("%.2f", cell), |
|---|
| 400 | | #'tmp = fileobj.printf("# cell%d\\n")' % cell, |
|---|
| 401 | | 'tmp = cell%d.spiketimes.where("<=", tstop).printf(fileobj, fmt)' % cell] |
|---|
| 402 | | hoc_commands += ['tmp = fileobj.close()'] |
|---|
| 906 | | |
|---|
| 907 | | suffix = ''*(record_what=='spiketimes') + '_v'*(record_what=='vtrace') |
|---|
| 908 | | for id in record_from: |
|---|
| 909 | | if id in self.gidlist: |
|---|
| 910 | | hoc_commands += ['tmp = %s.object(%d).record%s(1)' % (self.hoc_label, self.gidlist.index(id), suffix)] |
|---|
| 911 | | |
|---|
| 912 | | # note that self.record_from is not the same on all nodes, like self.gidlist, for example. |
|---|
| 913 | | self.record_from[record_what].update(Set(record_from)) |
|---|
| 914 | | hoc_commands += ['objref record_from'] |
|---|
| 915 | | hoc_execute(hoc_commands) |
|---|
| 916 | | |
|---|
| 917 | | # Then we have to send the lists of local recorded objects to the master node, |
|---|
| 918 | | # but only if the list has not been specified by the user. |
|---|
| 919 | | if fixed_list is False: |
|---|
| 920 | | if myid != 0: # on slave nodes |
|---|
| 921 | | hoc_commands = ['record_from = new Vector()'] |
|---|
| 922 | | for id in self.record_from[record_what]: |
|---|
| 923 | | if id in self.gidlist: |
|---|
| 924 | | hoc_commands += ['record_from = record_from.append(%d)' %id] |
|---|
| 925 | | hoc_commands += ['tmp = pc.post("%s.record_from[%s].node[%d]", record_from)' %(self.hoc_label, record_what, myid)] |
|---|
| 926 | | hoc_execute(hoc_commands, " (Posting recorded cells)") |
|---|
| 927 | | else: # on the master node |
|---|
| 928 | | for id in range (1, nhost): |
|---|
| 929 | | hoc_commands = ['record_from = new Vector()'] |
|---|
| 930 | | hoc_commands += ['tmp = pc.take("%s.record_from[%s].node[%d]", record_from)' %(self.hoc_label, record_what, id)] |
|---|
| 931 | | hoc_execute(hoc_commands) |
|---|
| 932 | | for j in xrange(int(h.record_from.size())): |
|---|
| 933 | | self.record_from[record_what].add(int(h.record_from.x[j])) |
|---|
| | 983 | self.recorders[record_what].record(record_from) |
|---|
| 954 | | self.__record('vtrace', record_from, rng) |
|---|
| 955 | | |
|---|
| 956 | | def __print(self, print_what, filename, num_format, gather, header=None): |
|---|
| 957 | | """Private method used by printSpikes() and print_v().""" |
|---|
| 958 | | global myid |
|---|
| 959 | | vector_operation = '' |
|---|
| 960 | | if print_what == 'spiketimes': |
|---|
| 961 | | vector_operation = '.where("<=", tstop)' |
|---|
| 962 | | if gather and myid != 0: # on slave nodes, post data |
|---|
| 963 | | hoc_commands = [] |
|---|
| 964 | | for id in self.record_from[print_what]: |
|---|
| 965 | | if id in self.gidlist: |
|---|
| 966 | | hoc_commands += ['tmp = pc.post("%s[%d].%s",%s.object(%d).%s%s)' % (self.hoc_label, id, |
|---|
| 967 | | print_what, |
|---|
| 968 | | self.hoc_label, |
|---|
| 969 | | self.gidlist.index(id), |
|---|
| 970 | | print_what, |
|---|
| 971 | | vector_operation)] |
|---|
| 972 | | hoc_execute(hoc_commands,"--- Population[%s].__print()__ --- [Post objects to master]" %self.label) |
|---|
| 973 | | |
|---|
| 974 | | if not gather: |
|---|
| 975 | | filename += ".%d" % myid |
|---|
| 976 | | |
|---|
| 977 | | if myid==0 or not gather: |
|---|
| 978 | | hoc_commands = ['objref fileobj', |
|---|
| 979 | | 'fileobj = new File()', |
|---|
| 980 | | 'tmp = fileobj.wopen("%s")' % filename] |
|---|
| 981 | | if header: |
|---|
| 982 | | hoc_commands += ['tmp = fileobj.printf("%s\\n")' % header] |
|---|
| 983 | | if gather: |
|---|
| 984 | | hoc_commands += ['objref gatheredvec'] |
|---|
| 985 | | padding = self.fullgidlist[0] |
|---|
| 986 | | for id in self.record_from[print_what]: |
|---|
| 987 | | addr = self.locate(id) |
|---|
| 988 | | #hoc_commands += ['fmt = "%s\\t%s\\n"' % (num_format, "\\t".join([str(j) for j in addr]))] |
|---|
| 989 | | hoc_commands += ['fmt = "%s\\t%d\\n"' % (num_format, id-padding)] |
|---|
| 990 | | if id in self.gidlist: |
|---|
| 991 | | hoc_commands += ['tmp = %s.object(%d).%s%s.printf(fileobj, fmt)' % (self.hoc_label, |
|---|
| 992 | | self.gidlist.index(id), |
|---|
| 993 | | print_what, |
|---|
| 994 | | vector_operation)] |
|---|
| 995 | | elif gather: |
|---|
| 996 | | hoc_commands += ['gatheredvec = new Vector()'] |
|---|
| 997 | | hoc_commands += ['tmp = pc.take("%s[%d].%s", gatheredvec)' % (self.hoc_label, id, print_what), |
|---|
| 998 | | 'tmp = gatheredvec.printf(fileobj, fmt)'] |
|---|
| 999 | | hoc_commands += ['tmp = fileobj.close()'] |
|---|
| 1000 | | hoc_execute(hoc_commands,"--- Population[%s].__print()__ ---" %self.label) |
|---|
| | 1004 | self.__record('v', record_from, rng) |
|---|