Changeset 208
- Timestamp:
- 09/23/08 16:06:27 (4 months ago)
- Files:
-
- branches/cleanup/src/io.py (modified) (6 diffs)
- branches/cleanup/src/signals.py (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/cleanup/src/io.py
r207 r208 1 1 import numpy, os, logging, cPickle 2 2 DEFAULT_BUFFER_SIZE = 10000 3 4 try: 5 import pytable 6 ENABLE_HDF5 = True 7 except ImportError: 8 ENABLE_HDF5 = False 9 3 10 4 11 … … 11 18 def __init__(self, filename): 12 19 self.filename = filename 13 if not os.path.exists(filename):14 raise Exception("The file %s does not exists !" %filename)15 16 20 17 21 ### Function to load/save data with the pickle package. Much more faster than a simple 18 22 ### plain text file. Useful if you don't care about reading the spike files 19 23 def pickle_load(self): 24 """ 25 Try to load a binary format 26 """ 20 27 return cPickle.load(file(self.filename,"r")) 21 28 22 29 def pickle_write(self, object, filename): 30 """ 31 Dump an object to a binary format 32 """ 23 33 return cPickle.dump(object, file(filename, "w")) 24 34 … … 26 36 ### Function to load/save data in a text format. 27 37 def txt_load(self, sepchar = "\t", skipchar = "#"): 38 """ 39 Load a text file and returns a list of data 40 """ 28 41 myfile = open(self.filename, "r", DEFAULT_BUFFER_SIZE) 29 42 contents = myfile.readlines() … … 46 59 47 60 class SpikeListIO(object): 61 """ 62 Convenient object to load txt file and process them in order 63 to get a SpikeList object 64 """ 65 def __init__(self, filename): 66 self.filename = filename 67 self.data_io = DataIO(self.filename) 68 self.header = {} 69 70 def parse_header(self): 71 """ 72 Read the informations that may be contained in the header of 73 the SpikeList object, if saved in a text file 74 """ 75 f = open(self.filename, 'r') 76 line = f.readline() 77 while line[0] == '#': 78 key, value = line[1:].strip().replace(" ","").split("=") 79 if key == "dimensions": 80 value = value.split(" ") 81 try: 82 value.remove('') 83 except Exception: 84 pass 85 for idx in xrange(len(value)): 86 value[idx] = eval(value[idx]) 87 self.header[key] = value 88 else: 89 self.header[key] = eval(value) 90 line = f.readline() 91 f.close() 92 93 def write_header(self, spikelist, filename): 94 """ 95 Write the header of a SpikeList object into a file 96 """ 97 f = open(filename,"w") 98 f.write("# dimensions = %s\n" % spikelist.dimensions) 99 f.write("# first_id = %d\n" % numpy.min(spikelist.id_list+1)) 100 f.write("# last_id = %d\n" % numpy.max(spikelist.id_list+1)) 101 f.write("# dt = %g\n" % spikelist.dt) 102 f.close() 103 104 105 def get_spikelist(self, id_list=None, dt=None, t_start=None, t_stop=None, dims=None): 106 """ 107 Return the SpikeList object created after reading the file. Extra parameters may 108 be used to define the header, if informations are not available in the file 109 """ 110 # First, we try to see if the data are stored in a pickled way (MUCH FASTER) 111 try : 112 res = self.data_io.pickle_load() 113 return res 114 except Exception: 115 # Otherwise we try the text mode.... 116 self.parse_header() 117 if dt is None and 'dt' in self.header: 118 logging.debug("dt is infered from the file header") 119 dt = self.header['dt'] 120 if id_list is None: 121 if ('first_id' in self.header) and ('last_id' in self.header): 122 logging.debug("id_list is infered from the file header") 123 n_cells = int(self.header['last_id']) - int(self.header['first_id']) + 1 124 id_list = n_cells 125 else: 126 raise Exception("id_list not provided and cannot be inferred from file header.") 127 if dims is None and 'dimensions' in self.header: 128 dims = self.header['dimensions'] 129 if isinstance(id_list, int): # allows to just specify the number of neurons 130 id_list = range(id_list) 131 from NeuroTools import signals 132 return signals.SpikeList(self.data_io.txt_load(), id_list, dt, t_start, t_stop, dims) 133 134 def save_spikelist_pickle(self, spikelist, filename): 135 """ 136 Save the SpikeList object into a binary format 137 """ 138 self.data_io.pickle_write(spikelist, filename) 139 140 def save_spikelist_txt(self, spikelist, filename): 141 """ 142 Save the SpikeList into a text format 143 """ 144 self.write_header(spikelist, filename) 145 data = numpy.array(spikelist.convert(format="[times, ids]")) 146 data = data.reshape(data.shape[1],data.shape[0]) 147 self.data_io.txt_write(data, filename+".tmp") 148 os.system("cat %s >> %s" %(filename+".tmp", filename)) 149 os.system("rm %s" %(filename+".tmp")) 150 151 152 class AnalogSignalIO(object): 48 153 """ 49 154 Convenient object to load txt file and process them in order … … 73 178 line = f.readline() 74 179 f.close() 75 76 def write_header(self, spikelist, filename):180 181 def write_header(self, analogsignal, filename): 77 182 f = open(filename,"w") 78 f.write("# dimensions = %s\n" % spikelist.dimensions) 79 f.write("# first_id = %d\n" % numpy.min(spikelist.id_list)+1) 80 f.write("# last_id = %d\n" % numpy.max(spikelist.id_list)+1) 81 f.write("# dt = %g\n" % spikelist.dt) 82 f.close() 183 f.write("# dimensions = %s\n" % analogsignal.dimensions) 184 f.write("# first_id = %d\n" % numpy.min(analogsignal.id_list+1)) 185 f.write("# last_id = %d\n" % numpy.max(analogsignal.id_list+1)) 186 f.write("# dt = %g\n" % analogsignal.dt) 187 f.close() 188 189 def read_header(self, id_list=None, dt=None, t_start=None, t_stop=None, dims=None): 83 190 84 85 def get_spikelist(self, id_list=None, dt=None, t_start=None, t_stop=None, dims=None, label=None): 86 # First, we try to see if the data are stored in a pickled way (MUCH FASTER) 87 try : 88 res = self.data_io.pickle_load() 89 return res 90 except Exception: 91 # Otherwise we try the text mode.... 92 self.parse_header() 93 if dt is None and 'dt' in self.header: 94 logging.debug("dt is infered from the file header") 95 dt = self.header['dt'] 96 if (id_list is None): 97 if (('first_id' in self.header) and ('last_id' in self.header)): 98 logging.debug("id_list is infered from the file header") 99 n_cells = int(self.header['last_id']) - int(self.header['first_id']) + 1 100 id_list = n_cells 101 else: 102 raise Exception("id_list not provided and cannot be inferred from file header.") 103 if dims is None and 'dimensions' in self.header: 104 dims = self.header['dimensions'] 105 if label is None: 106 label = self.data_io.filename 107 if isinstance(id_list, int): # allows to just specify the number of neurons 108 id_list = range(id_list) 109 from NeuroTools import signals 110 return signals.SpikeList(self.data_io.txt_load(), id_list, dt, t_start, t_stop, dims, label) 111 112 def save_spikelist_pickle(self, spikelist, filename): 113 self.data_io.pickle_write(spikelist, filename) 114 115 def save_spikelist_txt(self, spikelist, filename): 116 self.write_header(spikelist, filename) 117 data = numpy.array(spikelist.convert(format="[times, ids]")) 118 data = data.reshape(data.shape[1],data.shape[0]) 191 self.parse_header() 192 if dt is None and 'dt' in self.header: 193 logging.debug("dt is infered from the file header") 194 dt = self.header['dt'] 195 else: 196 raise Exception("dt must be defined for creation of an AnalogSignal") 197 198 if id_list is None: 199 if ('first_id' in self.header) and ('last_id' in self.header): 200 logging.debug("id_list is infered from the file header") 201 n_cells = int(self.header['last_id']) - int(self.header['first_id']) + 1 202 id_list = n_cells 203 else: 204 raise Exception("id_list not provided and cannot be inferred from file header.") 205 206 if dims is None and 'dimensions' in self.header: 207 dims = self.header['dimensions'] 208 209 if isinstance(id_list, int): # allows to just specify the number of neurons 210 id_list = range(id_list) 211 212 return [id_list, dt, t_start, t_stop, dims] 213 214 def get_vmlist(self, id_list=None, dt=None, t_start=None, t_stop=None, dims=None): 215 from NeuroTools import signals 216 try: 217 res = self.data_io.pickle_load() 218 return res 219 except Exception: 220 d = self.read_header(id_list, dt, t_start, t_stop, dims) 221 return signals.VmList(self.data_io.txt_load(), d[0], d[1], d[2], d[3], d[4]) 222 223 def get_conductancelist(self, id_list=None, dt=None, t_start=None, t_stop=None, dims=None): 224 from NeuroTools import signals 225 try: 226 res = self.data_io.pickle_load() 227 return res 228 except Exception: 229 d = self.read_header(id_list, dt, t_start, t_stop, dims) 230 return signals.ConductanceList(self.data_io.txt_load(), d[0], d[1], d[2], d[3], d[4]) 231 232 def get_currentlist(self, id_list=None, dt=None, t_start=None, t_stop=None, dims=None): 233 from NeuroTools import signals 234 try: 235 res = self.data_io.pickle_load() 236 return res 237 except Exception: 238 d = self.read_header(id_list, dt, t_start, t_stop, dims) 239 return signals.CurrentList(self.data_io.txt_load(), d[0], d[1], d[2], d[3], d[4]) 240 241 def save_analogsignal_pickle(self, analogsignal, filename): 242 """ 243 Save the AnalogSignal object into a binary format 244 """ 245 self.data_io.pickle_write(analogsignal, filename) 246 247 def save_analogsignal_txt(self, analogsignal, filename): 248 """ 249 Save the AnalogSignal into a text format 250 """ 251 self.write_header(analogsignal, filename) 252 ###data = test 119 253 self.data_io.txt_write(data, filename+".tmp") 120 254 os.system("cat %s >> %s" %(filename+".tmp", filename)) 121 255 os.system("rm %s" %(filename+".tmp")) 122 256 123 #class HDF5DataLoader(object):124 #class HDF5SpikeListLoader(object):125 126 127 128 class AnalogSignalIO(object):129 """130 Convenient object to load txt file and process them in order131 to get a SpikeList object132 """133 def __init__(self, filename, signal_type):134 self.filename = filename135 self.loader = TxtDataLoader(self.filename)136 137 def parse_header(self):138 cmd = ''139 f = open(self.filename, 'r')140 for line in f.readlines():141 if line[0] == '#':142 cmd += line[1:].strip() + ';'143 f.close()144 header = {}145 exec cmd in None, header146 return header147 148 def get_dims(self, header):149 return 0150 151 def get_AnalogSignal(self, id_list=None, dt=None, t_start=None, t_stop=None, dims=None, label=None):152 header = self.parse_header()153 154 if dt is None and 'dt' in header:155 logging.debug("dt is infered from the file header")156 dt = header['dt']157 158 if (id_list is None) and (('first_id' in header) and ('last_id' in header)):159 logging.debug("id_list is infered from the file header")160 n_cells = int(header['last_id']) - int(header['first_id']) + 1161 id_list = n_cells162 else:163 raise Exception("id_list not provided and cannot be inferred from file header.")164 165 if dims is None and 'dimensions' in header:166 dims = self.get_dims(header['dimensions'])167 168 if label is None:169 label = self.loader.filename170 171 if isinstance(id_list, int): # allows to just specify the number of neurons172 id_list = range(id_list)173 174 from NeuroTools import signals175 return signals.SpikeList(self.loader.readData(), id_list, dt, t_start, t_stop, dims, label)176 177 178 179 257 ############################################## 180 258 ### WORK IN PROGRESS … … 184 262 185 263 186 def load_conductancetracelist(filename, id_list, dt = None, t_start=None, t_stop=None):187 if isinstance(id_list,int): # allows to just specify the number of neurons188 id_list = range(id_list)189 analog_signals = readFile(filename)190 return ConductanceTraceList(analog_signals, id_list, dt, t_start, t_stop)191 192 193 def load_membranetracelist(filename, id_list, dt = None, t_start=None, t_stop=None):194 if isinstance(id_list,int): # allows to just specify the number of neurons195 id_list = range(id_list)196 analog_signals = readFile(filename)197 return MembraneTraceList(analog_signals, id_list, dt, t_start, t_stop)198 199 200 def load_currenttracelist(filename, id_list, dt = None, t_start=None, t_stop=None):201 if isinstance(id_list,int): # allows to just specify the number of neurons202 id_list = range(id_list)203 analog_signals = readFile(filename)204 return CurrentTraceList(analog_signals, id_list, dt, t_start, t_stop)branches/cleanup/src/signals.py
r207 r208 10 10 try : 11 11 import pylab 12 ENABLE_PLOTS = True12 ENABLE_PLOTS = True 13 13 except ImportError: 14 ENABLE_PLOTS = False 15 print "Warning: pylab not detected, plots will be disabled" 14 ENABLE_PLOTS = False 15 MATPLOTLIB_ERROR = """ 16 Matplotlib not detected so plots are disabled. 17 To turn on plots, please install the Matplotlib package 18 """ 19 print MATPLOTLIB_ERROR 16 20 17 21 … … 331 335 subplot = self.__getdisplay__(display) 332 336 if not subplot or not ENABLE_PLOTS: 333 print "Plots are unfortunately disabled... Please install matplotlib"337 print MATPLOTLIB_ERROR 334 338 return 335 339 else: … … 574 578 ## Constructor and key methods to manipulate the SpikeList objects ## 575 579 ####################################################################### 576 def __init__(self, spikes, id_list, dt=None, t_start=None, t_stop=None, dims=None , label=''):580 def __init__(self, spikes, id_list, dt=None, t_start=None, t_stop=None, dims=None): 577 581 """ 578 582 Constructor of the SpikeList object … … 585 589 self.t_stop = t_stop 586 590 self.dt = dt 587 self.label = label588 591 self.dimensions = dims 589 592 self.N = len(id_list) … … 1386 1389 1387 1390 if not subplot or not ENABLE_PLOTS: 1388 print "Plots are unfortunately disabled... Please install matplotlib"1391 print MATPLOTLIB_ERROR 1389 1392 else: 1390 1393 ids, spike_times = spk.convert(format="[ids, times]") … … 1418 1421 (2, nb_cells) with the x (first line) and y (second line) coordinates of 1419 1422 the cells 1423 bounds - The common color bounds used during all the movies frame. This is a tuple 1424 of values (min, max), in spikes per frame. 1420 1425 display - if True, a new figure is created. Could also be a subplot. The averaged 1421 1426 spike_histogram over the whole population is then plotted … … 1427 1432 1428 1433 Examples: 1429 >> spklist.activity_map(0,1000,display=True) 1430 1431 See also 1432 activity_movie 1433 """ 1434 time = self.t_start 1435 files = [] 1436 while (time < self.t_stop): 1437 subSpkList = self.time_slice(time, time + time_bin) 1438 activity_map = subSpkList.activity_map(dims, bounds, display=True) 1439 caption = time+time_bin/2 1440 pylab.title("Time = %g ms" %caption) 1441 fname = "_tmp_%g.jpg" %caption 1442 print " Saving Frame", fname 1443 pylab.savefig(fname) 1444 pylab.close() 1445 files.append(fname) 1446 time += time_bin 1447 print 'Making movie %s - this make take a while' %output 1448 command = "mencoder 'mf://_tmp_*.jpg' -mf type=jpg:fps=%d -ovc lavc -lavcopts vcodec=wmv2 -oac copy -o %s" %(fps,output) 1449 print command 1450 os.system(command) 1451 ## cleanup 1452 print "Clean up...." 1453 for fname in files: os.remove(fname) 1454 #clim(bounds[0],bounds[1]) 1455 #count = 0 1456 #manager = get_current_fig_manager() 1457 1458 #while (t < t_stop): 1459 #for idx in xrange(len(spk)): 1460 #activity_maps[idx] = zeros((N,N)) 1461 #tmp_idx = idefix[idx] 1462 #while((time[idx][tmp_idx] < t + dt) and (tmp_idx < len(position[idx])-1)): 1463 #activity_maps[idx][tuple(position[idx][tmp_idx])] = activity_maps[idx][tuple(position[idx][tmp_idx])] + 1 1464 #tmp_idx += 1 1465 #idefix[idx] = tmp_idx 1466 #im[idx].set_array(activity_maps[idx]) 1467 ##title("time = %d ms" %t) 1468 #manager.canvas.draw() 1469 #clim(bounds[0],bounds[1]) 1470 #fname = "_tmp_spikes_%05d.png" %count 1471 #print " Saving Frame", fname 1472 #savefig(fname) 1473 #files.append(fname) 1474 #t += dt 1475 #count += 1 1476 1434 >> spklist.activity_movie(10,0,1000,bounds=(0,5),display=subplot(221),output="test.mpg") 1435 1436 See also 1437 activity_map 1438 """ 1439 subplot = self.__getdisplay__(display) 1440 if t_start is None: t_start = spk.t_start 1441 if t_stop is None: t_stop = spk.t_stop 1442 if not subplot or not ENABLE_PLOTS: 1443 print MATPLOTLIB_ERROR 1444 else: 1445 clim(bounds[0],bounds[1]) 1446 count = 0 1447 manager = get_current_fig_manager() 1448 t = t_start 1449 if t_start != spk.t_start or t_stop != spk.t_stop: 1450 spk = spk.time_slice(t_start, t_stop) 1451 else: 1452 spk = self 1453 time, pos = spk.convert("times, ids") 1454 # We sort the spikes to allow faster process later 1455 idx = time.ravel().argsort() 1456 time = time[idx] 1457 pos = pos[idx] 1458 if float_positions is None: 1459 if self.dimensions is None: 1460 raise Exception("Dimensions of the population are not defined ! Set spikelist.dims") 1461 while (t < t_stop): 1462 activity_maps = zeros(spk.dimensions) 1463 while (time[count] < t + time_bin): 1464 addr = spk.id2position(pos[idx]) 1465 activity_maps[addr] = activity_maps[addr] + 1 1466 count += 1 1467 im.set_array(activity_maps) 1468 title("time = %d ms" %t) 1469 manager.canvas.draw() 1470 clim(bounds[0],bounds[1]) 1471 fname = "_tmp_spikes_%05d.png" %count 1472 print " Saving Frame", fname 1473 savefig(fname) 1474 files.append(fname) 1475 t += dt 1476 count += 1 1477 print 'Making movie %s - this make take a while' %output 1478 command = "mencoder 'mf://_tmp_*.jpg' -mf type=jpg:fps=%d -ovc lavc -lavcopts vcodec=wmv2 -oac copy -o %s" %(fps,output) 1479 print command 1480 os.system(command) 1481 ## cleanup 1482 print "Clean up...." 1483 for fname in files: os.remove(fname) 1484 1477 1485 1478 1486 #################################################################### … … 1587 1595 1588 1596 1589 def load_spikelist(filename, id_list=None, dt = None, t_start=None, t_stop=None, dims=None, label=None): 1597 class AnalogSignal(object): 1598 """ 1599 AnalogSignal(signal, dt, t_start=None, t_stop=None) 1600 1601 Return a AnalogSignal object which will be a analog signal trace 1602 1603 Inputs: 1604 signal - the vector with the data of the AnalogSignal 1605 dt - the time step between two data points of the sampled analog signal 1606 t_start - begining of the signal, in ms. If None, will be set to 0 1607 t_stop - end of the SpikeList, in ms. If None, will be infered from the data 1608 1609 Examples: 1610 >>> as = AnalogSignal(range(100), dt=0.1, t_start=0, t_stop=10) 1611 1612 See also 1613 AnalogSignalList, load_currenttraces, load_membranetrace, load_conductancetraces 1614 1615 """ 1616 def __init__(self, signal, dt, t_start=None, t_stop=None): 1617 1618 self.signal = numpy.array(signal,float) 1619 self.dt = dt 1620 self.t_start = t_start 1621 self.t_stop = t_stop 1622 1623 # If t_start is not None, we resize the signal keeping only 1624 # elements with t >= t_start 1625 if self.t_start is not None: 1626 self.signal = self.signal[(self.t_start/self.dt):] 1627 1628 # If t_stop is not None, we resize the signal keeping only 1629 # elements with t <= t_stop 1630 if self.t_stop is not None: 1631 self.signal = self.signal[:(self.t_stop-self.t_start)/self.dt] 1632 1633 if len(self.signal) > 0: # spike list may be empty 1634 if self.t_start is None: 1635 self.t_start = 0. 1636 if self.t_stop is None: 1637 self.t_stop = len(self.signal)*self.dt 1638 1639 # TODO raise an error if some data is outside [t_start, t_stop] ? 1640 #TODO return an exception if self.t_stop < self.t_start (when not empty) 1641 if self.t_start >= self.t_stop : 1642 raise Exception("Incompatible time interval for the creation of the AnalogSignal") 1643 1644 def __getslice__(self, i, j): 1645 """ 1646 Return a sublist of the spike_times vector of the SpikeTrain 1647 """ 1648 return self.signal[i:j] 1649 1650 def duration(self): 1651 """ 1652 Return the duration of the SpikeTrain 1653 """ 1654 return self.t_stop - self.t_start 1655 1656 def __str__(self): 1657 return str(self.signal) 1658 1659 def __len__(self): 1660 return len(self.signal) 1661 1662 def time_axis(self): 1663 return numpy.arange(self.t_start, self.t_stop, self.dt) 1664 1665 def time_slice(self, t_start, t_stop): 1666 """ 1667 Return a new AnalogSignal obtained by slicing between t_start and t_stop 1668 1669 Inputs: 1670 t_start - begining of the new SpikeTrain, in ms. 1671 t_stop - end of the new SpikeTrain, in ms. 1672 1673 """ 1674 signal = signal[t_start/self.dt,t_stop/self.dt] 1675 return AnalogSignal(signal, self.dt, t_start, t_stop) 1676 1677 1678 1679 class AnalogSignalList(object): 1680 """ 1681 AnalogSignalList(signals, id_list, dt=None, t_start=None, t_stop=None) 1682 1683 Return a AnalogSignalList object which will be a list of AnalogSignal objects. 1684 1685 Inputs: 1686 signals - a list of the AnalogSignals objects 1687 id_list - the list of the ids of all recorded cells (needed for silent cells) 1688 dt - if dt is specified, time values should be floats 1689 t_start - begining of the SpikeList, in ms. If None, will be infered from the data 1690 t_stop - end of the SpikeList, in ms. If None, will be infered from the data 1691 dims - dimensions of the recorded population, if not 1D population 1692 label - optionnal name to identify the SpikeList 1693 1694 dt, t_start and t_stop are shared for all SpikeTrains object within the SpikeList 1695 1696 Examples: 1697 >>> sl = SpikeList(3, [(0, 0.1), (1, 0.1), (0, 0.2)]) 1698 >>> type( sl[0] ) 1699 >>> <type SpikeTrain> 1700 1701 See also 1702 loadCurrentTraces, loadMembraneTrace, loadConductanceTraces 1703 1704 """ 1705 def __init__(self, signals, id_list, dt=None, t_start=None, t_stop=None, dims=None): 1706 self.id_list = id_list 1707 self.N = len(id_list) 1708 self.t_start = t_start 1709 self.t_stop = t_stop 1710 self.dt = dt 1711 self.dimensions = dims 1712 self.analog_signals = {} 1713 for id in id_list: 1714 self.analog_signals[id] = [] 1715 for id,value in signals: 1716 self.analog_signals[id].append(value) 1717 1718 if t_start is None: 1719 self.t_start = 0 1720 1721 # writing as a list of SpikeTrains 1722 for id,signal in self.analog_signals.items(): #TODO: handle missing fields 1723 self.analog_signals[id] = AnalogSignal(signal, dt=dt, t_start=self.t_start, t_stop=self.t_stop) 1724 if t_start is None or t_stop is None: 1725 self.__calc_startstop() 1726 1727 1728 def __calc_startstop(self): 1729 """ 1730 t_start and t_stop are shared for all neurons, so we take min and max values respectively. 1731 TO DO : check the t_start and t_stop parameters for a SpikeList. Is it commun to 1732 all the spikeTrains within the spikelist or each spikelistes do need its own. 1733 """ 1734 if len(self) > 0: 1735 if self.t_start is None: 1736 start_times = numpy.array([self.analog_signals[idx].t_start for idx in self.id_list]) 1737 self.t_start = numpy.min(start_times) 1738 logging.debug("Warning, t_start is infered from the data : %f" %self.t_start) 1739 for id in self.analog_signals.keys(): 1740 self.analog_signals[id].t_start = self.t_start 1741 if self.t_stop is None: 1742 stop_times = numpy.array([self.analog_signals[idx].t_stop for idx in self.id_list]) 1743 self.t_stop = numpy.max(stop_times) 1744 logging.debug("Warning, t_stop is infered from the data : %f" %self.t_stop) 1745 for id in self.analog_signals.keys(): 1746 self.analog_signals[id].t_stop = self.t_stop 1747 else: 1748 raise Exception("No Analog Signals !") 1749 1750 def __getdisplay__(self,display): 1751 """ 1752 Return a pylab object with a plot() function to draw the plots. 1753 1754 Inputs: 1755 display - if True, a new figure is created. Otherwise, if display is a 1756 subplot object, this object is returned. 1757 """ 1758 if display is False: 1759 return None 1760 elif display is True: 1761 pylab.figure() 1762 return pylab 1763 else: 1764 return display 1765 1766 def __labels__(self, subplot, xlabel, ylabel): 1767 """ 1768 Function to put some labels on a plot 1769 1770 Inputs: 1771 subplot - the targeted plot 1772 xlabel - a string for the x label 1773 ylabel - a string for the y label 1774 """ 1775 if hasattr(subplot, 'xlabel'): 1776 subplot.xlabel(xlabel) 1777 subplot.ylabel(ylabel) 1778 else: 1779 subplot.set_xlabel(xlabel) 1780 subplot.set_ylabel(ylabel) 1781 1782 def __getitem__(self, i): 1783 return self.analog_signals[i] 1784 1785 def __setitem__(self, i, val): 1786 assert isinstance(val, SpikeTrain), "An AnalogSignalList object can only contain AnalogSignal objects" 1787 self.analog_signals[i] = val 1788 self.__calc_startstop() 1789 1790 def __len__(self): 1791 return len(self.analog_signals) 1792 1793 def __get_id_list(self, sub_list=None): 1794 if sub_list == None: 1795 return self.id_list 1796 if type(sub_list) == int: 1797 return numpy.random.permutation(self.id_list)[0:sub_list] 1798 if type(sub_list) == list: 1799 return sub_list 1800 1801 def append(self, id, signal): 1802 assert isinstance(signal, AnalogSignal), "An AnalogSignalList object can only contain AnalogSignal objects" 1803 if id in self.id_list: 1804 raise Exception("Id already present in AnalogSignalList.Use setitem instead()") 1805 else: 1806 self.analog_signals[id] = signal 1807 self.id_list.append(id) 1808 self.N += 1 1809 self.__calc_startstop() 1810 1811 def time_axis(self): 1812 return numpy.arange(self.t_start,self.t_stop,self.dt) 1813 1814 def id_slice(self, id_list): 1815 pass 1816 1817 def save(self, filename, method="text"): 1818 """ 1819 Save the AnalogSignal in a text or binary file 1820 1821 Inputs: 1822 filename - name of the output file 1823 method - "text" -> a classical human readible text file 1824 "pickle" -> binary backup, much more faster to load/save, 1825 but no longer human readible 1826 "hdf5" -> a compress an optimized structure, not 1827 implemented yet 1828 """ 1829 as_loader = io.AnalogSignalIO(filename) 1830 if method == "pickle": 1831 as_loader.save_analogsignal_pickle(self, filename) 1832 if method == "text": 1833 as_loader.save_analogsignal_txt(self, filename) 1834 1835 1836 def time_slice(self, t_start, t_stop): 1837 pass 1838 1839 1840 1841 1842 class VmList(AnalogSignalList): 1843 1844 def plot(self, id_list=None, v_thresh=None, display=True, kwargs={}): 1845 subplot = self.__getdisplay__(display) 1846 id_list = self._AnalogSignalList__get_id_list(id_list) 1847 time_axis = self.time_axis() 1848 if not subplot or not ENABLE_PLOTS: 1849 print MATPLOTLIB_ERROR 1850 else: 1851 xlabel = "Time (ms)" 1852 ylabel = "Membrane Potential (mV)" 1853 self.__labels__(subplot, xlabel, ylabel) 1854 for id in id_list: 1855 to_be_plot = self.analog_signals[id].signal 1856 if v_thresh is not None: 1857 to_be_plot = pylab.where(to_be_plot>=v_thresh-0.05,0.0,to_be_plot) 1858 subplot.plot(time_axis, to_be_plot, **kwargs) 1859 subplot.hold(1) 1860 pylab.draw() 1861 1862 1863 class CurrentList(AnalogSignalList): 1864 1865 def plot(self, id_list=None, v_thresh=None, display=True, kwargs={}): 1866 subplot = self.__getdisplay__(display) 1867 id_list = self._AnalogSignalList__get_id_list(id_list) 1868 time_axis = self.time_axis() 1869 if not subplot or not ENABLE_PLOTS: 1870 print MATPLOTLIB_ERROR 1871 else: 1872 xlabel = "Time (ms)" 1873 ylabel = "Current (nA)" 1874 self.__labels__(subplot, xlabel, ylabel) 1875 for id in id_list: 1876 subplot.plot(time_axis, self.analog_signals[id].signal, **kwargs) 1877 subplot.hold(1) 1878 pylab.draw() 1879 1880 class ConductanceList(AnalogSignalList): 1881 1882 def plot(self, id_list=None, v_thresh=None, display=True, kwargs={}): 1883 subplot = self.__getdisplay__(display) 1884 id_list = self._AnalogSignalList__get_id_list(id_list) 1885 time_axis = self.time_axis() 1886 if not subplot or not ENABLE_PLOTS: 1887 print MATPLOTLIB_ERROR 1888 else: 1889 xlabel = "Time (ms)" 1890 ylabel = "Conductance (nS)" 1891 self.__labels__(subplot, xlabel, ylabel) 1892 for id in id_list: 1893 subplot.plot(time_axis, self.analog_signals[id].signal, **kwargs) 1894 subplot.hold(1) 1895 pylab.draw() 1896 1897 1898 1899 ############################################################# 1900 ## Object Loaders. Functions used to create NeuroTools 1901 ## objects from data generated by pyNN (the most simple form 1902 ## supported right now) 1903 ############################################################# 1904 1905 def load_spikelist(filename, id_list=None, dt = None, t_start=None, t_stop=None, dims=None): 1590 1906 """ 1591 1907 Returns a SpikeList object from a file. If the file has been generated by PyNN, … … 1608 1924 """ 1609 1925 spike_loader = io.SpikeListIO(filename) 1610 return spike_loader.get_spikelist(id_list, dt, t_start, t_stop, dims, label) 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 class AnalogSignal(object): 1632 1633 def __init__(self, signal, dt, t_start=None, t_stop=None): 1634 1635 self.signal = numpy.array(signal,float) 1636 self.dt = dt 1637 self.t_start = t_start 1638 self.t_stop = t_stop 1639 1640 # If t_start is not None, we resize the signal keeping only 1641 # elements with t >= t_start 1642 if self.t_start is not None: 1643 self.signal = self.signal[(self.t_start/self.dt):] 1644 1645 # If t_stop is not None, we resize the signal keeping only 1646 # elements with t <= t_stop 1647 if self.t_stop is not None: 1648 self.signal = self.signal[:(self.t_stop-self.t_start/self.dt)] 1649 1650 if len(signal) > 0: # spike list may be empty 1651 if self.t_start is None: 1652 self.t_start = 0. 1653 if self.t_stop is None: 1654 self.t_stop = len(self.signal)*self.dt 1655 1656 # TODO raise an error if some data is outside [t_start, t_stop] ? 1657 #TODO return an exception if self.t_stop < self.t_start (when not empty) 1658 if self.t_start >= self.t_stop : 1659 raise("Incompatible time interval for the creation of the AnalogSignal") 1660 1661 def __getslice__(self, i, j): 1662 """ 1663 Return a sublist of the spike_times vector of the SpikeTrain 1664 """ 1665 return self.signal[i:j] 1666 1667 def duration(self): 1668 """ 1669 Return the duration of the SpikeTrain 1670 """ 1671 return self.t_stop - self.t_start 1672 1673 def __str__(self): 1674 return str(self.signal) 1675 1676 def __len__(self): 1677 return len(self.signal) 1678 1679 def time_axis(self): 1680 return numpy.arange(self.t_start, self.t_stop, self.dt) 1681 1682 1683 class AnalogSignalList(object): 1926 return spike_loader.get_spikelist(id_list, dt, t_start, t_stop, dims) 1927 1928 1929 1930 def load_conductancelist(filename, id_list=None, dt = None, t_start=None, t_stop=None, dims=None): 1684 1931 """ 1685 AnalogSignalList(signals, id_list, dt=None, t_start=None, t_stop=None) 1686 1687 Return a AnalogSignalList object which will be a list of AnalogSignal objects. 1688 1932 Returns a ConductanceList object from a file. If the file has been generated by PyNN, 1933 a header should be found with following parameters: 1934 ---> dims, dt, id of the first cell, id of the last cell. 1935 They must be specified otherwise. Then the classical PyNN format for text file is: 1936 ---> one line per event: data value, GID 1937 1689 1938 Inputs: 1690 signals - a list of the AnalogSignal 1691 id_list - the list of the ids of all recorded cells (needed for silent cells) 1692 dt - if dt is specified, time values should be floats 1693 t_start - begining of the SpikeList, in ms. If None, will be infered from the data 1694 t_stop - end of the SpikeList, in ms. If None, will be infered from the data 1695 dims - dimensions of the recorded population, if not 1D population 1696 label - optionnal name to identify the SpikeList 1697 1698 dt, t_start and t_stop are shared for all SpikeTrains object within the SpikeList 1699 1700 Examples: 1701 >>> sl = SpikeList(3, [(0, 0.1), (1, 0.1), (0, 0.2)]) 1702 >>> type( sl[0] ) 1703 >>> <type SpikeTrain> 1704 1705 See also 1706 loadCurrentTraces, loadMembraneTrace, loadConductanceTraces 1707 1939 filename - the name of the spike file 1940 id_list - the list of the recorded ids. Can be an int (meaning cells in the range (0,..,N)), 1941 or a list. 1942 dims - if the cells were aranged on a 2/3D grid, a tuple with the dimensions 1943 dt - the discretization step, in ms 1944 t_start - begining of the simulation, in ms. 1945 t_stop - end of the simulation, in ms 1946 1947 If dims, dt, t_start, t_stop or id_list are None, they will be infered from either the data or from the header. 1948 All times are in milliseconds. The format of the file (text, pickle or hdf5) will be inferred automatically 1708 1949 """ 1709 def __init__(self, signals, id_list, dt=None, t_start=None, t_stop=None): 1710 self.id_list = id_list 1711 self.N = len(id_list) 1712 self.t_start = t_start 1713 self.t_stop = t_stop 1714 self.dt = dt 1715 self.analog_signals = {} 1716 for id in id_list: 1717 self.analog_signals[id] = [] 1718 for id,value in signals: 1719 self.analog_signals[id].append(value) 1720 1721 # writing as a list of SpikeTrains 1722 for id,signal in self.analog_signals.items(): #TODO: handle missing fields 1723 self.analog_signals[id] = AnalogSignal(signal, dt=dt, t_start=self.t_start, t_stop=self.t_stop) 1724 if t_start is None or t_stop is None: 1725 self.__calc_startstop() 1726 #self.spiketrains.append( SpikeTrain(spike_array[i_neuron], dt=dt )) 1727 1728 def __calc_startstop(self): 1729 """ 1730 t_start and t_stop are shared for all neurons, so we take min and max values respectively. 1731 TO DO : check the t_start and t_stop parameters for a SpikeList. Is it commun to 1732 all the spikeTrains within the spikelist or each spikelistes do need its own. 1733 """ 1734 if len(self) > 0: 1735 if self.t_start is None: 1736 self.t_start = 0. 1737 #if self.t_stop is None: 1738 # 1739 else: 1740 raise Exception("No Analog Signals !") 1741 1742 def __getdisplay__(self,display): 1743 """ 1744 Return a pylab object with a plot() function to draw the plots. 1745 1746 Inputs: 1747 display - if True, a new figure is created. Otherwise, if display is a 1748 subplot object, this object is returned. 1749 """ 1750 if display is False: 1751 return None 1752 elif display is True: 1753 pylab.figure() 1754 return pylab 1755 else: 1756 return display 1757 1758 def __labels__(self, subplot, xlabel, ylabel): 1759 """ 1760 Function to put some labels on a plot 1761 1762 Inputs: 1763 subplot - the targeted plot 1764 xlabel - a string for the x label 1765 ylabel - a string for the y label 1766 """ 1767 if hasattr(subplot, 'xlabel'): 1768 subplot.xlabel(xlabel) 1769 subplot.ylabel(ylabel) 1770 else: 1771 subplot.set_xlabel(xlabel) 1772 subplot.set_ylabel(ylabel) 1773 1774 def __getitem__(self, i): 1775 return self.analog_signals[i] 1776 1777 def __setitem__(self, i, val): 1778
