예제 #1
0
    def createNewProject(self, file_name, pen_data):
            PenDataSegmentCategory.clearSegmentCache()

            self._project_settings = None

            self._name = file_name

            # Normalize pen sample times so first sample starts at 0.0 sec.
            self._original_timebase_offset=pen_data[0]['time']
            pen_data['time']-=self._original_timebase_offset
            pen_data['time']=pen_data['time']/1000.0

            # to flip data vertically by changing y pos values...
            # Maybe better to see if pyqtgraph has a built in option
            # to flip a plot vertically.
            #
            # pmax = pen_data['y'].max()
            # pmin = pen_data['y'].min()
            # pen_data['y'] = pmax-pen_data['y']+pmin

            self._pendata = pen_data
            self.nonzero_pressure_mask=self._pendata['pressure']>0
            # nonzero_regions_ix will be a tuple of (starts, stops, lengths) arrays
            self.nonzero_region_ix=contiguous_regions(self.nonzero_pressure_mask)
            self._segmentset=PenDataSegmentCategory(name=self.name,project=self)
            self._pendata['segment_id']=self._segmentset.id

            if self._selectedtimeregion is None:
                MarkWriteProject._selectedtimeregion = SelectedTimePeriodItem(project=self)
            else:
                MarkWriteProject._selectedtimeregion.project = self

            MarkWriteProject._selectedtimeregion.setBounds(bounds=(self.pendata['time'][0], self.pendata['time'][-1]))
            MarkWriteProject._selectedtimeregion.setRegion([self.pendata['time'][0], self.pendata['time'][0] + 1.0])
예제 #2
0
    def createNewProject(self, file_name, pen_data, condvars=None, stime_var=None, etime_var=None, file_type=None):
            PenDataSegmentCategory.clearSegmentCache()

            self._project_settings = None

            self._name = file_name
            self._filetype = file_type

            self._expcondvars = condvars
            self._stimevar = stime_var
            self._etimevar = etime_var

            # go through each trial, select only the samples within
            # the trial period, add the trials sample array to list of trial
            # sample data.
            samples_by_trial = []
            trial_times = None
            if self._expcondvars is not None and self._stimevar is not None and self._etimevar is not None:
                trial_times = []
                for t in self._expcondvars:
                    try:
                        trialstart = float(t[self._stimevar])
                        trialend = float(t[self._etimevar])
                        trial_times.append((trialstart,trialend))
                        trial_samples = pen_data[(pen_data['time'] >= trialstart) & (pen_data['time'] <= trialend)]
                        samples_by_trial.append(trial_samples)
                        #print "trial samples:",trial_samples.shape
                    except:
                        print("Error getting trial time period:")
                        import traceback
                        traceback.print_exc()

            if samples_by_trial:
                # make pen_data == concat'ed samples_by_trial
                pen_data = np.concatenate(samples_by_trial)

                # turn trial start, stop time list into np array
                trial_times = np.asarray(trial_times)

            # Normalize pen sample times so first sample starts at 0.0 sec.
            self._original_timebase_offset=pen_data[0]['time']
            pen_data['time']-=self._original_timebase_offset
            if trial_times is not None:
                trial_times-=self._original_timebase_offset
                self._trialtimes = trial_times

            # Change time stamps to sec.msec format, if needed
            if file_type != 'hdf5':
                # data from iohub hdf5 file is already in sec.msec format
                pen_data['time']=pen_data['time']/1000.0

            self._pendata = pen_data

            self.nonzero_pressure_mask=self._pendata['pressure']>0
            # nonzero_regions_ix will be a tuple of (starts, stops, lengths) arrays
            self.nonzero_region_ix=contiguous_regions(self.nonzero_pressure_mask)
            self._segmentset=PenDataSegmentCategory(name=self.name,project=self)
            self._pendata['segment_id']=self._segmentset.id

            if self._selectedtimeregion is None:
                MarkWriteProject._selectedtimeregion = SelectedTimePeriodItem(project=self)
            else:
                MarkWriteProject._selectedtimeregion.project = self
예제 #3
0
    def postprocess(cls,pendata):
        # Set initial sample state to HOVERING or PRESSED based on pressure
        pendata['state'][pendata['pressure']==0]=SAMPLE_STATES["HOVERING"]
        pendata['state'][pendata['pressure']>0]=SAMPLE_STATES["PRESSED"]

        # Calculate ISI value for samples 1-N
        sample_dts = pendata['time'][1:]-pendata['time'][:-1]
                
        # Handle non monotonic time stamped samples
        non_mono_ix = (sample_dts < 0.0).nonzero()[0]    
        if len(non_mono_ix)>0:
            non_mono_ix = non_mono_ix + 1
            print ">>>>>>>"
            print "WARNING: Non-monotonic Timestamps Detected."
            print "         Removing %d sample(s) with negative ISIs...."%(len(non_mono_ix))
            print "         Sample Indices:",non_mono_ix
            print "<<<<<<<"
            print
            # TODO: This code needs updating, it is a quick and dirty fix.
            #       Simply removes samples with negative ISI. In Guidos files,
            #       this seems to only occur within the first few samples
            #       of the file, if at all.
            pendata = np.delete(pendata,non_mono_ix)
            sample_dts = pendata['time'][1:]-pendata['time'][:-1]

        #
        # Detect Series Boundaries Using an ISI Threshold alg.
        #
        # Determine ISI threshold value to use
        if SETTINGS['series_detect_max_isi_msec'] > 0:
            series_isi_thresh = SETTINGS['series_detect_max_isi_msec']/1000.0
        else:
            try:
                series_isi_thresh = np.percentile(sample_dts,99.0,interpolation='nearest')*2.5
            except TypeError: 
                series_isi_thresh = np.percentile(sample_dts,99.0)*2.5
        print "series_isi_thresh:",series_isi_thresh
        print
        
        # Find sample array ix where ISI threshold is exceeded.
        # These are the series start ix
        series_start_ixs = (sample_dts > series_isi_thresh).nonzero()[0]
        if len(series_start_ixs)>0:
            series_start_ixs=series_start_ixs+1
        # First sample in data file is always a series start.
        series_start_ixs = np.insert(series_start_ixs, 0, 0)
        # Create list of series_start, series_end indexs for slicing
        series_bounds = []  # holds (series_start_ix, series_end_ix, 
                            # series_len, stime, etime, series_dur, series_dur/series_len)
        for i, start_ix in enumerate(series_start_ixs[:-1]):
            end_ix = series_start_ixs[i+1]
            stime, etime = pendata['time'][[start_ix,end_ix-1]]
            sdur = etime - stime 
            slen = end_ix-start_ix
            series_bounds.append((start_ix,end_ix,
                                  slen,stime, etime,sdur,sdur/slen))
        start_ix, end_ix = series_start_ixs[-1], len(pendata)
        stime, etime = pendata['time'][[start_ix,end_ix-1]]
        sdur = etime - stime 
        slen = end_ix-start_ix                         
        series_bounds.append((start_ix,end_ix,
                              slen,stime, etime,sdur,sdur/(slen-1)))

        # For each Sample Series in the data file,
        # 1) handle duplicate sample timestamps
        # 2) set FIRST_PRESS and FIRST_HOVER sample status as needed. 
        for i, sb in enumerate(series_bounds):
            # Cleanup duplicate timestamps after series bounds have been found
            # TODO: This code needs updating, it is a quick and dirty fix.
            #       A constant ISI across all series should really be used.
            dup_ix = (sample_dts[sb[0]:sb[1]] == 0.0).nonzero()[0]# + sb[0]    
            if len(dup_ix)>0:
                start_ix, end_ix, slen, stime, etime, sdur, sampling_interval = sb
                calc_sample_times, calc_isi = np.linspace(etime-slen*sampling_interval,etime,slen,retstep=True)
                print ">>>>>>>"
                print "Warning: Duplicate timestamps found in series", i+1, (stime, etime)
                print "         Sample / Duplicate Count:",slen,'/',len(dup_ix)
                print "         Calc. Series ISI:",calc_isi
                print "         Updating Series sample times......."
                print "<<<<<<<"
                print
                pendata['time'][start_ix:end_ix] = calc_sample_times[:]

            # Update sample state field to include FIRST_PRESS as needed
            run_start_ixs, _, _ = contiguous_regions(pendata['state'][sb[0]:sb[1]] == SAMPLE_STATES["PRESSED"])
            if len(run_start_ixs):
                run_start_ixs = np.array(run_start_ixs, dtype=np.uint32) + sb[0]
                pendata['state'][run_start_ixs]+= SAMPLE_STATES['FIRST_PRESS']        
            # Update sample state field to include FIRST_HOVER as needed
            hover_start_ixs, _, _ = contiguous_regions(pendata['state'][sb[0]:sb[1]] == SAMPLE_STATES["HOVERING"])
            if len(hover_start_ixs):
                hover_start_ixs = np.array(hover_start_ixs, dtype=np.uint32) + sb[0]
                pendata['state'][hover_start_ixs]+= SAMPLE_STATES['FIRST_HOVER']

        # For whole sample array, update series start sample's status
        # with FIRST_ENTER value.
        if len(series_start_ixs):
            pendata['state'][series_start_ixs] += SAMPLE_STATES['FIRST_ENTER']        
        
        # Return pendata array with sample state field populated.
        return pendata
예제 #4
0
    def postprocess(cls, pendata):
        # Set initial sample state to HOVERING or PRESSED based on pressure
        pendata['state'][pendata['pressure'] == 0] = SAMPLE_STATES["HOVERING"]
        pendata['state'][pendata['pressure'] > 0] = SAMPLE_STATES["PRESSED"]

        # Calculate ISI value for samples 1-N
        sample_dts = pendata['time'][1:] - pendata['time'][:-1]

        # Handle non monotonic time stamped samples
        non_mono_ix = (sample_dts < 0.0).nonzero()[0]
        if len(non_mono_ix) > 0:
            non_mono_ix = non_mono_ix + 1
            print ">>>>>>>"
            print "WARNING: Non-monotonic Timestamps Detected."
            print "         Removing %d sample(s) with negative ISIs...." % (
                len(non_mono_ix))
            print "         Sample Indices:", non_mono_ix
            print "<<<<<<<"
            print
            # TODO: This code needs updating, it is a quick and dirty fix.
            #       Simply removes samples with negative ISI. In Guidos files,
            #       this seems to only occur within the first few samples
            #       of the file, if at all.
            pendata = np.delete(pendata, non_mono_ix)
            sample_dts = pendata['time'][1:] - pendata['time'][:-1]

        #
        # Detect Series Boundaries Using an ISI Threshold alg.
        #
        # Determine ISI threshold value to use
        if SETTINGS['series_detect_max_isi_msec'] > 0:
            series_isi_thresh = SETTINGS['series_detect_max_isi_msec'] / 1000.0
        else:
            try:
                series_isi_thresh = np.percentile(
                    sample_dts, 99.0, interpolation='nearest') * 2.5
            except TypeError:
                series_isi_thresh = np.percentile(sample_dts, 99.0) * 2.5
        print "series_isi_thresh:", series_isi_thresh
        print

        # Find sample array ix where ISI threshold is exceeded.
        # These are the series start ix
        series_start_ixs = (sample_dts > series_isi_thresh).nonzero()[0]
        if len(series_start_ixs) > 0:
            series_start_ixs = series_start_ixs + 1
        # First sample in data file is always a series start.
        series_start_ixs = np.insert(series_start_ixs, 0, 0)
        # Create list of series_start, series_end indexs for slicing
        series_bounds = []  # holds (series_start_ix, series_end_ix,
        # series_len, stime, etime, series_dur, series_dur/series_len)
        for i, start_ix in enumerate(series_start_ixs[:-1]):
            end_ix = series_start_ixs[i + 1]
            stime, etime = pendata['time'][[start_ix, end_ix - 1]]
            sdur = etime - stime
            slen = end_ix - start_ix
            series_bounds.append(
                (start_ix, end_ix, slen, stime, etime, sdur, sdur / slen))
        start_ix, end_ix = series_start_ixs[-1], len(pendata)
        stime, etime = pendata['time'][[start_ix, end_ix - 1]]
        sdur = etime - stime
        slen = end_ix - start_ix
        series_bounds.append(
            (start_ix, end_ix, slen, stime, etime, sdur, sdur / (slen - 1)))

        # For each Sample Series in the data file,
        # 1) handle duplicate sample timestamps
        # 2) set FIRST_PRESS and FIRST_HOVER sample status as needed.
        for i, sb in enumerate(series_bounds):
            # Cleanup duplicate timestamps after series bounds have been found
            # TODO: This code needs updating, it is a quick and dirty fix.
            #       A constant ISI across all series should really be used.
            dup_ix = (sample_dts[sb[0]:sb[1]] == 0.0).nonzero()[0]  # + sb[0]
            if len(dup_ix) > 0:
                start_ix, end_ix, slen, stime, etime, sdur, sampling_interval = sb
                calc_sample_times, calc_isi = np.linspace(
                    etime - slen * sampling_interval,
                    etime,
                    slen,
                    retstep=True)
                print ">>>>>>>"
                print "Warning: Duplicate timestamps found in series", i + 1, (
                    stime, etime)
                print "         Sample / Duplicate Count:", slen, '/', len(
                    dup_ix)
                print "         Calc. Series ISI:", calc_isi
                print "         Updating Series sample times......."
                print "<<<<<<<"
                print
                pendata['time'][start_ix:end_ix] = calc_sample_times[:]

            # Update sample state field to include FIRST_PRESS as needed
            run_start_ixs, _, _ = contiguous_regions(
                pendata['state'][sb[0]:sb[1]] == SAMPLE_STATES["PRESSED"])
            if len(run_start_ixs):
                run_start_ixs = np.array(run_start_ixs,
                                         dtype=np.uint32) + sb[0]
                pendata['state'][run_start_ixs] += SAMPLE_STATES['FIRST_PRESS']
            # Update sample state field to include FIRST_HOVER as needed
            hover_start_ixs, _, _ = contiguous_regions(
                pendata['state'][sb[0]:sb[1]] == SAMPLE_STATES["HOVERING"])
            if len(hover_start_ixs):
                hover_start_ixs = np.array(hover_start_ixs,
                                           dtype=np.uint32) + sb[0]
                pendata['state'][hover_start_ixs] += SAMPLE_STATES[
                    'FIRST_HOVER']

        # For whole sample array, update series start sample's status
        # with FIRST_ENTER value.
        if len(series_start_ixs):
            pendata['state'][series_start_ixs] += SAMPLE_STATES['FIRST_ENTER']

        # Return pendata array with sample state field populated.
        return pendata