def rereference(raw, ref_new, ref_old=None):
    """
    Reference to new channels. raw object is modified in-place for efficiency.

    raw: mne.io.RawArray

    ref_new: None | list of str (RawArray) | list of int (numpy array)
        Channel(s) to re-reference, e.g. M1, M2.
        Average of these channel values are substracted from all channel values.

    ref_old: None | str
        Channel to recover, assuming this channel was originally used as a reference.
    """

    # Re-reference and recover the original reference channel values if possible
    if type(raw) == np.ndarray:
        if raw_ch_old is not None:
            logger.error('Recovering original reference channel is not yet supported for numpy arrays.')
            raise NotImplementedError
        if type(raw_ch_new[0]) is not int:
            logger.error('Channels must be integer values for numpy arrays')
            raise ValueError
        raw -= np.mean(raw[ref_new], axis=0)
    else:
        if ref_old is not None:
            # Add a blank (zero-valued) channel
            mne.io.add_reference_channels(raw, ref_old, copy=False)
        # Re-reference
        mne.io.set_eeg_reference(raw, ref_new, copy=False)

    return True
Esempio n. 2
0
def get_decoder_info(classifier):
    """
    Get the classifier information from a .pkl file.

    Parameters
    ----------
    classifier : str
        The (absolute) path to the classifier file (.pkl)

    Returns
    -------
    dict : Classifier info
    """

    with open(classifier, 'rb') as f:
        model = pickle.load(f)
    if model is None:
        logger.error('>> Error loading %s' % model)
        raise ValueError

    cls = model['cls']
    psde = model['psde']
    labels = list(cls.classes_)
    w_seconds = model['w_seconds']
    w_frames = model['w_frames']
    wstep = model['wstep']
    sfreq = model['sfreq']
    psd_temp = psde.transform(np.zeros((1, len(model['picks']), w_frames)))
    psd_shape = psd_temp.shape
    psd_size = psd_temp.size

    info = dict(labels=labels, cls=cls, psde=psde, w_seconds=w_seconds, w_frames=w_frames,\
                wstep=wstep, sfreq=sfreq, psd_shape=psd_shape, psd_size=psd_size)
    return info
Esempio n. 3
0
def check_config(cfg):
    """
    Ensure that the config file contains the parameters
    """
    critical_vars = {
        'COMMON': [
            'TRIGGER_DEVICE', 'TRIGGER_FILE', 'SCREEN_SIZE', 'START_VOICE',
            'END_VOICE'
        ],
    }
    optional_vars = {
        'GLOBAL_TIME': 2 * 60,
        'SCREEN_POS': (0, 0),
        'GLASS_USE': False,
    }

    for key in critical_vars['COMMON']:
        if not hasattr(cfg, key):
            logger.error('%s is a required parameter' % key)
            raise RuntimeError

    for key in optional_vars:
        if not hasattr(cfg, key):
            setattr(cfg, key, optional_vars[key])
            logger.warning('Setting undefined parameter %s=%s' %
                           (key, getattr(cfg, key)))
Esempio n. 4
0
    def move(self,
             dir,
             dx,
             overlay=False,
             barcolor=None,
             caption='',
             caption_color='W'):
        if barcolor is None:
            if dx == self.xl2:
                c = 'G'
            else:
                c = 'R'
        else:
            c = barcolor

        self.glass.fullbar_color(c)
        color = self.color[c]

        if dir == 'L':
            if self.pc_feedback:
                self.img = self.left_images[dx]
            if self.glass_feedback:
                self.glass.move_bar(dir, dx, overlay)
        elif dir == 'R':
            if self.pc_feedback:
                self.img = self.right_images[dx]
            if self.glass_feedback:
                self.glass.move_bar(dir, dx, overlay)
        else:
            logger.error('Unknown direction %s' % dir)
        self.put_text(caption, caption_color)
        self.update()
Esempio n. 5
0
def any2fif(filename, interactive=False, outdir=None, channel_file=None):
    """
    Generic file format converter
    """
    p = qc.parse_path(filename)
    if outdir is not None:
        qc.make_dirs(outdir)

    if p.ext == 'pcl':
        eve_file = '%s/%s.txt' % (p.dir, p.name.replace('raw', 'eve'))
        if os.path.exists(eve_file):
            logger.info('Adding events from %s' % eve_file)
        else:
            eve_file = None
        pcl2fif(filename,
                interactive=interactive,
                outdir=outdir,
                external_event=eve_file)
    elif p.ext == 'eeg':
        eeg2fif(filename, interactive=interactive, outdir=outdir)
    elif p.ext in ['edf', 'bdf']:
        bdf2fif(filename, interactive=interactive, outdir=outdir)
    elif p.ext == 'gdf':
        gdf2fif(filename,
                interactive=interactive,
                outdir=outdir,
                channel_file=channel_file)
    elif p.ext == 'xdf':
        xdf2fif(filename, interactive=interactive, outdir=outdir)
    else:  # unknown format
        logger.error(
            'Ignored unrecognized file extension %s. It should be [.pcl | .eeg | .gdf | .bdf]'
            % p.ext)
Esempio n. 6
0
def _check_cfg_selected(cfg, optional_vars, select):
    """
    Used in case of dict attributes containing subparams
    Check that the selected cfg params is valid and that its
    subparameters are defined.

    Parameters
    ----------
    cfg : python.module
        The config module containing the parameters to check
    optional_vars :
        The optional parameters with predefined values for the param
    selected = the cfg parameter (type=dict) containing a key: selected
    """
    param = getattr(cfg, select)
    selected = param['selected']

    if selected not in param:
        logger.error('%s not defined in config.' % selected)
        raise RuntimeError
    for v, vv in optional_vars[selected].items():
        if v not in param[selected]:
            param[selected].update({v: vv})
            setattr(cfg, select, param)
            logger.warning(
                'Updating internal parameter for classifier %s: %s=%s' %
                (selected, v, vv))
Esempio n. 7
0
def get_timelags(epochs, wlen, wstep, downsample=1, picks=None):
    """
    (DEPRECATED FUNCTION)
    Get concatenated timelag features

    TODO: Unit test.

    Input
    =====
    epochs: input signals
    wlen: window length (# time points) in downsampled data
    wstep: window step in downsampled data
    downsample: downsample signal to be 1/downsample length
    picks: ignored for now

    Output
    ======
    X: [epochs] x [windows] x [channels*freqs]
    y: [epochs] x [labels]
    """
    '''
    wlen = int(wlen)
    wstep = int(wstep)
    downsample = int(downsample)
    X_data = None
    y_data = None
    labels = epochs.events[:, -1]  # every epoch must have event id
    epochs_data = epochs.get_data()
    n_channels = epochs_data.shape[1]
    # trim to the nearest divisible length
    epoch_ds_len = int(epochs_data.shape[2] / downsample)
    epoch_len = downsample * epoch_ds_len
    range_epochs = np.arange(epochs_data.shape[0])
    range_channels = np.arange(epochs_data.shape[1])
    range_windows = np.arange(epoch_ds_len - wlen, 0, -wstep)
    X_data = np.zeros((len(range_epochs), len(range_windows), wlen * n_channels))

    # for each epoch
    for ep in range_epochs:
        epoch = epochs_data[ep, :, :epoch_len]
        ds = qc.average_every_n(epoch.reshape(-1), downsample)  # flatten to 1-D, then downsample
        epoch_ds = ds.reshape(n_channels, -1)  # recover structure to channel x samples
        # for each window over all channels
        for i in range(len(range_windows)):
            w = range_windows[i]
            X = epoch_ds[:, w:w + wlen].reshape(1, -1)  # our feature vector
            X_data[ep, i, :] = X

        # fill labels
        y = np.empty((1, len(range_windows)))  # 1 x windows
        y.fill(labels[ep])
        if y_data is None:
            y_data = y
        else:
            y_data = np.concatenate((y_data, y), axis=0)

    return X_data, y_data
    '''
    logger.error('This function is deprecated.')
    raise NotImplementedError
def lsl_channel_list(inlet):
    """
    Reads XML description of LSL header and returns channel list

    Input:
        pylsl.StreamInlet object
    Returns:
        ch_list: [ name1, name2, ... ]
    """
    if not type(inlet) is pylsl.StreamInlet:
        logger.error('lsl_channel_list(): wrong input type %s' % type(inlet))
        raise TypeError
    root = ET.fromstring(inlet.info().as_xml())
    desc = root.find('desc')
    ch_list = []
    for ch in desc.find('channels').getchildren():
        ch_name = ch.find('label').text
        ch_list.append(ch_name)

    ''' This code may throw access violation error due to bug in pylsl.XMLElement
    # for some reason type(inlet) returns 'instance' type in Python 2.
    ch = inlet.info().desc().child('channels').first_child()
    ch_list = []
    for k in range(inlet.info().channel_count()):
        ch_name = ch.child_value('label')
        ch_list.append(ch_name)
        ch = ch.next_sibling()
    '''
    return ch_list
Esempio n. 9
0
 def get_index_max(seq):
     if type(seq) == list:
         return max(range(len(seq)), key=seq.__getitem__)
     elif type(seq) == dict:
         return max(seq, key=seq.__getitem__)
     else:
         logger.error('Unsupported input %s' % type(seq))
         return None
Esempio n. 10
0
 def check_connect(self):
     """
     Check connection and automatically connect if not connected
     """
     while not self.connected:
         logger.error('LSL server not connected yet. Trying to connect automatically.')
         self.connect()
         time.sleep(1)
Esempio n. 11
0
def fit_predict_thres(cls,
                      X_train,
                      Y_train,
                      X_test,
                      Y_test,
                      cnum,
                      label_list,
                      ignore_thres=None,
                      decision_thres=None):
    """
    Any likelihood lower than a threshold is not counted as classification score
    Confusion matrix, accuracy and F1 score (macro average) are computed.

    Params
    ======
    ignore_thres:
    if not None or larger than 0, likelihood values lower than ignore_thres will be ignored
    while computing confusion matrix.

    """
    timer = qc.Timer()
    cls.fit(X_train, Y_train)
    assert ignore_thres is None or ignore_thres >= 0
    if ignore_thres is None or ignore_thres == 0:
        Y_pred = cls.predict(X_test)
        score = skmetrics.accuracy_score(Y_test, Y_pred)
        cm = skmetrics.confusion_matrix(Y_test, Y_pred, label_list)
        f1 = skmetrics.f1_score(Y_test, Y_pred, average='macro')
    else:
        if decision_thres is not None:
            logger.error(
                'decision threshold and ignore_thres cannot be set at the same time.'
            )
            raise ValueError
        Y_pred = cls.predict_proba(X_test)
        Y_pred_labels = np.argmax(Y_pred, axis=1)
        Y_pred_maxes = np.array([x[i] for i, x in zip(Y_pred_labels, Y_pred)])
        Y_index_overthres = np.where(Y_pred_maxes >= ignore_thres)[0]
        Y_index_underthres = np.where(Y_pred_maxes < ignore_thres)[0]
        Y_pred_overthres = np.array(
            [cls.classes_[x] for x in Y_pred_labels[Y_index_overthres]])
        Y_pred_underthres = np.array(
            [cls.classes_[x] for x in Y_pred_labels[Y_index_underthres]])
        Y_pred_underthres_count = np.array(
            [np.count_nonzero(Y_pred_underthres == c) for c in label_list])
        Y_test_overthres = Y_test[Y_index_overthres]
        score = skmetrics.accuracy_score(Y_test_overthres, Y_pred_overthres)
        cm = skmetrics.confusion_matrix(Y_test_overthres, Y_pred_overthres,
                                        label_list)
        cm = np.concatenate((cm, Y_pred_underthres_count[:, np.newaxis]),
                            axis=1)
        f1 = skmetrics.f1_score(Y_test_overthres,
                                Y_pred_overthres,
                                average='macro')

    logger.info('Cross-validation %d (%.3f) - %.1f sec' %
                (cnum, score, timer.sec()))
    return score, cm, f1
Esempio n. 12
0
def run(cfg, state=mp.Value('i', 1), queue=None, logger=logger):
    '''
    Main function used to run the offline protocol.

    Parameters
    ----------
    cfg : python.module
        The loaded config module from the corresponding config_offline.py
    queue : mp.Queue
        If not None, redirect sys.stdout to GUI terminal
    logger : logging.logger
        The logger to use
    '''
    # Use to redirect sys.stdout to GUI terminal if GUI usage
    redirect_stdout_to_queue(logger, queue, 'INFO')

    # Wait the recording to start (GUI)
    while state.value == 2:  # 0: stop, 1:start, 2:wait
        pass

    # Protocol start if equals to 1
    if not state.value:
        sys.exit()

    # Load the mapping from int to string for triggers events
    cfg.tdef = TriggerDef(cfg.TRIGGER_FILE)

    # Refresh rate
    refresh_delay = 1.0 / cfg.REFRESH_RATE

    # Trigger
    trigger = Trigger(lpttype=cfg.TRIGGER_DEVICE, state=state)
    if trigger.init(50) == False:
        logger.error(
            '\n** Error connecting to the trigger device. Use a mock trigger instead?'
        )
        input('Press Ctrl+C to stop or Enter to continue.')
        trigger = Trigger(lpttype='FAKE')
        trigger.init(50)

    # timers
    timer_refresh = Timer()

    trial = 1
    num_trials = cfg.TRIALS_NB

    # start
    while trial <= num_trials:
        timer_refresh.sleep_atleast(refresh_delay)
        timer_refresh.reset()

        #-------------------------------------
        # ADD YOUR CODE HERE
        #-------------------------------------

    with state.get_lock():
        state.value = 0
Esempio n. 13
0
 def set_pin(self, pin):
     if self.lpttype == 'SOFTWARE':
         logger.error('set_pin() not supported for software trigger.')
         return False
     elif self.lpttype == 'FAKE':
         logger.info('FAKE trigger pin %s' % pin)
         return True
     else:
         self.set_data(2**(pin - 1))
Esempio n. 14
0
def balance_samples(X, Y, balance_type, verbose=False):
    if balance_type == 'OVER':
        """
        Oversample from classes that lack samples
        """
        label_set = np.unique(Y)
        max_set = []
        X_balanced = np.array(X)
        Y_balanced = np.array(Y)

        # find a class with maximum number of samples
        for c in label_set:
            yl = np.where(Y == c)[0]
            if len(max_set) == 0 or len(yl) > max_set[1]:
                max_set = [c, len(yl)]
        for c in label_set:
            if c == max_set[0]: continue
            yl = np.where(Y == c)[0]
            extra_samples = max_set[1] - len(yl)
            extra_idx = np.random.choice(yl, extra_samples)
            X_balanced = np.append(X_balanced, X[extra_idx], axis=0)
            Y_balanced = np.append(Y_balanced, Y[extra_idx], axis=0)
    elif balance_type == 'UNDER':
        """
        Undersample from classes that are excessive
        """
        label_set = np.unique(Y)
        min_set = []

        # find a class with minimum number of samples
        for c in label_set:
            yl = np.where(Y == c)[0]
            if len(min_set) == 0 or len(yl) < min_set[1]:
                min_set = [c, len(yl)]
        yl = np.where(Y == min_set[0])[0]
        X_balanced = np.array(X[yl])
        Y_balanced = np.array(Y[yl])
        for c in label_set:
            if c == min_set[0]: continue
            yl = np.where(Y == c)[0]
            reduced_idx = np.random.choice(yl, min_set[1])
            X_balanced = np.append(X_balanced, X[reduced_idx], axis=0)
            Y_balanced = np.append(Y_balanced, Y[reduced_idx], axis=0)
    elif balance_type is None or balance_type is False:
        return X, Y
    else:
        logger.error('Unknown balancing type %s' % balance_type)
        raise ValueError

    logger.info_green('\nNumber of samples after %ssampling' %
                      balance_type.lower())
    for c in label_set:
        logger.info(
            '%s: %d -> %d' %
            (c, len(np.where(Y == c)[0]), len(np.where(Y_balanced == c)[0])))

    return X_balanced, Y_balanced
Esempio n. 15
0
    def move(self,
             dir,
             dx,
             overlay=False,
             barcolor=None,
             caption='',
             caption_color='W'):
        if not overlay:
            self.draw_cue()

        if barcolor is None:
            if dx == self.xl2:
                c = 'G'
            else:
                c = 'R'
        else:
            c = barcolor

        self.glass.fullbar_color(c)
        color = self.color[c]

        if dir == 'L':
            if self.pc_feedback:
                cv2.rectangle(self.img, (self.xl1 - dx, self.yl1),
                              (self.xl1, self.yr1), color, -1)
            if self.glass_feedback:
                self.glass.move_bar(dir, dx, overlay)
        elif dir == 'U':
            if self.pc_feedback:
                cv2.rectangle(self.img, (self.xl1, self.yl1 - dx),
                              (self.xr1, self.yl1), color, -1)
            if self.glass_feedback:
                self.glass.move_bar(dir, dx, overlay)
        elif dir == 'R':
            if self.pc_feedback:
                cv2.rectangle(self.img, (self.xr1, self.yl1),
                              (self.xr1 + dx, self.yr1), color, -1)
            if self.glass_feedback:
                self.glass.move_bar(dir, dx, overlay)
        elif dir == 'D':
            if self.pc_feedback:
                cv2.rectangle(self.img, (self.xl1, self.yr1),
                              (self.xr1, self.yr1 + dx), color, -1)
            if self.glass_feedback:
                self.glass.move_bar(dir, dx, overlay)
        elif dir == 'B':
            if self.pc_feedback:
                cv2.rectangle(self.img, (self.xl1 - dx, self.yl1),
                              (self.xl1, self.yr1), color, -1)
                cv2.rectangle(self.img, (self.xr1, self.yl1),
                              (self.xr1 + dx, self.yr1), color, -1)
            if self.glass_feedback:
                self.glass.move_bar('S', dx, overlay)
        else:
            logger.error('Unknown direction %s' % dir)
        self.put_text(caption, caption_color)
Esempio n. 16
0
def get_index_max(seq):
    """
    Get the index of the maximum item in a list or dict
    """
    if type(seq) == list:
        return max(range(len(seq)), key=seq.__getitem__)
    elif type(seq) == dict:
        return max(seq, key=seq.__getitem__)
    else:
        logger.error('Unsupported input %s' % type(seq))
        return None
Esempio n. 17
0
    def move(self, dir, dx, overlay=False, barcolor=None, caption='', caption_color='W'):
        
        #if barcolor is None:
            #if dx == self.xl2:
                #c = 'G'
            #else:
                #c = 'R'
        #else:
            #c = barcolor

        #color = self.color[c]

        if dir == 'L':
            if self.pc_feedback:
                if barcolor is None:
                    color = ((dx/100) * self.color['B'][0], self.color['B'][1], self.color['B'][2])
                else:
                    color = self.color[barcolor]
                # color = ((dx/100) * self.color['B'][0], self.color['B'][1], self.color['B'][2])
                # color = ((dx/100) * color[0], color[1], color[2])
                cv2.circle(self.img, (self.cx, self.cy), int(self.cx/8) - int(self.outerRadiusThickness-2), color, -1)
                # self.draw_fixation_cross()
                if not overlay:
                    self.draw_cue(self.actual_cue)

        elif dir == 'R':
            if self.pc_feedback:
                if barcolor is None:
                    color = (self.color['R'][0], self.color['R'][1], (dx/100) * self.color['R'][2])
                else:
                    color = self.color[barcolor]                    
                # color = (color[0], color[1], (dx/100) * color[2])
                # color = (self.color['R'][0], self.color['R'][1], (dx/100) * self.color['R'][2])
                cv2.circle(self.img, (self.cx, self.cy), int(self.cx/8) - int(self.outerRadiusThickness-2), color, -1)
                # self.draw_fixation_cross()
                if not overlay:
                    self.draw_cue(self.actual_cue)
        
        #elif dir == 'U':
            #if self.pc_feedback:tas
                #color = (self.color['R'][0], self.color['R'][1], (dx/100) * self.color['R'][2])
                #cv2.circle(self.img, (self.cx, self.cy), int(self.cx/8), color, -1)
                #self.draw_fixation_cross()                
        
            
        #elif dir == 'D':
            #if self.pc_feedback:
                #color = (self.color['R'][0], self.color['R'][1], (dx/100) * self.color['R'][2])
                #cv2.circle(self.img, (self.cx, self.cy), int(self.cx/8), color, -1)
                #self.draw_fixation_cross()                
            
        else:
            logger.error('Unknown direction %s' % dir)
        self.put_text(caption, caption_color)
Esempio n. 18
0
def check_cfg_mandatory(cfg, critical_vars, key_var):
    """
    Check that the mandatory parameters are defined

    cfg = config module containing the parameters to check
    critical_vars = critival parameters needed for the protocol
    key_var = key to look at in critical_vars
    """
    for v in critical_vars[key_var]:
        if not hasattr(cfg, v):
            logger.error('%s not defined in config.' % v)
            raise RuntimeError
Esempio n. 19
0
    def reset(self):
        """
        Reset the classifier to its initial state.
        """
        # share numpy array self.psd between processes.
        # to compute the shared memory size, we need to create a temporary decoder object.
        if self.fake == True:
            psd_size = None
            psd_shape = None
            psd_ctypes = None
            self.psd = None
        else:
            info = get_decoder_info(self.classifier)
            psd_size = info['psd_size']
            psd_shape = info['psd_shape'][1:]  # we get only the last window
            psd_ctypes = sharedctypes.RawArray('d', np.zeros(psd_size))
            self.psd = np.frombuffer(psd_ctypes,
                                     dtype=np.float64,
                                     count=psd_size)

        self.probs = mp.Array('d', [1.0 / len(self.labels)] * len(self.labels))
        self.probs_smooth = mp.Array('d', [1.0 / len(self.labels)] *
                                     len(self.labels))
        self.pread = mp.Value('i', 1)
        self.t_problast = mp.Value('d', 0)
        self.return_psd = mp.Value('i', 0)
        self.procs = []
        mp.freeze_support()

        if self.parallel:
            logger.error(
                'Parallel decoding is under a rigorous test. Please do not use it for now.'
            )
            raise NotImplementedError
            num_strides = self.parallel['num_strides']
            period = self.parallel['period']
            self.running = [mp.Value('i', 0)] * num_strides
            if num_strides > 1:
                stride = period / num_strides
            else:
                stride = 0
            t_start = time.time()
            for i in range(num_strides):
                self.procs.append(mp.Process(target=self._daemon, args=\
                    [self.classifier, self.probs, self.probs_smooth, self.pread, self.t_problast,\
                     self.running[i], self.return_psd, psd_ctypes, self.psdlock,\
                     dict(t_start=(t_start+i*stride), period=period), self.label]))
        else:
            self.running = [mp.Value('i', 0)]
            self.procs = [mp.Process(target=self._daemon, args=\
                [self.classifier, self.probs, self.probs_smooth, self.pread, self.t_problast,\
                 self.running[0], self.return_psd, psd_ctypes, self.psdlock, None, self.label])]
Esempio n. 20
0
def make_dirs(dirname, delete=False):
    """
    Recusively create directories.
    if delete=true, directory will be deleted first if exists.
    """
    if os.path.exists(dirname) and delete == True:
        try:
            shutil.rmtree(dirname)
        except OSError:
            logger.error(
                'Directory was not completely removed. (Perhaps a Dropbox folder?). Continuing.'
            )
    if not os.path.exists(dirname):
        os.makedirs(dirname)
Esempio n. 21
0
def load_raw(rawfile, spfilter=None, spchannels=None, events_ext=None, multiplier=1, verbose='ERROR'):
    """
    Loads data from a fif-format file.
    You can convert non-fif files (.eeg, .bdf, .gdf, .pcl) to fif format.

    Parameters:
    rawfile: (absolute) data file path
    spfilter: 'car' | 'laplacian' | None
    spchannels: None | list (for CAR) | dict (for LAPLACIAN)
        'car': channel indices used for CAR filtering. If None, use all channels except
               the trigger channel (index 0).
        'laplacian': {channel:[neighbor1, neighbor2, ...], ...}
        *** Note ***
        Since neurodecode puts trigger channel as index 0, data channel starts from index 1.
    events_ext: Add externally recorded events.
                [ [sample_index1, 0, event_value1],... ]
    multiplier: Multiply all values except triggers (to convert unit).

    Returns:
    raw: mne.io.RawArray object. First channel (index 0) is always trigger channel.
    events: mne-compatible events numpy array object (N x [frame, 0, type])
    spfilter= {None | 'car' | 'laplacian'}

    """

    if not os.path.exists(rawfile):
        logger.error('File %s not found' % rawfile)
        raise IOError
    if not os.path.isfile(rawfile):
        logger.error('%s is not a file' % rawfile)
        raise IOError

    extension = qc.parse_path(rawfile).ext
    assert extension in ['fif', 'fiff'], 'only fif format is supported'
    raw = mne.io.Raw(rawfile, preload=True, verbose=verbose)
    if spfilter is not None or multiplier is not 1:
        preprocess(raw, spatial=spfilter, spatial_ch=spchannels, multiplier=multiplier)
    if events_ext is not None:
        events = mne.read_events(events_ext)
    else:
        tch = find_event_channel(raw)
        if tch is not None:
            events = mne.find_events(raw, stim_channel=raw.ch_names[tch], shortest_event=1, uint_cast=True, consecutive='increasing')
            # MNE's annoying hidden cockroach: first_samp
            events[:, 0] -= raw.first_samp
        else:
            events = np.array([], dtype=np.int64)

    return raw, events
Esempio n. 22
0
def convert2mat(filename, matfile):
    """
    Convert to mat using MATLAB BioSig sload().
    """
    basename = '.'.join(filename.split('.')[:-1])
    # extension= filename.split('.')[-1]
    matfile = basename + '.mat'
    if not os.path.exists(matfile):
        logger.info('Converting input to mat file')
        run = "[sig,header]=sload('%s'); save('%s.mat','sig','header');" % (
            filename, basename)
        qc.matlab(run)
        if not os.path.exists(matfile):
            logger.error('mat file convertion error.')
            sys.exit()
Esempio n. 23
0
 def set_data(self, value):
     if self.lpttype == 'SOFTWARE':
         logger.error('set_data() not supported for software trigger.')
         return False
     elif self.lpttype == 'FAKE':
         logger.info('FAKE trigger value %s' % value)
         return True
     else:
         if self.lpttype == 'USB2LPT':
             self.lpt.setdata(value)
         elif self.lpttype == 'DESKTOP':
             self.lpt.setdata(self.portaddr, value)
         elif self.lpttype == 'ARDUINO':
             self.ser.write(bytes([value]))
         else:
             raise RuntimeError('Wrong trigger device')
Esempio n. 24
0
 def start(self):
     """
     Start the daemon
     """
     if self.is_running() > 0:
         msg = 'Cannot start. Daemon already running. (PID' + ', '.join(
             ['%d' % proc.pid for proc in self.procs]) + ')'
         logger.error(msg)
         return
     for proc in self.procs:
         proc.start()
     if self.wait_init:
         for running in self.running:
             while running.value == 0:
                 time.sleep(0.001)
     logger.info(self.startmsg)
Esempio n. 25
0
def check_config(cfg):
    critical_vars = {
        'COMMON': [
            'TRIGGER_DEVICE', 'TRIGGER_FILE', 'SCREEN_SIZE', 'DIRECTIONS',
            'DIR_RANDOM', 'TRIALS_EACH'
        ],
        'TIMINGS': [
            'INIT', 'GAP', 'CUE', 'READY', 'READY_RANDOMIZE', 'DIR',
            'DIR_RANDOMIZE'
        ]
    }
    optional_vars = {
        'FEEDBACK_TYPE': 'BAR',
        'FEEDBACK_IMAGE_PATH': None,
        'SCREEN_POS': (0, 0),
        'DIR_RANDOM': True,
        'GLASS_USE': False,
        'TRIAL_PAUSE': False,
        'REFRESH_RATE': 30
    }

    for key in critical_vars['COMMON']:
        if not hasattr(cfg, key):
            raise RuntimeError('%s is a required parameter' % key)

    if not hasattr(cfg, 'TIMINGS'):
        logger.error('"TIMINGS" not defined in config.')
        raise RuntimeError
    for v in critical_vars['TIMINGS']:
        if v not in cfg.TIMINGS:
            logger.error('%s not defined in config.' % v)
            raise RuntimeError

    for key in optional_vars:
        if not hasattr(cfg, key):
            setattr(cfg, key, optional_vars[key])
            logger.warning('Setting undefined %s=%s' % (key, optional[key]))

    if getattr(cfg, 'TRIGGER_DEVICE') == None:
        logger.warning(
            'The trigger device is set to None! No events will be saved.')
        raise RuntimeError(
            'The trigger device is set to None! No events will be saved.')
Esempio n. 26
0
def bdf2fif(filename, interactive=False, outdir=None):
    """
    EDF or BioSemi BDF format
    """
    # convert to mat using MATLAB (MNE's edf reader has an offset bug)
    fdir, fname, fext = qc.parse_path_list(filename)
    if outdir is None:
        outdir = fdir
    elif outdir[-1] != '/':
        outdir += '/'

    fiffile = outdir + fname + '.fif'
    raw = mne.io.read_raw_edf(filename, preload=True)

    # process event channel
    if raw.info['chs'][-1]['ch_name'] != 'STI 014':
        logger.error(
            "The last channel (%s) doesn't seem to be an event channel. Entering debugging mode."
            % raw.info['chs'][-1]['ch_name'])
        pdb.set_trace()
    raw.info['chs'][-1]['ch_name'] = 'TRIGGER'
    events = mne.find_events(raw,
                             stim_channel='TRIGGER',
                             shortest_event=1,
                             uint_cast=True,
                             consecutive=True)
    events[:, 2] -= events[:, 1]  # set offset to 0
    events[:, 1] = 0
    # move the event channel to index 0 (for consistency)
    raw._data = np.concatenate(
        (raw._data[-1, :].reshape(1, -1), raw._data[:-1, :]))
    raw._data[0] *= 0  # init the event channel
    raw.info['chs'] = [raw.info['chs'][-1]] + raw.info['chs'][:-1]

    # add events
    raw.add_events(events, 'TRIGGER')

    # save and close
    raw.save(fiffile, verbose=False, overwrite=True, fmt='double')
    logger.info('Saved to %s' % fiffile)

    saveChannels2txt(outdir, ch_names)
Esempio n. 27
0
    def init(self, duration):
        if self.lpttype == 'SOFTWARE':
            logger.info('Ignoring delay parameter for software trigger.')
            return True
        elif self.lpttype == 'FAKE':
            return True
        else:
            self.delay = duration / 1000.0

            if self.lpttype in ['DESKTOP', 'USB2LPT']:
                if self.lpt.init() == -1:
                    logger.error(
                        'Connecting to LPT port failed. Check the driver status.'
                    )
                    self.lpt = None
                    return False

            self.action = False
            self.offtimer = threading.Timer(self.delay, self.signal_off)
            return True
Esempio n. 28
0
def check_config(cfg):
    """
    Ensure that the config file contains the parameters
    """
    critical_vars = {
        'COMMON': ['DATA_PATH'],
    }
    optional_vars = {
    }
    
    for key in critical_vars['COMMON']:
        if not hasattr(cfg, key):
            logger.error('%s is a required parameter' % key)
            raise RuntimeError
    
    for key in optional_vars:
        if not hasattr(cfg, key):
            setattr(cfg, key, optional_vars[key])
            logger.warning('Setting undefined parameter %s=%s' % (key, getattr(cfg, key)))
    
    return cfg
Esempio n. 29
0
    def print_c(msg, color=None, end='\n'):
        """
        Colored print using colorama.

        Fullset:
            https://pypi.python.org/pypi/colorama
            Fore: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
            Back: BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, RESET.
            Style: DIM, NORMAL, BRIGHT, RESET_ALL

        TODO:
            Make it using *args and **kwargs to support fully featured print().

        """
        if color is None:
            print(str(msg), end=end)
            return
        color = str(color)
        if len(color) != 1:
            raise ValueError(
                'Color parameter must be a single color code, not %s' %
                type(color))
        if color.upper() == 'B':
            c = colorama.Fore.BLUE
        elif color.upper() == 'R':
            c = colorama.Fore.RED
        elif color.upper() == 'G':
            c = colorama.Fore.GREEN
        elif color.upper() == 'Y':
            c = colorama.Fore.YELLOW
        elif color.upper() == 'W':
            c = colorama.Fore.WHITE
        elif color.upper() == 'C':
            c = colorama.Fore.CYAN
        else:
            logger.error('print_c(): Unknown color code %s' % color)
            raise ValueError
        print(colorama.Style.BRIGHT + c + str(msg) + colorama.Style.RESET_ALL,
              end=end)
Esempio n. 30
0
def check_config(cfg):
    """
    Ensure that the config file contains the parameters
    """
    critical_vars = {'COMMON': ['DATA_PATH']}

    optional_vars = {
        'AMP_NAME': None,
        'AMP_SERIAL': None,
        'GLOBAL_TIME': 1.0 * 60,
        'NJOBS': 1,
    }

    for key in critical_vars['COMMON']:
        if not hasattr(cfg, key):
            logger.error('%s is a required parameter' % key)
            raise RuntimeError

    for key in optional_vars:
        if not hasattr(cfg, key):
            setattr(cfg, key, optional_vars[key])
            logger.warning('Setting undefined parameter %s=%s' %
                           (key, getattr(cfg, key)))