Changeset 209

Show
Ignore:
Timestamp:
09/23/08 18:50:44 (4 months ago)
Author:
pierre
Message:

Bugs and errors, like always. Implement the activity_movie function in a faster way, clean also all the AnalogSignal? part. Should work. To enhance compatibility, it would be good if pyNN could save, in the header, dimensions=[x,y,z] instead of dimensions=x\ty\z\. I will change it, hope nobody will be too affected. Add some functions to the AnalogSignal? object, like append, time_slice, id_slice, ...

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/cleanup/src/analysis.py

    r202 r209  
    88 
    99import os, numpy 
    10  
    1110 
    1211def ccf(x, y, axis=None): 
     
    6059    return iFxy/varxy 
    6160 
    62  
    63  
    64  
    65  
    66  
    67  
    68  
    69  
    70  
    71 def record(output, cfilename = 'SpikeTrainPlay.wav', fs=44100, enc = 'pcm26'): 
    72     """ record the 'sound' produced by a neuron. Takes a spike train as the 
    73     output. 
    74     >>> record(my_spike_train) 
    75     """ 
    76  
    77  
    78     # from the spike list 
    79     simtime_seconds = (output.t_stop - output.t_start)/1000. 
    80     #time = numpy.linspace(0, simtime_seconds , fs*simtime_seconds) 
    81     (trace,time) = numpy.histogram(output.spike_times*1000., fs*simtime_seconds) 
    82  
    83     # TODO convolve with proper spike... 
    84     spike = numpy.ones((fs/1000.,)) # one ms 
    85     trace = numpy.convolve(trace, spike, mode='same')#/2.0 
    86     trace /= numpy.abs(trace).max() * 1.1 
    87     try: 
    88         from scikits.audiolab import wavwrite 
    89     except ImportError: 
    90         print "You need the scikits.audiolab package to produce sounds !" 
    91     wavwrite(trace, cfilename, fs = fs, enc = enc) 
    92  
    93  
    94  
    95 def play(output): 
    96     """ 
    97     plays a spike list to the audio output 
    98     play(spike_list) where spike_list is a spike_list object 
    99     see playing_with_simple_single_neuron.py for a sample use 
    100     >>> play(my_spike_train) 
    101     TODO: make it possible to play multiple spike trains in stereo 
    102     """ 
    103  
    104  
    105     from tempfile import mkstemp 
    106     fd, cfilename   = mkstemp('SpikeListPlay.wav') 
    107     try: 
    108         record(output, cfilename) 
    109         import pyaudio 
    110         import wave 
    111  
    112         chunk = 1024 
    113         wf = wave.open(cfilename, 'rb') 
    114         p = pyaudio.PyAudio() 
    115  
    116         # open stream 
    117         stream = p.open(format = 
    118                         p.get_format_from_width(wf.getsampwidth()), 
    119                         channels = wf.getnchannels(), 
    120                         rate = wf.getframerate(), 
    121                         output = True) 
    122  
    123         # read data 
    124         data = wf.readframes(chunk) 
    125  
    126         # play stream 
    127         while data != '': 
    128             stream.write(data) 
    129             data = wf.readframes(chunk) 
    130  
    131         stream.close() 
    132         p.terminate() 
    133     except: 
    134         print "Error playing the SpikeTrain " 
    135         # finally 
    136         os.remove(cfilename) 
    137  
    138     # Python 2.4 compatibility 
    139     # finally: 
    140     os.remove(cfilename) 
    14161 
    14262def _dict_max(D): 
  • branches/cleanup/src/io.py

    r208 r209  
    5454        # The simplest way to do that, for the moment, is to supposed that you have 
    5555        # numpy 1.0.4 :-) 
    56         numpy.savetxt(filename, data
     56        numpy.savetxt(filename, data, delimiter="\t"
    5757 
    5858 
     
    7373        the SpikeList object, if saved in a text file 
    7474        """ 
    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      
     75        cmd = '' 
     76        f = open(self.filename, 'r') 
     77        for line in f.readlines(): 
     78            if line[0] == '#': 
     79                cmd += line[1:].strip() + ';' 
     80        f.close() 
     81        exec cmd in None, self.header 
     82         
     83 
    9384    def write_header(self, spikelist, filename): 
    9485        """ 
     
    9788        f = open(filename,"w") 
    9889        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)) 
     90        ids = numpy.array(spikelist.id_list)+1 
     91        f.write("# first_id = %d\n" % numpy.min(ids)) 
     92        f.write("# last_id = %d\n" % numpy.max(ids)) 
    10193        f.write("# dt = %g\n" % spikelist.dt) 
    10294        f.close() 
     
    161153     
    162154    def parse_header(self): 
    163         f      = open(self.filename, 'r') 
    164         line   = f.readline() 
    165         while line[0] == '#': 
    166             key, value = line[1:].strip().replace(" ","").split("=") 
    167             if key == "dimensions": 
    168                 value = value.split(" ") 
    169                 try: 
    170                     value.remove('') 
    171                 except Exception: 
    172                     pass 
    173                 for idx in xrange(len(value)): 
    174                     value[idx] = eval(value[idx]) 
    175                 self.header[key] = value 
    176             else: 
    177                 self.header[key] = eval(value) 
    178             line = f.readline() 
    179         f.close() 
     155        """ 
     156        Read the informations that may be contained in the header of 
     157        the SpikeList object, if saved in a text file 
     158        """ 
     159        cmd = '' 
     160        f = open(self.filename, 'r') 
     161        for line in f.readlines(): 
     162            if line[0] == '#': 
     163                cmd += line[1:].strip() + ';' 
     164        f.close() 
     165        exec cmd in None, self.header 
    180166 
    181167    def write_header(self, analogsignal, filename): 
    182168        f = open(filename,"w") 
    183169        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)) 
     170        ids = numpy.array(analogsignal.id_list)+1 
     171        f.write("# first_id = %d\n" % numpy.min(ids)) 
     172        f.write("# last_id = %d\n" % numpy.max(ids)) 
    186173        f.write("# dt = %g\n" % analogsignal.dt) 
    187174        f.close() 
  • branches/cleanup/src/signals.py

    r208 r209  
    459459        result[idx] = -(vec_2[idx]/vec_1[idx] -1) 
    460460        return numpy.sum(numpy.abs(result)) 
     461     
     462     
     463    def record(self, filename = 'SpikeTrain.wav', fs=44100): 
     464        """  
     465        Fancy tool, not really useful but still... 
     466        Record the 'sound' produced by a SpikeTrain. Need the scikits.audiolab 
     467        package 
     468         
     469        Inputs: 
     470            filename - the name of the output file (should have .wav extension) 
     471            fs       - the sampling rate 
     472         
     473        Examples: 
     474            >>> spktrain.record("my_sound.wav") 
     475        """ 
     476        # from the spike list 
     477        simtime_seconds = (self.t_stop - self.t_start)/1000. 
     478        (trace,time) = numpy.histogram(self.spike_times*1000., fs*simtime_seconds) 
     479        # TODO convolve with proper spike... 
     480        spike = numpy.ones((fs/1000.,)) # one ms 
     481        trace = numpy.convolve(trace, spike, mode='same')#/2.0 
     482        trace /= numpy.abs(trace).max() * 1.1 
     483        try: 
     484            from scikits.audiolab import wavwrite 
     485        except ImportError: 
     486            print "You need the scikits.audiolab package to produce sounds !" 
     487        wavwrite(trace, filename, fs = fs, enc = 'pcm26') 
    461488 
    462489    #################################################################### 
     
    551578class SpikeList(object): 
    552579    """ 
    553     SpikeList(spikes, id_list, dt=None, t_start=None, t_stop=None, dims=None, label=''
     580    SpikeList(spikes, id_list, dt=None, t_start=None, t_stop=None, dims=None
    554581     
    555582    Return a SpikeList object which will be a list of SpikeTrain objects. 
     
    562589        t_stop  - end of the SpikeList, in ms. If None, will be infered from the data 
    563590        dims    - dimensions of the recorded population, if not 1D population 
    564         label   - optionnal name to identify the SpikeList 
    565591     
    566592    dt, t_start and t_stop are shared for all SpikeTrains object within the SpikeList 
     
    704730            self.spiketrains[id] = spktrain.time_slice(self.t_start, self.t_stop) 
    705731            self.id_list.append(id) 
     732            self.N += 1 
    706733 
    707734    def get_time_parameters(self): 
     
    11221149        if len(self.dimensions) == 1: 
    11231150            return id 
    1124         if len(dims) == 2: 
     1151        if len(self.dimensions) == 2: 
    11251152            x = numpy.floor(id/self.dimensions[0]) 
    11261153            y = id % self.dimensions[1] 
     
    11361163            t_start         - if not defined, the one of the SpikeList is used 
    11371164            t_stop          - if not defined, the one of the SpikeList is used 
    1138             float_positions - None by default, meaning that the dimensions attribute of the SpikeList 
    1139                               is used to arange the ids on a 2D grid. Otherwise, if the cells have 
    1140                               flotting positions, float_positions should be an array of size 
    1141                               (2, nb_cells) with the x (first line) and y (second line) coordinates of 
    1142                               the cells 
    1143             display         - if True, a new figure is created. Could also be a subplot. The averaged 
    1144                               spike_histogram over the whole population is then plotted 
    1145             kwargs          - dictionary contening extra parameters that will be sent to the plot  
    1146                               function 
     1165            float_positions - None by default, meaning that the dimensions attribute  
     1166                              of the SpikeList is used to arange the ids on a 2D grid.  
     1167                              Otherwise, if the cells have flotting positions,  
     1168                              float_positions should be an array of size 
     1169                              (2, nb_cells) with the x (first line) and y (second line)  
     1170                              coordinates of the cells 
     1171            display         - if True, a new figure is created. Could also be a subplot.  
     1172                              The averaged spike_histogram over the whole population is  
     1173                              then plotted 
     1174            kwargs          - dictionary contening extra parameters that will be sent  
     1175                              to the plot function 
    11471176 
    11481177        The 'dimensions' attribute of the SpikeList is used to turn ids into 2d positions. It should 
     
    14071436 
    14081437 
    1409     def activity_movie(self, time_bin=10, t_start=None, t_stop=None, float_positions=None, output="animation.mpg", fps=10): 
     1438    def activity_movie(self, time_bin=10, t_start=None, t_stop=None, float_positions=None, output="animation.mpg", bounds=(0,5), fps=10, display = True, kwargs={}): 
    14101439        """ 
    14111440        Generate a movie of the activity between t_start and t_stop. 
     
    14131442         
    14141443        Inputs: 
    1415             time_bin        - time step to bin activity during the movie. One frame is the mean rate during time_bin 
     1444            time_bin        - time step to bin activity during the movie.  
     1445                              One frame is the mean rate during time_bin 
    14161446            t_start         - if not defined, the one of the SpikeList is used, in ms 
    14171447            t_stop          - if not defined, the one of the SpikeList is used, in ms 
     
    14211451                              (2, nb_cells) with the x (first line) and y (second line) coordinates of 
    14221452                              the cells 
    1423             bounds          - The common color bounds used during all the movies frame. This is a tuple 
     1453            output          - The filename to store the movie 
     1454            bounds          - The common color bounds used during all the movies frame.  
     1455                              This is a tuple 
    14241456                              of values (min, max), in spikes per frame. 
    1425             display         - if True, a new figure is created. Could also be a subplot. The averaged 
    1426                               spike_histogram over the whole population is then plotted 
     1457            fps             - The number of frame per second in the final movie 
     1458            display         - if True, a new figure is created. Could also be a subplot. 
    14271459            kwargs          - dictionary contening extra parameters that will be sent to the plot  
    14281460                              function 
     
    14381470        """ 
    14391471        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 
     1472        if t_start is None: t_start = self.t_start 
     1473        if t_stop is None:  t_stop  = self.t_stop 
    14421474        if not subplot or not ENABLE_PLOTS: 
    14431475            print MATPLOTLIB_ERROR 
    14441476        else: 
    1445             clim(bounds[0],bounds[1]) 
     1477            files        = [] 
     1478            activity_map = numpy.zeros(self.dimensions) 
     1479            im           = subplot.imshow(activity_map, **kwargs) 
     1480            im.set_clim(bounds[0],bounds[1]) 
     1481            im.colorbar() 
    14461482            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: 
     1483            idx       = 0 
     1484            manager   = pylab.get_current_fig_manager() 
     1485            if t_start != self.t_start or t_stop != self.t_stop: 
    14501486                spk   = spk.time_slice(t_start, t_stop) 
    14511487            else: 
     
    14531489            time, pos = spk.convert("times, ids") 
    14541490            # We sort the spikes to allow faster process later 
    1455             idx       = time.ravel().argsort() 
    1456             time      = time[idx] 
    1457             pos       = pos[idx] 
     1491            sort_idx  = time.ravel().argsort() 
     1492            time      = time[sort_idx] 
     1493            pos       = pos[sort_idx] 
     1494 
    14581495            if float_positions is None: 
    14591496                if self.dimensions is None: 
    14601497                    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): 
     1498            while (t_start < t_stop): 
     1499                activity_map = numpy.zeros(spk.dimensions) 
     1500                while (time[idx] < t_start + time_bin): 
    14641501                    addr = spk.id2position(pos[idx]) 
    1465                     activity_maps[addr] = activity_maps[addr] +
    1466                     count += 1 
    1467                 im.set_array(activity_maps
    1468                 title("time = %d ms" %t) 
     1502                    activity_map[addr] +=
     1503                    idx += 1 
     1504                im.set_array(activity_map
     1505                subplot.title("time = %d ms" %t_start) 
    14691506                manager.canvas.draw() 
    1470                 clim(bounds[0],bounds[1]) 
     1507                im.set_clim(bounds[0],bounds[1]) 
    14711508                fname = "_tmp_spikes_%05d.png" %count 
    14721509                print " Saving Frame", fname 
    1473                 savefig(fname) 
     1510                pylab.savefig(fname) 
    14741511                files.append(fname) 
    1475                 t     += dt 
     1512                t_start += time_bin 
    14761513                count += 1 
    14771514            print 'Making movie %s - this make take a while' %output 
     
    14821519            print "Clean up...." 
    14831520            for fname in files: os.remove(fname) 
    1484              
     1521 
    14851522 
    14861523    #################################################################### 
     
    16441681    def __getslice__(self, i, j): 
    16451682        """ 
    1646         Return a sublist of the spike_times vector of the SpikeTrain 
     1683        Return a sublist of the signal vector of the AnalogSignal 
    16471684        """ 
    16481685        return self.signal[i:j] 
     
    16611698 
    16621699    def time_axis(self): 
     1700        """ 
     1701        Return the time axis of the AnalogSignal 
     1702        """ 
    16631703        return numpy.arange(self.t_start, self.t_stop, self.dt) 
    16641704 
     
    16721712 
    16731713        """ 
    1674         signal = signal[t_start/self.dt,t_stop/self.dt] 
     1714        signal = self.signal[t_start/self.dt:t_stop/self.dt] 
    16751715        return AnalogSignal(signal, self.dt, t_start, t_stop) 
    16761716         
     
    16901730        t_stop  - end of the SpikeList, in ms. If None, will be infered from the data 
    16911731        dims    - dimensions of the recorded population, if not 1D population 
    1692         label   - optionnal name to identify the SpikeList 
    16931732     
    16941733    dt, t_start and t_stop are shared for all SpikeTrains object within the SpikeList 
    16951734     
    1696     Examples: 
    1697         >>> sl = SpikeList(3, [(0, 0.1), (1, 0.1), (0, 0.2)]) 
    1698         >>> type( sl[0] ) 
    1699         >>> <type SpikeTrain> 
    1700      
    17011735    See also 
    1702         loadCurrentTraces, loadMembraneTrace, loadConductanceTraces 
     1736        load_currentlist load_vmlist, load_conductancelist 
    17031737 
    17041738    """ 
     
    18001834 
    18011835    def append(self, id, signal): 
     1836        """ 
     1837        Add an AnalogSignal object to the AnalogSignalList 
     1838         
     1839        Inputs: 
     1840            id     - the id of the new cell 
     1841            signal - the AnalogSignal object representing the new cell 
     1842         
     1843        The AnalogSignal object is sliced according to the t_start and t_stop times 
     1844        of the AnalogSignallist object 
     1845         
     1846        See also 
     1847            __setitem__ 
     1848        """ 
    18021849        assert isinstance(signal, AnalogSignal), "An AnalogSignalList object can only contain AnalogSignal objects" 
    18031850        if id in self.id_list: 
    1804             raise Exception("Id already present in AnalogSignalList.Use setitem instead()") 
     1851            raise Exception("Id already present in AnalogSignalList. Use setitem instead()") 
    18051852        else: 
    18061853            self.analog_signals[id] = signal 
     
    18101857 
    18111858    def time_axis(self): 
     1859        """ 
     1860        Return the time axis of the AnalogSignalList object 
     1861        """ 
    18121862        return numpy.arange(self.t_start,self.t_stop,self.dt) 
    18131863 
    18141864    def id_slice(self, id_list): 
    1815         pass  
    1816      
     1865        """ 
     1866        Return a new AnalogSignalList obtained by selecting particular ids 
     1867         
     1868        Inputs: 
     1869            id_list - Can be an integer (and then N random cells will be selected) 
     1870                      or a sublist of the current ids 
     1871         
     1872        The new AnalogSignalList inherits the time parameters (t_start, t_stop, dt) 
     1873         
     1874        See also 
     1875            time_slice 
     1876        """ 
     1877        new_AnalogSignalList = AnalogSignalList([], [], self.dt, self.t_start, self.t_stop, self.dimensions) 
     1878        if isinstance(id_list, int): 
     1879            id_list = numpy.random.permutation(self.id_list)[0:id_list] 
     1880        for id in id_list: 
     1881            try: 
     1882                AnalogSignalList.append(id, self.analog_signals[id]) 
     1883            except Exception: 
     1884                print "id %d is not in the source AnalogSignalList" %id 
     1885        return new_AnalogSignalList 
     1886 
     1887    def time_slice(self, t_start, t_stop): 
     1888        """ 
     1889        Return a new AnalogSignalList obtained by slicing between t_start and t_stop 
     1890         
     1891        Inputs: 
     1892            t_start - begining of the new AnalogSignalList, in ms. 
     1893            t_stop  - end of the new AnalogSignalList, in ms. 
     1894         
     1895        See also 
     1896            id_slice 
     1897        """ 
     1898        new_AnalogSignalList = AnalogSignalList([], [], self.dt, t_start, t_stop, self.dimensions) 
     1899        for id in self.id_list: 
     1900            new_AnalogSignalList.append(id, self.analog_signals[id].time_slice(t_start, t_stop)) 
     1901        new_AnalogSignalList.__calc_startstop() 
     1902        return new_AnalogSignalList 
     1903 
    18171904    def save(self, filename, method="text"): 
    18181905        """ 
     
    18341921         
    18351922     
    1836     def time_slice(self, t_start, t_stop): 
    1837         pass 
    1838      
    1839  
    1840  
    18411923 
    18421924class VmList(AnalogSignalList): 
    18431925 
    18441926    def plot(self, id_list=None, v_thresh=None, display=True, kwargs={}): 
     1927        """ 
     1928        Plot all cells in the AnalogSignalList defined by id_list 
     1929         
     1930        Inputs: 
     1931            id_list - can be a integer (and then N cells are randomly selected) or a  
     1932                      list of ids. If None, we use all the ids of the SpikeList 
     1933            v_thresh- For graphical purpose, plot a spike when Vm > V_thresh. If None,  
     1934                      just plot the raw Vm 
     1935            display - if True, a new figure is created. Could also be a subplot 
     1936            kwargs  - dictionary contening extra parameters that will be sent to the plot  
     1937                      function 
     1938         
     1939        Examples: 
     1940            >>> z = subplot(221) 
     1941            >>> aslist.plot(5, v_thresh = -50, display=z, kwargs={'color':'r'}) 
     1942        """ 
    18451943        subplot   = self.__getdisplay__(display) 
    18461944        id_list   = self._AnalogSignalList__get_id_list(id_list) 
     
    18641962 
    18651963    def plot(self, id_list=None, v_thresh=None, display=True, kwargs={}): 
     1964        """ 
     1965        Plot all cells in the AnalogSignalList defined by id_list 
     1966         
     1967        Inputs: 
     1968            id_list - can be a integer (and then N cells are randomly selected) or a  
     1969                      list of ids. If None, we use all the ids of the SpikeList 
     1970            display - if True, a new figure is created. Could also be a subplot 
     1971            kwargs  - dictionary contening extra parameters that will be sent to the plot  
     1972                      function 
     1973         
     1974        Examples: 
     1975            >>> z = subplot(221) 
     1976            >>> aslist.plot(5, display=z, kwargs={'color':'r'}) 
     1977        """ 
    18661978        subplot   = self.__getdisplay__(display) 
    18671979        id_list   = self._AnalogSignalList__get_id_list(id_list) 
     
    18811993 
    18821994    def plot(self, id_list=None, v_thresh=None, display=True, kwargs={}): 
     1995        """ 
     1996        Plot all cells in the AnalogSignalList defined by id_list 
     1997         
     1998        Inputs: 
     1999            id_list - can be a integer (and then N cells are randomly selected) or a  
     2000                      list of ids. If None, we use all the ids of the SpikeList 
     2001            display - if True, a new figure is created. Could also be a subplot 
     2002            kwargs  - dictionary contening extra parameters that will be sent to the plot  
     2003                      function 
     2004         
     2005        Examples: 
     2006            >>> z = subplot(221) 
     2007            >>> aslist.plot(5, display=z, kwargs={'color':'r'}) 
     2008        """ 
    18832009        subplot   = self.__getdisplay__(display) 
    18842010        id_list   = self._AnalogSignalList__get_id_list(id_list)