Пример #1
0
    def events_find_events(self, raw, **param):
        """
        some how calls <mne.find_events()>
        input:
             raw obj,
             e.g. parameters:
              {'event_id': 40, 'and_mask': 255,
               'events': {'consecutive': True, 'output':'steps','stim_channel': 'STI 014',
               'min_duration':0.002,'shortest_event': 2,'mask': 0}
              }

         return:
                pandas data-frame with epoch event structure for stimulus or response channel
                    id       : event id
                    offset   : np array with TSL event code offset
                    onset    : np array with TSL event code onset
                    counts   : number of events
                    bads     : np.array with index of bad events
                    #=> RESPONSE MATCHING
                    #rt_type     : NAN => np array with values  MISSED=0 ,TOEARLY=1,WRONG=2,HIT=3
                    #rt      : NAN => np array with reaction time [TSL]
                    #rt_onset: NAN => np array with response onset [TSL]
                    #rt_id       : NAN => np array with response key / id

                dict() with event structure for stimulus or response channel
                sfreq    : sampling frequency  => raw.info['sfreq']
                duration : {mean,min,max}  in TSL
                system_delay_is_applied : True/False
                 --> if true <system_delay_ms> converted to TSLs and added to the TSLs in onset,offset
                (TSL => timeslices , your samples)
        """
        if raw is None:
            print "ERROR in  <get_event_structure: No raw obj \n"
            return None
    #---
        import pandas as pd
        df = pd.DataFrame(columns=self.data_frame_stimulus_cols)

        #---
        events = param['events'].copy()
        events['output'] = 'step'
        ev = mne.find_events(raw, **events)  #-- return int64

        #--- apply and mask e.g. 255 get the first 8 bits in Trigger channel
        if param['and_mask']:
            ev[:, 1:] = np.bitwise_and(ev[:, 1:], param['and_mask'])
            ev[:, 2:] = np.bitwise_and(ev[:, 2:], param['and_mask'])

    #--- search and return only events with event_id in event_id-array
    #--- shape =>(trials,3)  => [trial idx ,tsl-onset/ tsl-offset,event id]
    #--- split this in onset offset

        ev_onset = np.squeeze(ev[np.where(ev[:, 2]), :])  # > 0
        ev_offset = np.squeeze(ev[np.where(ev[:, 1]), :])

        if param['event_id']:
            ev_id = jumeg_base.str_range_to_numpy(param['event_id'],
                                                  exclude_zero=True)

            #ev_onset  = np.squeeze( ev[np.where( np.in1d( ev[:,2],ev_id ) ), :])
            #ev_offset = np.squeeze( ev[np.where( np.in1d( ev[:,1],ev_id ) ), :])

            ev_id_idx = np.squeeze(np.where(np.in1d(ev_onset[:, 2], ev_id)))

            ev_onset = ev_onset[ev_id_idx, :]
            ev_offset = ev_offset[ev_id_idx, :]

        if (ev_onset.size == 0):
            return df

    #--- apply system delay if is defined e.g. auditory take`s 20ms to subjects ears
        if param['system_delay_ms']:
            system_delay_tsl = raw.time_as_index(param['system_delay_ms'] /
                                                 1000)  # calc in sec
            ev_onset[:, 0] += system_delay_tsl
            ev_offset[:, 0] += system_delay_tsl
            system_delay_is_applied = True
        else:
            system_delay_is_applied = False

    #-- avoid invalid index/dimension error if last offset is none
        div = ev_offset[:, 0] - ev_onset[:ev_offset[:, 0].size, 0]
        df['id'] = ev_onset[:, 2]
        df['onset'] = ev_onset[:, 0]
        df['offset'] = np.zeros(ev_onset[:, 0].size, dtype=np.long)
        df['offset'][:ev_offset[:, 0].size] = ev_offset[:, 0]
        return df, dict({
            'sfreq': raw.info['sfreq'],
            'duration': {
                'mean': np.rint(div.mean()),
                'min': div.min(),
                'max': div.max()
            },
            'system_delay_is_applied': system_delay_is_applied
        })
Пример #2
0
    def events_response_matching(self,
                                 raw,
                                 stim_df=None,
                                 resp_df=None,
                                 **param):
        """
        matching correct responses with respect to <stimulus channel> <output type> (onset,offset)
        input:
                stim_df = <stimulus channel data frame>
                res_df  = <response channel data frame>
                param :  parameter dict
                   e.g.:{ 'response':{'counts':1,'window':[0,0.5],'event_id':2,'include_early_ids':[1,4],'events':{'output':'onset'} },
                         'stimulus':{'events':{'output'.'onset'}} }
        return:
                <stimulus data frame>  pandas DataFrame obj
                with added cols
                rt_type       : response type MISSED,EARLY,WRONG,HIT
                rt        : response time as tsl (RT)
                rt_id         : event id button press code
                rt_onset      : response onset  [tsl]
                rt_offset     : response offset [tsl]
                rt_index      : index in response onset / offset
                rt_counts     : number of responses in <response time window>
                bads          : flag for bad epochs; e.g. later use in combination with ecg/eog events
        """
        #--- ck errors
        err_msg = None

        if raw is None:
            err_msg = "ERROR in <apply_response_matching> : no raw obj \n"
        if (stim_df is None):
            err_msg += "\nERROR no Stimulus-Data-Frame obj. provided\n"
        if (resp_df is None):
            err_msg += "\nERROR no Response-Data-Frame obj. provided\n"
        if (param is None):
            err_msg += "\nERROR no Parameter obj. provided\n"
    #--- ck RT window range
        if (param['response']['window'][0] >= param['response']['window'][1]):
            err_msg += "ERROR in parameter response windows\n"

        if err_msg:
            print "ERROR in <apply_response_matching>\n" + err_msg + "\n\n"
            return None

    #--- extend stimulus data frame
        for x in self.data_frame_response_cols:
            stim_df[x] = 0  #np.NaN

    #--- convert rt window [ms] into tsl
        (r_window_tsl_start,
         r_window_tsl_end) = raw.time_as_index(param['response']['window'])

        #--- get respose code -> event_id [int or string] as np array
        r_event_id = jumeg_base.str_range_to_numpy(
            param['response']['event_id'])

        #--- ck if any toearly-id is defined, returns None if not
        r_event_id_toearly = jumeg_base.str_range_to_numpy(
            param['response']['include_early_ids'])

        #--- get output type: onset or offset
        stim_output_type = param['stimulus']['events']['output']
        resp_output_type = param['response']['events']['output']

        #--- loop for all stim events
        ridx = 0
        #--- get rt important part of respose df
        RESP_TSLs = resp_df[resp_output_type]

        for idx in stim_df.index:
            st_tsl_onset = stim_df[stim_output_type][idx]
            st_window_tsl0 = stim_df[stim_output_type][idx] + r_window_tsl_start
            st_window_tsl1 = stim_df[stim_output_type][idx] + r_window_tsl_end
            # st_id          = stim_df['id'][idx]

            #--- check for to TOEARLY responses
            toearly_tsl0 = st_tsl_onset
            toearly_tsl1 = st_window_tsl0
            #--- look for part of response dataframe ...
            res_df_early = resp_df[(toearly_tsl0 <= RESP_TSLs)
                                   & (RESP_TSLs < toearly_tsl1)]
            if res_df_early.index.size > 0:
                if not res_df_early.isin(r_event_id_toearly).all:
                    ridx = res_df_early.index[0]
                    stim_df.rt_counts[idx] = res_df_in.index.size
                    stim_df.rt_onset[idx] = resp_df.onset[ridx]
                    stim_df.rt_offset[idx] = resp_df.offset[ridx]
                    stim_df.rt_id[idx] = resp_df.id[ridx]
                    stim_df.rt_index[idx] = ridx
                    stim_df.rt_type[idx] = self.idx_toearly
                    continue

        #--- find index of responses from window-start till end of res_event_type array [e.g. onset / offset]
        # res_df_in = resp_df[ ( st_window_tsl0 <= RESP_TSLs ) & ( RESP_TSLs <= st_window_tsl1) ]
            resp_df_in_idx = resp_df[(st_window_tsl0 <= RESP_TSLs)
                                     & (RESP_TSLs <= st_window_tsl1)].index

            #--- MISSED response
            if not np.any(resp_df_in_idx):
                continue

        #--- WRONG or HIT;
        # if res_df_in.index.size > 0 :
        #    ridx = res_df_in.index[0]
            if resp_df_in_idx.size > 0:
                ridx = resp_df_in_idx[0]
                stim_df.rt_counts[idx] = resp_df_in_idx.size
                stim_df.rt_onset[idx] = resp_df.onset[ridx]
                stim_df.rt_offset[idx] = resp_df.offset[ridx]
                stim_df.rt_type[idx] = self.idx_wrong
                stim_df.rt_id[idx] = resp_df.id[ridx]
                #stim_df.rt_id[idx]     = resp_df.id[resp_df_in_idx].max()

                #stim_df.rt_id[idx]     = np.bitwise_and(resp_df.id[resp_df_in_idx], 72).max()
                stim_df.rt_index[idx] = ridx

                #--- HIT; ck number of responses; ck pressed buttons; wrong if more than count
                if (stim_df.rt_counts[idx] <= param['response']['counts']):
                    #if np.all( res_df_in.id.isin( r_event_id ) ) :
                    if np.all(resp_df.id[resp_df_in_idx].isin(r_event_id)):
                        stim_df.rt_type[idx] = self.idx_hit

            # if (stim_df.rt_id[idx] <1) and(stim_df.rt_type[idx]  == self.idx_wrong):
            #      print"!!ERROR"
            #      print resp_df_in_idx
            #      print resp_df.onset[resp_df_in_idx]
            #      print resp_df.id[resp_df_in_idx]
            #      assert "erroe rt"
#--- MISSED response
            else:
                continue

    #---  calc reaction time (rt in tsl)
        if stim_output_type == 'offset':
            sto = stim_df.offset
        else:
            sto = stim_df.onset
        if resp_output_type == 'offset':
            rto = stim_df.rt_offset
        else:
            rto = stim_df.rt_onset

        stim_df.rt = rto - sto
        stim_df.rt[(stim_df.rt_type == self.idx_missed)] = 0
        #---
        if self.verbose:
            for kidx in range(len(self.rt_type_list)):
                print "\n\n---> Stimulus DataFrame Type: " + self.rt_type_list[
                    kidx]
                ddf = stim_df[stim_df.rt_type == kidx]
                if ddf.index.size > 0:
                    print ddf.describe()
                else:
                    print "---> EMPTY"
                print "---------------------------"
            print "\n\n"

        #import sys
        #char = sys.stdin.read(1)
        return stim_df
Пример #3
0
    def events_find_events(self,raw,**param):
        """
        some how calls <mne.find_events()>
        input:
             raw obj,
             e.g. parameters:
              {'event_id': 40, 'and_mask': 255,
               'events': {'consecutive': True, 'output':'steps','stim_channel': 'STI 014',
               'min_duration':0.002,'shortest_event': 2,'mask': 0}
              }

         return:
                pandas data-frame with epoch event structure for stimulus or response channel
                    id       : event id
                    offset   : np array with TSL event code offset
                    onset    : np array with TSL event code onset
                    counts   : number of events
                    bads     : np.array with index of bad events
                    #=> RESPONSE MATCHING
                    #rt_type     : NAN => np array with values  MISSED=0 ,TOEARLY=1,WRONG=2,HIT=3
                    #rt      : NAN => np array with reaction time [TSL]
                    #rt_onset: NAN => np array with response onset [TSL]
                    #rt_id       : NAN => np array with response key / id

                dict() with event structure for stimulus or response channel
                sfreq    : sampling frequency  => raw.info['sfreq']
                duration : {mean,min,max}  in TSL
                system_delay_is_applied : True/False
                 --> if true <system_delay_ms> converted to TSLs and added to the TSLs in onset,offset
                (TSL => timeslices , your samples)
        """
        if raw is None:
           print "ERROR in  <get_event_structure: No raw obj \n"
           return None
       #---
        import pandas as pd
        df = pd.DataFrame(columns = self.data_frame_stimulus_cols)

       #---
        events           = param['events'].copy()
        events['output'] = 'step'
        ev               = mne.find_events(raw, **events)

       #--- apply and mask e.g. 255 get the first 8 bits in Trigger channel
        if param['and_mask']:
           ev[:, 1:] = np.bitwise_and(ev[:, 1:], param['and_mask'])
           ev[:, 2:] = np.bitwise_and(ev[:, 2:], param['and_mask'])

       #--- search and return only events with event_id in event_id-array
       #--- shape =>(trials,3)  => [trial idx ,tsl-onset/ tsl-offset,event id]
       #--- split this in onset offset
        if param['event_id']:
           ev_id     = jumeg_base.str_range_to_numpy(param['event_id'])
           ev_onset  = np.squeeze( ev[np.where( np.in1d( ev[:,2],ev_id ) ), :])
           ev_offset = np.squeeze( ev[np.where( np.in1d( ev[:,1],ev_id ) ), :])

       #--- get all ids e.g. response for later response matching
        else:
           ev_onset  = ev[0::2,]
           ev_offset = ev[1::2,]

        if ( ev_onset.size == 0 ):
           return df

       #--- apply system delay if is defined e.g. auditory take`s 20ms to subjects ears
        if param['system_delay_ms']:
           system_delay_tsl = raw.time_as_index( param['system_delay_ms']/1000 ) # calc in sec
           ev_onset[:, 0] += system_delay_tsl
           ev_offset[:, 0]+= system_delay_tsl
           system_delay_is_applied = True
        else:
           system_delay_is_applied = False

        div          = ev_offset[:,0] - ev_onset[:,0]
        df['id']     = ev_onset[:,2]
        df['onset']  = ev_onset[:,0]
        df['offset'] = ev_offset[:,0]
        return df,dict( {
                         'sfreq'        : raw.info['sfreq'],
                         'duration'     :{'mean':np.rint(div.mean()),'min':div.min(),'max':div.max()},
                         'system_delay_is_applied' : system_delay_is_applied
                         } )
Пример #4
0
    def events_response_matching(self,raw,stim_df=None,resp_df=None, **param ):
        """
        matching correct responses with respect to <stimulus channel> <output type> (onset,offset)
        input:
                stim_df = <stimulus channel data frame>
                res_df  = <response channel data frame>
                param :  parameter dict
                   e.g.:{ 'response':{'counts':1,'window':[0,0.5],'event_id':2,'include_early_ids':[1,4],'events':{'output':'onset'} },
                         'stimulus':{'events':{'output'.'onset'}} }
        return:
                <stimulus data frame>  pandas DataFrame obj
                with added cols
                rt_type       : response type MISSED,EARLY,WRONG,HIT
                rt        : response time as tsl (RT)
                rt_id         : event id button press code
                rt_onset      : response onset  [tsl]
                rt_offset     : response offset [tsl]
                rt_index      : index in response onset / offset
                rt_counts     : number of responses in <response time window>
                bads          : flag for bad epochs; e.g. later use in combination with ecg/eog events
        """
      #--- ck errors
        err_msg = None

        if raw is None:
           err_msg = "ERROR in <apply_response_matching> : no raw obj \n"
        if (stim_df is None):
           err_msg +="\nERROR no Stimulus-Data-Frame obj. provided\n"
        if (resp_df is None):
           err_msg +="\nERROR no Response-Data-Frame obj. provided\n"
        if (param is None):
           err_msg +="\nERROR no Parameter obj. provided\n"
       #--- ck RT window range
        if ( param['response']['window'][0] >= param['response']['window'][1] ):
            err_msg += "ERROR in parameter response windows\n"

        if err_msg:
           print "ERROR in <apply_response_matching>\n" + err_msg +"\n\n"
           return None

       #--- extend stimulus data frame
        for x in self.data_frame_response_cols :
            stim_df[x]= 0 #np.NaN

       #--- convert rt window [ms] into tsl
        (r_window_tsl_start, r_window_tsl_end ) = raw.time_as_index( param['response']['window'] );

       #--- get respose code -> event_id [int or string] as np array
        r_event_id = jumeg_base.str_range_to_numpy( param['response']['event_id'] )

       #--- ck if any toearly-id is defined, returns None if not
        r_event_id_toearly = jumeg_base.str_range_to_numpy( param['response']['include_early_ids'] )

       #--- get output type: onset or offset
        stim_output_type = param['stimulus']['events']['output']
        resp_output_type = param['response']['events']['output']

       #--- loop for all stim events
        ridx = 0
       #--- get rt important part of respose df
        RESP_TSLs = resp_df[resp_output_type]

        for idx in stim_df.index :
            st_tsl_onset   = stim_df[stim_output_type][idx]
            st_window_tsl0 = stim_df[stim_output_type][idx] + r_window_tsl_start
            st_window_tsl1 = stim_df[stim_output_type][idx] + r_window_tsl_end
            st_id          = stim_df['id'][idx]

          #--- check for to TOEARLY responses
            toearly_tsl0 = st_tsl_onset
            toearly_tsl1 = st_window_tsl0
          #--- look for part of response dataframe ...
            res_df_early = resp_df[(toearly_tsl0 <= RESP_TSLs ) & ( RESP_TSLs < toearly_tsl1 )]
            if res_df_early.index.size > 0 :
               if not res_df_early.isin( r_event_id_toearly ).all :
                      ridx                   = res_df_early.index[0]
                      stim_df.rt_counts[idx] = res_df_in.index.size
                      stim_df.rt_onset[idx]  = resp_df.onset[ridx]
                      stim_df.rt_offset[idx] = resp_df.offset[ridx]
                      stim_df.rt_id[idx]     = resp_df.id[ridx]
                      stim_df.rt_index[idx]  = ridx
                      stim_df.rt_type[idx]   = self.idx_toearly
                      continue

          #--- find index of responses from window-start till end of res_event_type array [e.g. onset / offset]
            res_df_in = resp_df[ ( st_window_tsl0 <= RESP_TSLs ) & ( RESP_TSLs <= st_window_tsl1) ]

          #--- MISSED response
            if res_df_in.empty : continue

          #--- WRONG or HIT;
            if res_df_in.index.size > 0 :
               ridx = res_df_in.index[0]
               stim_df.rt_counts[idx] = res_df_in.index.size
               stim_df.rt_onset[idx]  = resp_df.onset[ridx]
               stim_df.rt_offset[idx] = resp_df.offset[ridx]
               stim_df.rt_type[idx]   = self.idx_wrong
               stim_df.rt_id[idx]     = resp_df.id[ridx]
               stim_df.rt_index[idx]  = ridx
          #--- HIT; ck number of responses; ck pressed buttons; wrong if more than count
               if (  stim_df.rt_counts[idx] <= param['response']['counts'] ):
                   if res_df_in.id.isin( r_event_id ).all :
                      stim_df.rt_type[idx] = self.idx_hit


      #---  calc reaction time (rt in tsl)
        if stim_output_type == 'offset' :
           sto = stim_df.offset
        else:
           sto = stim_df.onset
        if resp_output_type == 'offset' :
           rto = stim_df.rt_offset
        else:
           rto = stim_df.rt_onset

        stim_df.rt = rto - sto

       #---
        if self.verbose:
           for kidx in range( len( self.rt_type_list ) ) :
               print "\n\n---> Stimulus DataFrame Type: " + self.rt_type_list[kidx]
               ddf = stim_df[ stim_df.rt_type == kidx ]
               if ddf.index.size > 0 :
                  print ddf.describe()
               else :
                  print "---> EMPTY"
               print"---------------------------"
           print "\n\n"

        #import sys
        #char = sys.stdin.read(1)
        return stim_df
Пример #5
0
    def events_response_matching(self,raw,stim_df=None,resp_df=None, **param ):
        """
        matching correct responses with respect to <stimulus channel> <output type> (onset,offset)
        input:
                stim_df = <stimulus channel data frame>
                res_df  = <response channel data frame>
                param :  parameter dict
                   e.g.:{ 'response':{'counts':1,'window':[0,0.5],'event_id':2,'include_early_ids':[1,4],'events':{'output':'onset'} },
                         'stimulus':{'events':{'output'.'onset'}} }
        return:
                <stimulus data frame>  pandas DataFrame obj
                with added cols
                rt_type       : response type MISSED,EARLY,WRONG,HIT
                rt        : response time as tsl (RT)
                rt_id         : event id button press code
                rt_onset      : response onset  [tsl]
                rt_offset     : response offset [tsl]
                rt_index      : index in response onset / offset
                rt_counts     : number of responses in <response time window>
                bads          : flag for bad epochs; e.g. later use in combination with ecg/eog events
        """
      #--- ck errors
        err_msg = None

        if raw is None:
           err_msg = "ERROR in <apply_response_matching> : no raw obj \n"
        if (stim_df is None):
           err_msg +="\nERROR no Stimulus-Data-Frame obj. provided\n"
        if (resp_df is None):
           err_msg +="\nERROR no Response-Data-Frame obj. provided\n"
        if (param is None):
           err_msg +="\nERROR no Parameter obj. provided\n"
       #--- ck RT window range
        if ( param['response']['window'][0] >= param['response']['window'][1] ):
            err_msg += "ERROR in parameter response windows\n"

        if err_msg:
           print "ERROR in <apply_response_matching>\n" + err_msg +"\n\n"
           return None

       #--- extend stimulus data frame
        for x in self.data_frame_response_cols :
            stim_df[x]= 0 #np.NaN

       #--- convert rt window [ms] into tsl
        (r_window_tsl_start, r_window_tsl_end ) = raw.time_as_index( param['response']['window'] );

       #--- get respose code -> event_id [int or string] as np array
        r_event_id = jumeg_base.str_range_to_numpy( param['response']['event_id'] )

       #--- ck if any toearly-id is defined, returns None if not
        r_event_id_toearly = jumeg_base.str_range_to_numpy( param['response']['include_early_ids'] )

       #--- get output type: onset or offset
        stim_output_type = param['stimulus']['events']['output']
        resp_output_type = param['response']['events']['output']

       #--- loop for all stim events
        ridx = 0
       #--- get rt important part of respose df
        RESP_TSLs = resp_df[resp_output_type]

        for idx in stim_df.index :
            st_tsl_onset   = stim_df[stim_output_type][idx]
            st_window_tsl0 = stim_df[stim_output_type][idx] + r_window_tsl_start
            st_window_tsl1 = stim_df[stim_output_type][idx] + r_window_tsl_end
Пример #6
0
=======
        ev               = mne.find_events(raw, **events) #-- return int64
       
>>>>>>> fb_devel_03082015
       #--- apply and mask e.g. 255 get the first 8 bits in Trigger channel
        if param['and_mask']:
           ev[:, 1:] = np.bitwise_and(ev[:, 1:], param['and_mask'])
           ev[:, 2:] = np.bitwise_and(ev[:, 2:], param['and_mask'])

       #--- search and return only events with event_id in event_id-array
       #--- shape =>(trials,3)  => [trial idx ,tsl-onset/ tsl-offset,event id]
       #--- split this in onset offset
<<<<<<< HEAD
        if param['event_id']:
           ev_id     = jumeg_base.str_range_to_numpy(param['event_id'])
           ev_onset  = np.squeeze( ev[np.where( np.in1d( ev[:,2],ev_id ) ), :])
           ev_offset = np.squeeze( ev[np.where( np.in1d( ev[:,1],ev_id ) ), :])

       #--- get all ids e.g. response for later response matching
        else:
           ev_onset  = ev[0::2,]
           ev_offset = ev[1::2,]
=======
          
        ev_onset  = np.squeeze( ev[np.where( ev[:,2] ),:])  # > 0
        ev_offset = np.squeeze( ev[np.where( ev[:,1] ),:])

        if param['event_id']:
           ev_id     = jumeg_base.str_range_to_numpy(param['event_id'],exclude_zero=True)