示例#1
0
class BCISignal():
    def __init__(self, fs, bands, ch_names, states_labels, indexes):
        self.states_labels = states_labels
        self.bands = bands
        self.prefilter = FilterSequence([ButterFilter((0.5, 45), fs, len(ch_names))])
        self.csp_pools = [SpatialDecompositionPool(ch_names, fs, bands, 'csp', indexes) for _label in states_labels]
        self.csp_transformer = None
        self.var_detector = InstantaneousVarianceFilter(len(bands)*len(indexes)*len(states_labels), n_taps=fs//2)
        self.classifier = MLPClassifier(hidden_layer_sizes=(), early_stopping=True, verbose=True)
        #self.classifier = RandomForestClassifier(max_depth=3, min_samples_leaf=100)

    def fit(self, X, y=None):
        X = self.prefilter.apply(X)
        for csp_pool, label in zip(self.csp_pools, self.states_labels):
            csp_pool.fit(X, y == label)
        self.csp_transformer = FilterStack([pool.get_filter_stack() for pool in self.csp_pools])
        X = self.csp_transformer.apply(X)
        X = self.var_detector.apply(X)
        self.classifier.fit(X, y)
        print('Fit accuracy {}'.format(sum(self.classifier.predict(X) == y)/len(y)))

    def apply(self, chunk: np.ndarray):
        chunk = self.prefilter.apply(chunk)
        chunk = self.csp_transformer.apply(chunk)
        chunk = self.var_detector.apply(chunk)
        predicted_labels = self.classifier.predict(chunk)
        return predicted_labels
示例#2
0
class BCISignal1():
    def __init__(self, fs, bands, ch_names, states_labels, indexes):
        self.states_labels = states_labels
        self.bands = bands
        self.prefilter = FilterSequence([ButterFilter((0.5, 45), fs, len(ch_names))])
        self.csp_pools = [SpatialDecompositionPool(ch_names, fs, bands, 'csp', indexes) for _label in states_labels]
        self.csp_transformer = None
        self.var_detector = InstantaneousVarianceFilter(len(bands)*len(indexes)*len(states_labels), n_taps=fs//2)
        self.classifier = MLPClassifier(hidden_layer_sizes=(), early_stopping=True, verbose=True)
        #self.classifier = RandomForestClassifier(max_depth=3, min_samples_leaf=100)

    def fit(self, X, y=None):
        X = self.prefilter.apply(X)
        for csp_pool, label in zip(self.csp_pools, self.states_labels):
            csp_pool.fit(X, y == label)
        self.csp_transformer = FilterStack([pool.get_filter_stack() for pool in self.csp_pools])
        X = self.csp_transformer.apply(X)
        X = self.var_detector.apply(X)
        self.classifier.fit(X, y)
        print('Fit accuracy {}'.format(sum(self.classifier.predict(X) == y)/len(y)))

    def apply(self, chunk: np.ndarray):
        chunk = self.prefilter.apply(chunk)
        chunk = self.csp_transformer.apply(chunk)
        chunk = self.var_detector.apply(chunk)
        predicted_labels = self.classifier.predict(chunk)
        return predicted_labels
示例#3
0
 def __init__(self, fs, bands, ch_names, states_labels, indexes):
     self.states_labels = states_labels
     self.bands = bands
     self.prefilter = FilterSequence([ButterFilter((0.5, 45), fs, len(ch_names))])
     self.csp_pools = [SpatialDecompositionPool(ch_names, fs, bands, 'csp', indexes) for _label in states_labels]
     self.csp_transformer = None
     self.var_detector = InstantaneousVarianceFilter(len(bands)*len(indexes)*len(states_labels), n_taps=fs//2)
     self.classifier = MLPClassifier(hidden_layer_sizes=(), early_stopping=True, verbose=True)
示例#4
0
 def __init__(self, fs, bands, ch_names, states_labels, indexes):
     self.states_labels = states_labels
     self.bands = bands
     self.prefilter = FilterSequence([ButterFilter((0.5, 45), fs, len(ch_names))])
     self.csp_pools = [SpatialDecompositionPool(ch_names, fs, bands, 'csp', indexes) for _label in states_labels]
     self.csp_transformer = None
     self.var_detector = InstantaneousVarianceFilter(len(bands)*len(indexes)*len(states_labels), n_taps=fs//2)
     self.classifier = MLPClassifier(hidden_layer_sizes=(), early_stopping=True, verbose=True)
示例#5
0
    def __init__(self,
                 ind,
                 source_freq,
                 n_channels=50,
                 n_samples=1000,
                 bandpass_low=None,
                 bandpass_high=None,
                 spatial_filter=None,
                 scale=False,
                 name='Untitled',
                 disable_spectrum_evaluation=False,
                 smoothing_factor=0.1,
                 temporal_filter_type='fft',
                 envelop_detector_kwargs=None,
                 smoother_type='exp',
                 estimator_type='envdetector',
                 filter_order=2,
                 delay_ms=0):

        self.n_samples = int(n_samples)

        # bandpass
        self.bandpass = (bandpass_low if bandpass_low else 0,
                         bandpass_high if bandpass_high else source_freq)

        if estimator_type == 'envdetector':
            # setup smoother
            if smoother_type == 'exp':
                smoother = ExponentialSmoother(smoothing_factor)
            elif smoother_type == 'savgol':
                smoother = SGSmoother(151, 2)
            else:
                raise TypeError('Incorrect smoother type')
            # setup specific parameters of envelope detector
            if temporal_filter_type == 'fft':
                self.signal_estimator = FFTBandEnvelopeDetector(
                    self.bandpass, source_freq, smoother, self.n_samples)
            elif temporal_filter_type == 'complexdem':
                self.signal_estimator = ComplexDemodulationBandEnvelopeDetector(
                    self.bandpass, source_freq, smoother)
            elif temporal_filter_type == 'butter':
                self.signal_estimator = ButterBandEnvelopeDetector(
                    self.bandpass, source_freq, smoother, filter_order)
            elif temporal_filter_type == 'cfir':
                self.signal_estimator = CFIRBandEnvelopeDetector(
                    self.bandpass,
                    source_freq,
                    smoother,
                    n_taps=self.n_samples)
            else:
                raise TypeError('Incorrect envelope detector type')
        elif estimator_type == 'filter':
            self.signal_estimator = ScalarButterFilter(self.bandpass,
                                                       source_freq,
                                                       filter_order)
        elif estimator_type == 'identity':
            self.signal_estimator = IdentityFilter()
        else:
            raise TypeError('Incorrect estimator type')

        if delay_ms > 0:
            self.signal_estimator = FilterSequence([
                self.signal_estimator,
                DelayFilter(int(source_freq * delay_ms / 1000))
            ])

        # id
        self.ind = ind
        # signal name
        self.name = name

        # signal buffer
        self.buffer = np.zeros((self.n_samples, ))
        # signal statistics
        self.scaling_flag = scale
        self.mean = np.nan
        self.std = np.nan

        # rejections matrices list
        self.rejections = Rejections(n_channels)

        # spatial filter
        self.spatial_filter = np.zeros((n_channels, ))
        self.spatial_filter_topography = None
        if spatial_filter is None:
            self.spatial_filter[0] = 0
        else:
            shape = min(spatial_filter.shape[0], n_channels)
            self.spatial_filter[:shape] = spatial_filter[:shape]

        # spatial matrix
        self.spatial_matrix = self.spatial_filter.copy()

        # current sample
        self.previous_sample = 0
        self.current_chunk = None
        pass
示例#6
0
class DerivedSignal:
    @classmethod
    def from_params(cls,
                    ind,
                    fs,
                    n_channels,
                    channels,
                    params,
                    spatial_filter=None):
        if spatial_filter is None:
            spatial_filter = read_spatial_filter(params['SpatialFilterMatrix'],
                                                 fs, channels,
                                                 params['sROILabel'])
        return cls(
            ind=ind,
            bandpass_high=params['fBandpassHighHz'],
            bandpass_low=params['fBandpassLowHz'],
            name=params['sSignalName'],
            n_channels=n_channels,
            spatial_filter=spatial_filter,
            disable_spectrum_evaluation=params['bDisableSpectrumEvaluation'],
            n_samples=params['fFFTWindowSize'],
            smoothing_factor=params['fSmoothingFactor'],
            source_freq=fs,
            estimator_type=params['sTemporalType'],
            temporal_filter_type=params['sTemporalFilterType'],
            smoother_type=params['sTemporalSmootherType'],
            filter_order=params['fTemporalFilterButterOrder'],
            delay_ms=params['iDelayMs'])

    def __init__(self,
                 ind,
                 source_freq,
                 n_channels=50,
                 n_samples=1000,
                 bandpass_low=None,
                 bandpass_high=None,
                 spatial_filter=None,
                 scale=False,
                 name='Untitled',
                 disable_spectrum_evaluation=False,
                 smoothing_factor=0.1,
                 temporal_filter_type='fft',
                 envelop_detector_kwargs=None,
                 smoother_type='exp',
                 estimator_type='envdetector',
                 filter_order=2,
                 delay_ms=0):

        self.n_samples = int(n_samples)

        # bandpass
        self.bandpass = (bandpass_low if bandpass_low else 0,
                         bandpass_high if bandpass_high else source_freq)

        if estimator_type == 'envdetector':
            # setup smoother
            if smoother_type == 'exp':
                smoother = ExponentialSmoother(smoothing_factor)
            elif smoother_type == 'savgol':
                smoother = SGSmoother(151, 2)
            else:
                raise TypeError('Incorrect smoother type')
            # setup specific parameters of envelope detector
            if temporal_filter_type == 'fft':
                self.signal_estimator = FFTBandEnvelopeDetector(
                    self.bandpass, source_freq, smoother, self.n_samples)
            elif temporal_filter_type == 'complexdem':
                self.signal_estimator = ComplexDemodulationBandEnvelopeDetector(
                    self.bandpass, source_freq, smoother)
            elif temporal_filter_type == 'butter':
                self.signal_estimator = ButterBandEnvelopeDetector(
                    self.bandpass, source_freq, smoother, filter_order)
            elif temporal_filter_type == 'cfir':
                self.signal_estimator = CFIRBandEnvelopeDetector(
                    self.bandpass,
                    source_freq,
                    smoother,
                    n_taps=self.n_samples)
            else:
                raise TypeError('Incorrect envelope detector type')
        elif estimator_type == 'filter':
            self.signal_estimator = ScalarButterFilter(self.bandpass,
                                                       source_freq,
                                                       filter_order)
        elif estimator_type == 'identity':
            self.signal_estimator = IdentityFilter()
        else:
            raise TypeError('Incorrect estimator type')

        if delay_ms > 0:
            self.signal_estimator = FilterSequence([
                self.signal_estimator,
                DelayFilter(int(source_freq * delay_ms / 1000))
            ])

        # id
        self.ind = ind
        # signal name
        self.name = name

        # signal buffer
        self.buffer = np.zeros((self.n_samples, ))
        # signal statistics
        self.scaling_flag = scale
        self.mean = np.nan
        self.std = np.nan

        # rejections matrices list
        self.rejections = Rejections(n_channels)

        # spatial filter
        self.spatial_filter = np.zeros((n_channels, ))
        self.spatial_filter_topography = None
        if spatial_filter is None:
            self.spatial_filter[0] = 0
        else:
            shape = min(spatial_filter.shape[0], n_channels)
            self.spatial_filter[:shape] = spatial_filter[:shape]

        # spatial matrix
        self.spatial_matrix = self.spatial_filter.copy()

        # current sample
        self.previous_sample = 0
        self.current_chunk = None
        pass

    def spatial_filter_is_zeros(self):
        return (self.spatial_filter == 0).all()

    def update(self, chunk):
        filtered_chunk = np.dot(chunk, self.spatial_matrix)
        current_chunk = self.signal_estimator.apply(filtered_chunk)
        if self.scaling_flag and self.std > 0:
            current_chunk = (current_chunk - self.mean) / self.std
        self.current_chunk = current_chunk
        return current_chunk

    def update_statistics(self,
                          raw=None,
                          emulate=False,
                          signals_recorder=None,
                          stats_type='meanstd'):
        if raw is not None and emulate:
            signal_recordings = np.zeros_like(signals_recorder[:, self.ind])
            mean_chunk_size = 8
            for k in range(0, raw.shape[0] - mean_chunk_size, mean_chunk_size):
                chunk = raw[k:k + mean_chunk_size]
                self.update(chunk)
                signal_recordings[k:k + mean_chunk_size] = self.current_chunk
        else:
            signal_recordings = signals_recorder[:, self.ind]
        if stats_type == 'meanstd':
            self.mean = signal_recordings.mean()
            self.std = signal_recordings.std()
        elif stats_type == 'max':
            self.std = signal_recordings.max()
            self.std = 1 if self.std == 0 else self.std
            self.mean = 0
        self.enable_scaling()
        return (signal_recordings -
                self.mean) / (self.std if self.std > 0 else 1)

    def update_spatial_filter(self, spatial_filter=None, topography=None):
        if spatial_filter is not None:
            self.spatial_filter = np.array(spatial_filter)
        self.spatial_matrix = np.dot(self.rejections.get_prod(),
                                     self.spatial_filter)
        self.spatial_filter_topography = topography if topography is not None else self.spatial_filter_topography

    def update_rejections(self, rejections, append=False):
        self.rejections.update_list(rejections, append=append)
        self.update_spatial_filter()

    def update_ica_rejection(self, rejection=None):
        self.rejections.update_ica(rejection)
        self.update_spatial_filter()

    def update_bandpass(self, bandpass):
        self.bandpass = bandpass

    def drop_rejection(self, ind):
        self.rejections.drop(ind)
        self.update_spatial_filter()
        print(self.rejections)

    def enable_scaling(self):
        self.scaling_flag = True

    def descale_recording(self, data):
        return data * self.std + self.mean if self.scaling_flag else data

    def save_spatial_matrix(self, file_path, channels_labels=None):
        """
        Save full spatial matrix: R1*R2*...*Rk*S, where R1,..Rk - rejections matrices, S - spatial filter
        :return:
        """
        save_spatial_filter(file_path,
                            self.spatial_matrix,
                            channels_labels=channels_labels)
示例#7
0
文件: derived.py 项目: nikolaims/nfb
    def __init__(self, ind, source_freq, n_channels=50, n_samples=1000, bandpass_low=None, bandpass_high=None,
                 spatial_filter=None, scale=False, name='Untitled', disable_spectrum_evaluation=False,
                 smoothing_factor=0.1, temporal_filter_type='fft', envelop_detector_kwargs=None, smoother_type='exp',
                 estimator_type='envdetector', filter_order=2, delay_ms=0):

        self.n_samples = int(n_samples)

        # bandpass
        self.bandpass = (bandpass_low if bandpass_low else 0,
                         bandpass_high if bandpass_high else source_freq)

        if estimator_type == 'envdetector':
            # setup smoother
            if smoother_type == 'exp':
                smoother = ExponentialSmoother(smoothing_factor)
            elif smoother_type == 'savgol':
                smoother = SGSmoother(151, 2)
            else:
                raise TypeError('Incorrect smoother type')
            # setup specific parameters of envelope detector
            if temporal_filter_type == 'fft':
                self.signal_estimator = FFTBandEnvelopeDetector(self.bandpass, source_freq, smoother, self.n_samples)
            elif temporal_filter_type == 'complexdem':
                self.signal_estimator = ComplexDemodulationBandEnvelopeDetector(self.bandpass, source_freq, smoother)
            elif temporal_filter_type == 'butter':
                self.signal_estimator = ButterBandEnvelopeDetector(self.bandpass, source_freq, smoother, filter_order)
            elif temporal_filter_type == 'cfir':
                self.signal_estimator = CFIRBandEnvelopeDetector(self.bandpass, source_freq, smoother, n_taps=self.n_samples)
            else:
                raise TypeError('Incorrect envelope detector type')
        elif estimator_type == 'filter':
            self.signal_estimator = ScalarButterFilter(self.bandpass, source_freq, filter_order)
        elif estimator_type == 'identity':
            self.signal_estimator = IdentityFilter()
        else:
            raise TypeError('Incorrect estimator type')

        if delay_ms > 0:
            self.signal_estimator = FilterSequence([self.signal_estimator, DelayFilter(int(source_freq*delay_ms/1000))])

        # id
        self.ind = ind
        # signal name
        self.name = name

        # signal buffer
        self.buffer = np.zeros((self.n_samples,))
        # signal statistics
        self.scaling_flag = scale
        self.mean = np.nan
        self.std = np.nan

        # rejections matrices list
        self.rejections = Rejections(n_channels)

        # spatial filter
        self.spatial_filter = np.zeros((n_channels,))
        self.spatial_filter_topography = None
        if spatial_filter is None:
            self.spatial_filter[0] = 0
        else:
            shape = min(spatial_filter.shape[0], n_channels)
            self.spatial_filter[:shape] = spatial_filter[:shape]

        # spatial matrix
        self.spatial_matrix = self.spatial_filter.copy()

        # current sample
        self.previous_sample = 0
        self.current_chunk = None
        pass
示例#8
0
文件: derived.py 项目: nikolaims/nfb
class DerivedSignal:
    @classmethod
    def from_params(cls, ind, fs, n_channels, channels, params, spatial_filter=None):
        if spatial_filter is None:
            spatial_filter = read_spatial_filter(params['SpatialFilterMatrix'], fs, channels, params['sROILabel'])
        return cls(ind=ind,
                   bandpass_high=params['fBandpassHighHz'],
                   bandpass_low=params['fBandpassLowHz'],
                   name=params['sSignalName'],
                   n_channels=n_channels,
                   spatial_filter=spatial_filter,
                   disable_spectrum_evaluation=params['bDisableSpectrumEvaluation'],
                   n_samples=params['fFFTWindowSize'],
                   smoothing_factor=params['fSmoothingFactor'],
                   source_freq=fs,
                   estimator_type=params['sTemporalType'],
                   temporal_filter_type=params['sTemporalFilterType'],
                   smoother_type=params['sTemporalSmootherType'],
                   filter_order=params['fTemporalFilterButterOrder'],
                   delay_ms=params['iDelayMs'])

    def __init__(self, ind, source_freq, n_channels=50, n_samples=1000, bandpass_low=None, bandpass_high=None,
                 spatial_filter=None, scale=False, name='Untitled', disable_spectrum_evaluation=False,
                 smoothing_factor=0.1, temporal_filter_type='fft', envelop_detector_kwargs=None, smoother_type='exp',
                 estimator_type='envdetector', filter_order=2, delay_ms=0):

        self.n_samples = int(n_samples)

        # bandpass
        self.bandpass = (bandpass_low if bandpass_low else 0,
                         bandpass_high if bandpass_high else source_freq)

        if estimator_type == 'envdetector':
            # setup smoother
            if smoother_type == 'exp':
                smoother = ExponentialSmoother(smoothing_factor)
            elif smoother_type == 'savgol':
                smoother = SGSmoother(151, 2)
            else:
                raise TypeError('Incorrect smoother type')
            # setup specific parameters of envelope detector
            if temporal_filter_type == 'fft':
                self.signal_estimator = FFTBandEnvelopeDetector(self.bandpass, source_freq, smoother, self.n_samples)
            elif temporal_filter_type == 'complexdem':
                self.signal_estimator = ComplexDemodulationBandEnvelopeDetector(self.bandpass, source_freq, smoother)
            elif temporal_filter_type == 'butter':
                self.signal_estimator = ButterBandEnvelopeDetector(self.bandpass, source_freq, smoother, filter_order)
            elif temporal_filter_type == 'cfir':
                self.signal_estimator = CFIRBandEnvelopeDetector(self.bandpass, source_freq, smoother, n_taps=self.n_samples)
            else:
                raise TypeError('Incorrect envelope detector type')
        elif estimator_type == 'filter':
            self.signal_estimator = ScalarButterFilter(self.bandpass, source_freq, filter_order)
        elif estimator_type == 'identity':
            self.signal_estimator = IdentityFilter()
        else:
            raise TypeError('Incorrect estimator type')

        if delay_ms > 0:
            self.signal_estimator = FilterSequence([self.signal_estimator, DelayFilter(int(source_freq*delay_ms/1000))])

        # id
        self.ind = ind
        # signal name
        self.name = name

        # signal buffer
        self.buffer = np.zeros((self.n_samples,))
        # signal statistics
        self.scaling_flag = scale
        self.mean = np.nan
        self.std = np.nan

        # rejections matrices list
        self.rejections = Rejections(n_channels)

        # spatial filter
        self.spatial_filter = np.zeros((n_channels,))
        self.spatial_filter_topography = None
        if spatial_filter is None:
            self.spatial_filter[0] = 0
        else:
            shape = min(spatial_filter.shape[0], n_channels)
            self.spatial_filter[:shape] = spatial_filter[:shape]

        # spatial matrix
        self.spatial_matrix = self.spatial_filter.copy()

        # current sample
        self.previous_sample = 0
        self.current_chunk = None
        pass

    def spatial_filter_is_zeros(self):
        return (self.spatial_filter == 0).all()

    def update(self, chunk):
        filtered_chunk = np.dot(chunk, self.spatial_matrix)
        current_chunk = self.signal_estimator.apply(filtered_chunk)
        if self.scaling_flag and self.std > 0:
            current_chunk = (current_chunk - self.mean) / self.std
        self.current_chunk = current_chunk
        return current_chunk

    def update_statistics(self, raw=None, emulate=False, signals_recorder=None, stats_type='meanstd'):
        if raw is not None and emulate:
            signal_recordings = np.zeros_like(signals_recorder[:, self.ind])
            mean_chunk_size = 8
            for k in range(0, raw.shape[0] - mean_chunk_size, mean_chunk_size):
                chunk = raw[k:k + mean_chunk_size]
                self.update(chunk)
                signal_recordings[k:k + mean_chunk_size] = self.current_chunk
        else:
            signal_recordings = signals_recorder[:, self.ind]
        if stats_type == 'meanstd':
            self.mean = signal_recordings.mean()
            self.std = signal_recordings.std()
        elif stats_type == 'max':
            self.std = signal_recordings.max()
            self.std = 1 if self.std == 0 else self.std
            self.mean = 0
        self.enable_scaling()
        return (signal_recordings - self.mean) / (self.std if self.std > 0 else 1)

    def update_spatial_filter(self, spatial_filter=None, topography=None):
        if spatial_filter is not None:
            self.spatial_filter = np.array(spatial_filter)
        self.spatial_matrix = np.dot(self.rejections.get_prod(), self.spatial_filter)
        self.spatial_filter_topography = topography if topography is not None else self.spatial_filter_topography

    def update_rejections(self, rejections, append=False):
        self.rejections.update_list(rejections, append=append)
        self.update_spatial_filter()

    def update_ica_rejection(self, rejection=None):
        self.rejections.update_ica(rejection)
        self.update_spatial_filter()

    def update_bandpass(self, bandpass):
        self.bandpass = bandpass

    def drop_rejection(self, ind):
        self.rejections.drop(ind)
        self.update_spatial_filter()
        print(self.rejections)


    def enable_scaling(self):
        self.scaling_flag = True

    def descale_recording(self, data):
        return data * self.std + self.mean if self.scaling_flag else data

    def save_spatial_matrix(self, file_path, channels_labels=None):
        """
        Save full spatial matrix: R1*R2*...*Rk*S, where R1,..Rk - rejections matrices, S - spatial filter
        :return:
        """
        save_spatial_filter(file_path, self.spatial_matrix, channels_labels=channels_labels)