Changeset 430

Show
Ignore:
Timestamp:
08/26/09 11:22:13 (3 years ago)
Author:
lestebanez
Message:

analog.py : port the analogSignalList to intervals. One issue : how to represent sliced analog signals ?
A list of sub-signals will not be very compatible with the current reprensentation.
Or reimplement all methods to take into account this new shape.

Location:
branches/interval/src/signals
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • branches/interval/src/signals/analogs.py

    r429 r430  
    7676        AnalogSignalList, load_currentlist, load_vmlist, load_conductancelist, load 
    7777    """ 
    78     def __init__(self, signal, dt, t_start=0, t_stop=None): 
    79         logging.debug("Creating AnalogSignal. len(signal)=%d, dt=%g, t_start=%g, t_stop=%s" % (len(signal), dt, t_start, t_stop)) 
    80         self.signal  = numpy.array(signal, float) 
     78    def __init__(self, signal, dt, t_start=0, t_stop=None, interval=None): 
     79        #logging.debug("Creating AnalogSignal. len(signal)=%d, dt=%g, t_start=%g, t_stop=%s" % (len(signal), dt, t_start, t_stop)) 
     80        self.signal  = signal 
    8181        self.dt      = float(dt) 
    8282        self.interval = self.create_intervals(t_start, t_stop, interval) 
     
    100100        else: 
    101101            if t_start is None and t_stop is None : 
    102                 try: 
    103                     t_start = numpy.min(self.spike_times) 
    104                 except Exception: 
    105                     print "AnalogSignal error in guessing t_start (first spike), spikes may be empty !" 
    106                     t_start = 0 
    107                 try: 
    108                     t_stop  = numpy.max(self.spike_times) 
    109                 except Exception: 
    110                     print "AnalogSignal error in guessing t_stop (last spike), spikes may be empty !" 
    111                     t_stop = t_start+self.dt 
     102                print "AnalogSignal interval derived from dt" 
     103                interval_out = Interval([[0,len(self.signal)*self.dt]]) 
     104            elif t_start is None and t_stop is not None: 
     105                interval_out = Interval([[t_stop - len(self.signal)*self.dt, t_stop]]) 
     106            elif t_start is not None and t_stop is not None: 
     107                if (t_stop - t_start)/self.dt != len(self.signal): 
     108                    print 't_start/t_stop and dt are not consistent with len(signal)' 
    112109                interval_out = Interval([[t_start, t_stop]]) 
    113             elif t_start is None and t_stop is not None: 
    114                 try: 
    115                     t_start  = numpy.min(self.spike_times) 
    116                 except Exception: 
    117                     print "AnalogSignal error in guessing t_start (first spike), spikes may be empty !" 
    118                     t_start = 0 
    119                 interval_out = Interval([[t_start, t_stop]]) 
    120             elif t_start is not None and t_stop is not None: 
    121                 interval_out = Interval([[t_start, t_stop]]) 
    122110            elif t_start is not None and t_stop is None: 
    123111                if type(t_start) == float or type(t_start) == int: 
    124                     try: 
    125                         t_stop  = numpy.max(self.spike_times) 
    126                     except Exception: 
    127                         print "AnalogSignal error in guessing t_stop (last spike), spikes may be empty !" 
    128                         t_stop = t_start+self.dt 
    129                     interval_out = Interval([[t_start, t_stop]])  
     112                    interval_out = Interval([[t_start, t_start + len(self.signal)*self.dt]]) 
    130113                else : 
    131114                    if type(t_start) == Interval: 
     
    135118        return interval_out 
    136119 
     120    def init_times(self): 
     121        """ 
     122        Update the t_start and t_stop constant to reflect the current t_start() and t_stop() methods 
     123        """ 
     124        self.t_start = self.interval.t_start() 
     125        self.t_stop  = self.interval.t_stop() 
    137126 
    138127    def __getslice__(self, i, j): 
     
    173162        Return the time axis of the AnalogSignal 
    174163        """ 
     164        self.init_times() 
     165 
    175166        if normalized: 
    176167            norm = self.t_start 
    177168        else: 
    178169            norm = 0. 
    179         return numpy.arange(self.t_start-norm, self.t_stop-norm, self.dt) 
     170 
     171        time_pavement = numpy.arange(self.t_start-norm, self.t_stop-norm, self.dt) 
     172        return SpikeTrain(time_pavement, interval=self.interval).spike_times 
    180173     
    181174    def time_offset(self, offset): 
     
    251244        i_stop = int((t_stop-self.t_start)/self.dt) 
    252245        signal = self.signal[i_start:i_stop] 
    253         result = AnalogSignal(signal, self.dt, t_start, t_stop) 
    254         return result 
     246 
     247        return AnalogSignal(signal, self.dt, t_start, t_stop) 
    255248 
    256249    def interval_slice(self, interval): 
     
    268261            time_slice 
    269262        """ 
    270         result = [] 
     263        signal_list = [] 
     264 
     265        if type(interval) is not Interval : 
     266            interval = Interval(interval) 
     267 
    271268        for itv in interval.interval_data : 
    272             result.append(self.signal[(intv[0]-self.t_start)/self.dt:(intv[1]-t_start)/self.dt]) 
    273         return result 
     269            signal_list.append(self.signal[(itv[0]-self.t_start)/self.dt:(itv[1]-self.t_start)/self.dt]) 
     270 
     271        return AnalogSignal(signal_list, self.dt, interval) 
    274272 
    275273    def threshold_detection(self, threshold=None, format=None,sign='above'): 
     
    428426         
    429427             
    430  
    431  
    432  
    433428class AnalogSignalList(object): 
    434429    """ 
     
    450445        load_currentlist load_vmlist, load_conductancelist 
    451446    """ 
    452     def __init__(self, signals, id_list, dt, t_start=0, t_stop=None, dims=None): 
    453         #logging.debug("Creating an AnalogSignalList. len(signals)=%d, min(id_list)=%d, max(id_list)=%d, dt=%g, t_start=%g, t_stop=%s, dims=%s" % \ 
    454         #                 (len(signals), min(id_list), max(id_list), dt, t_start, t_stop, dims)) 
    455          
    456         if t_start is None: 
    457             t_start = 0 
    458         self.t_start        = float(t_start) 
    459         self.t_stop         = t_stop 
     447    def __init__(self, signals, id_list, dt, t_start=None, t_stop=None, interval=None, dims=None): 
     448         
    460449        self.dt             = float(dt) 
    461450        self.dimensions     = dims 
    462451        self.analog_signals = {} 
    463452         
    464         signals = numpy.array(signals) 
    465          
     453        signals = numpy.array(signals)         
    466454        for id in id_list: 
    467             signal = numpy.transpose(signals[signals[:,0] == id, 1:])[0] 
     455            signal = signals[[signals[:,0] == id]][:,1] 
     456            #signal = numpy.transpose(signals[signals[:,0] == id, 1:])[0] 
    468457            if len(signal) > 0: 
    469                 self.analog_signals[id] = AnalogSignal(signal, self.dt, self.t_start, self.t_stop) 
    470          
    471         if id_list: 
    472             signals = self.analog_signals.values() 
    473             self.signal_length = len(signals[0]) 
    474             for signal in signals[1:]: 
    475                 if len(signal) != self.signal_length: 
    476                     raise Exception("Signals must all be the same length %d != %d" % (self.signal_length, len(signal))) 
    477         else: 
    478             logging.warning("id_list is empty") 
    479             self.signal_length = 0 
    480          
    481         if t_stop is None: 
    482             self.t_stop = self.t_start + self.signal_length*self.dt 
     458                self.analog_signals[id] = AnalogSignal(signal, self.dt) 
     459        self.interval = self.create_intervals(t_start, t_stop, interval) 
     460        self.init_times() 
     461        if len(self) > 0: 
     462            for id in self.id_list(): 
     463                self.analog_signals[id] = self.analog_signals[id].interval_slice(self.interval) 
     464                self.analog_signals[id].init_times() 
     465        self.init_times() 
     466 
     467        #if len(self.id_list()) == 0 : 
     468            #logging.warning("id_list is empty") 
     469            #self.signal_length = 0 
     470                     
     471    def create_intervals(self, t_start=None, t_stop=None, interval=None): 
     472        # due to the design of the __init__, all signals have the same length 
     473        if len(self.id_list()) > 0 : 
     474            signal = self.analog_signals[self.id_list()[0]] 
     475        else : 
     476            signal = numpy.array([]) 
     477        if hasattr(self, 'interval') and t_start is None and t_stop is None and interval is None: 
     478            interval_out = self.interval.copy() 
     479        elif interval is not None: 
     480            # interval is fully defined by the user 
     481            if type(interval) == Interval: 
     482                interval_out = interval.copy() 
     483            else : 
     484                interval_out = Interval(interval)  
     485        else: 
     486            if t_start is None and t_stop is None : 
     487                print "AnalogSignal interval derived from dt" 
     488                interval_out = Interval([[0,max([len(signal),1])*self.dt]]) 
     489            elif t_start is None and t_stop is not None: 
     490                interval_out = Interval([[t_stop - len(signal)*self.dt, t_stop]]) 
     491            elif t_start is not None and t_stop is not None: 
     492                if (t_stop - t_start)/self.dt != len(signal): 
     493                    print 't_start/t_stop and dt are not consistent with len(signal)' 
     494                interval_out = Interval([[t_start, t_stop]]) 
     495            elif t_start is not None and t_stop is None: 
     496                if type(t_start) == float or type(t_start) == int: 
     497                    interval_out = Interval([[t_start, t_start + len(signal)*self.dt]]) 
     498                else : 
     499                    if type(t_start) == Interval: 
     500                        interval_out = t_start.copy() 
     501                    else : 
     502                        interval_out = Interval(t_start) 
     503        return interval_out 
     504 
     505    def init_times(self): 
     506        """ 
     507        Update the t_start and t_stop constant to reflect the current t_start() and t_stop() methods 
     508        """ 
     509        self.t_start = self.interval.t_start() 
     510        self.t_stop  = self.interval.t_stop() 
    483511 
    484512    def id_list(self): 
     
    509537        if len(self) > 0: 
    510538            errmsgs = [] 
    511             for attr in "dt", "t_start", "t_stop": 
    512                 if getattr(val, attr) != getattr(self, attr): 
    513                     errmsgs.append("%s: %g != %g" % (attr, getattr(val, attr), getattr(self, attr))) 
    514             if len(val) != self.signal_length: 
    515                 errmsgs.append("signal length: %g != %g" % (len(val), self.signal_length)) 
    516             if errmsgs: 
    517                 raise Exception("AnalogSignal being added does not match the existing signals: "+", ".join(errmsgs)) 
     539            print numpy.shape(val.signal) 
     540            val = val.interval_slice(self.interval) 
     541            print numpy.shape(val.signal) 
     542            if not val.interval.is_equal(self.interval) : 
     543                raise Exception("the provided signal doesn't cover the AnalogSignalList interval") 
    518544        else: 
    519545            self.signal_length = len(val) 
     546            self.interval = self.create_intervals(t_start=None, t_stop=None, interval=val.interval) 
    520547            self.t_start = val.t_start 
    521548            self.t_stop = val.t_stop 
     
    560587        Return the time axis of the AnalogSignalList object 
    561588        """ 
    562         return numpy.arange(self.t_start, self.t_stop, self.dt) 
     589        self.init_times() 
     590        time_pavement = numpy.arange(self.t_start, self.t_stop, self.dt) 
     591        return SpikeTrain(time_pavement, interval=self.interval).spike_times 
    563592 
    564593    def id_offset(self, offset): 
     
    597626            time_slice 
    598627        """ 
     628        id_list = self.__sub_id_list(id_list) 
    599629        new_AnalogSignalList = AnalogSignalList([], [], self.dt, self.t_start, self.t_stop, self.dimensions) 
    600         id_list = self.__sub_id_list(id_list) 
     630 
    601631        for id in id_list: 
    602632            try: 
     
    617647            id_slice 
    618648        """ 
    619         new_AnalogSignalList = AnalogSignalList([], [], self.dt, t_start, t_stop, self.dimensions) 
     649         
     650        new_AnalogSignalList = AnalogSignalList([], [], self.dt, t_start, t_stop, interval=None, dims=self.dimensions) 
    620651        for id in self.id_list(): 
    621652            new_AnalogSignalList.append(id, self.analog_signals[id].time_slice(t_start, t_stop)) 
    622653        return new_AnalogSignalList 
     654 
     655    def interval_slice(self, interval): 
     656        """ 
     657        Return a new AnalogSignalList obtained by slicing between t_start and t_stop 
     658        Return only the parts of the AnalogSignal that are defined in the range of the interval.  
     659        The output is therefor a list of signal segments 
     660         
     661        Inputs: 
     662            interval - The Interval to slice the AnalogSignalList with 
     663         
     664        Examples: 
     665            >> as.interval_slice(Interval([0,100],[50,150])) 
     666 
     667        See also: 
     668            time_slice 
     669        """ 
     670        new_AnalogSignalList = AnalogSignalList([], self.id_list(), self.dt, t_start=None, t_stop=None, interval=interval, dims=self.dimensions) 
     671        for id in self.id_list(): 
     672            new_AnalogSignalList[id] = self.analog_signals[id].interval_slice(interval) 
     673        return new_AnalogSignalList 
     674 
    623675 
    624676    def select_ids(self, criteria=None): 
     
    725777            std 
    726778        """ 
    727         result = numpy.zeros(int((self.t_stop - self.t_start)/self.dt),float) 
    728         for id in self.id_list(): 
    729              result += self.analog_signals[id].signal 
    730         return result/len(self) 
     779        result = [] 
     780        for i in range(len(self.interval)) : 
     781            result.append(numpy.zeros(int((self.interval[i][1] - self.interval[i][0])/self.dt),float)) 
     782            for id in self.id_list(): 
     783                result[i] += self.analog_signals[id].signal[i] 
     784        return numpy.array(result)/len(self) 
    731785     
    732786    def std(self): 
     
    742796            mean 
    743797        """ 
    744         result = numpy.zeros((len(self), int((self.t_stop - self.t_start)/self.dt)),float) 
    745         for count, id in enumerate(self.id_list()): 
    746             try: 
    747                 result[count,:] = self.analog_signals[id].signal 
    748             except ValueError: 
    749                 print result[count,:].shape, self.analog_signals[id].signal.shape 
    750                 raise 
    751         return numpy.std(result, axis=0) 
     798        result = [] 
     799        for i in range(len(self.interval)) : 
     800            result.append(numpy.zeros((int((self.interval[i][1] - self.interval[i][0])/self.dt),len(self.id_list())),float)) 
     801           
     802            for j in range(len(self.id_list())): 
     803                result[i][j,:] = self.analog_signals[j].signal[i] 
     804        return [numpy.std(result[i], axis=0) for i in range(len(self.interval))] 
    752805 
    753806    def event_triggered_average(self, eventdict, events_ids = None, analogsignal_ids = None, average = True, t_min = 0, t_max = 100, ylim = None, display = False, mode = 'same', kwargs={}): 
     
    780833            >> vmlist.event_triggered_average({'1':[200,300,'3':[234,788]]}, average=False, display=True) 
    781834        """ 
     835 
    782836        if isinstance(eventdict, SpikeList): 
    783837            eventdict = eventdict.spiketrains 
     838 
     839        # remove times that are out of the interval +-tmin/tmax 
     840        filtered_eventdict = {} 
     841        for index, spike in enumerate(eventdict): 
     842            if ((spike-t_min) >= self.t_start) and ((spike+t_max) < self.t_stop): 
     843                filtered_eventdict[index] = spike 
     844 
    784845        figure   = get_display(display) 
    785846        subplotcount = 1 
    786847         
    787848        if events_ids is None: 
    788             events_ids = eventdict.keys() 
     849            events_ids = filtered_eventdict.keys() 
    789850        if analogsignal_ids is None: 
    790851            analogsignal_ids = self.analog_signals.keys() 
     
    797858         
    798859        for id in events_ids: 
    799             events = eventdict[id] 
     860            events = filtered_eventdict[id] 
    800861            if len(events) <= 0: 
    801862                continue 
  • branches/interval/src/signals/spikes.py

    r429 r430  
    103103        self.spike_times = self.interval.slice_times(numpy.array(self.spike_times, numpy.float32)) 
    104104 
    105         # We sort the spike_times. May be slowe, but required for 
     105        # We sort the spike_times. May be slow, but required for 
    106106        # several analysis methods 
    107107        self.spike_times = numpy.sort(self.spike_times, kind="quicksort")