class EpochAveraging(Block): family = 'PreProcessing' name = 'EpochAveraging' def __init__(self): self.epochs = BlockInput( name='Epochs', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EPOCHS ) self.epochs_output = BlockOutput( name='Epochs', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.EPOCHS ) def input_params(self,data): self.epochs.set_value(data['Epochs']) def execute(self): avgepoch = self.epochs.value.average() self.epochs_output.set_value(avgepoch) return None
class Subtraction(Block): family = 'AddSub' name = 'Subtraction' def __init__(self): self.num1 = BlockInput(name='num1', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.NUMBER) self.num2 = BlockInput(name='num2', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.NUMBER) self.output = BlockOutput(name='output', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.NUMBER) def input_params(self, data): self.num1.set_value(data['num1']) self.num2.set_value(data['num2']) def execute(self): value = self.num1.value - self.num2.value self.output.set_value(value) return (value, 'STRING')
class EEGPlot(Block): family = 'Visualization' name = 'EEGPlot' def __init__(self): self.eeg_data = BlockInput(name='EEGData', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EEGDATA) def input_params(self, data): self.eeg_data.set_value(data['EEGData']) def execute(self): value = self.eeg_data.value channels = value.ch_names time = value.times plt.figure(figsize=(18, 7)) data = value.get_data() for i in range(data.shape[0]): plt.plot(time, np.array(data[i:i + 1, :]).flatten()) print(channels[i]) plt.legend(channels) plt.xlabel('Time (s)') plt.ylabel('EEG Amplitude') plt.title('EEG Data of channel/s: {}'.format(value.ch_names)) plt.grid() return (None, 'GRAPH')
class EpochPlot(Block): family = 'Visualization' name = 'EpochPlot' def __init__(self): self.epochs = BlockInput(name='Epochs', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EPOCHS) def input_params(self, data): self.epochs.set_value(data['Epochs']) def execute(self): epochs = self.epochs.value if (epochs.__class__.__name__ == 'Epochs'): plot = epochs.plot_image(picks=None, cmap='interactive', sigma=1., combine='mean', show=False) return (plot[0], 'GRAPH') elif (epochs.__class__.__name__ == 'EvokedArray'): plot = epochs.plot_image(picks=None, cmap='interactive', show=False) return (plot, 'GRAPH') return None
class WaveletTransform(Block): family = 'FeatureExtraction' name = 'WaveletTransform' def __init__(self): self.epochs = BlockInput(name='Epochs', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EPOCHS) self.feature_vector = BlockOutput( name='FeatureVector', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.FEATUREVECTOR) def input_params(self, data): self.epochs.set_value(data['Epochs']) def execute(self): feature_list = [] epochs = self.epochs.value event_ids = epochs.event_id event_id_class_mp = self.event_id_to_class(event_ids) for event_name, event_id in event_ids.items(): event_epochs = epochs[event_name].get_data() for epoch in event_epochs: # feature_vector = self.extractFeatures(epoch,event_id_class_mp[event_id]) feature_vector = self.extractFeatures(epoch, event_id) feature_list.append(feature_vector) self.feature_vector.set_value(feature_list) stdout_string = '<br>Total datapoints: {} <br> No. of Features: {}'.format( len(feature_list), feature_list[0].features.shape) return (stdout_string, 'STRING') def event_id_to_class(self, event_ids): event_id_class_mp = {} i = 0 for event_name, event_id in event_ids.items(): if (event_id not in event_id_class_mp.keys()): event_id_class_mp[event_id] = i i += 1 return event_id_class_mp def extractFeatures(self, epoch, event_id): features = np.array([]) for channel_data in epoch: coff_approx, coff_detail = pywt.dwt(channel_data, 'db1') features = np.hstack([features, coff_approx]) norm = np.linalg.norm(features) feature_vector = FeatureVector(features / norm, event_id) return feature_vector
class FeatureLabeling(Block): family = 'FeatureExtraction' name = 'FeatureLabeling' def __init__(self): self.feature_vector = BlockInput(name='FeatureVector', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EPOCHS) self.labels = BlockParameter( name='Labels', attribute_type=ParameterType.STRING_ARRAY, defaultvalue='', description= 'All comma separated event ids are considered as one class.<br>Event id will not be considered if not added' ) self.feature_vector_out = BlockOutput( name='FeatureVector', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.FEATUREVECTOR) def input_params(self, data): self.feature_vector.set_value(data['FeatureVector']) self.labels.set_value(data['Labels']) def execute(self): ''' Here every comma separated event ids are assigned same class. For exmaple if the block parameter is: - [ '2,4', '3', '5,6' ] - So classes are assigned like: - event id 2 and 4 are assigned class 0 - event id 3 is assigned class 1 - event id 5 and 5 are assigned class 2 ''' event_class_mp = self.event_class_mapping() features = [] for feature in self.feature_vector.value: class_id = feature.class_id if (class_id in event_class_mp.keys()): feature.set_class(event_class_mp[class_id]) features.append(feature) self.feature_vector_out.set_value(features) return (event_class_mp, 'STRING') def event_class_mapping(self): mapping = {} class_i = 0 for label in self.labels.value: event_ids = [int(x) for x in label.split(',')] for event_id in event_ids: mapping[event_id] = class_i class_i += 1 return mapping
class NeuralNetworkLayer(Block): family = 'Classification' name = 'NeuralNetworkLayer' def __init__(self): self.model = BlockInput(name='Model', min_cardinality=0, max_cardinality=1, attribute_type=ParameterType.MODEL) self.units = BlockParameter(name='Number of Units', attribute_type=ParameterType.NUMBER, defaultvalue='', description='Must be an Integer') self.activation = BlockParameter( name='Activation Function', attribute_type=ParameterType.STRING, defaultvalue='relu', description= "Either, 'sigmoid', 'relu', 'softmax', 'elu', 'leaky-relu', 'selu' or 'gelu'" ) self.dropout = BlockParameter( name='Dropout', attribute_type=ParameterType.STRING, defaultvalue='0', description="Fraction of the input units to drop") self.model_out = BlockOutput(name='Model', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.MODEL) def input_params(self, data): act_func = [ 'sigmoid', 'relu', 'softmax', 'elu', 'leaky-relu', 'selu', 'gelu' ] if ('Model' not in data.keys()): self.model.set_value(None) else: self.model.set_value(data['Model']) self.units.set_value(int(data['Number of Units'])) self.activation.set_value(data['Activation Function']) self.dropout.set_value(float(data['Dropout'])) def execute(self): if (self.model.value == None): model = Sequential() else: model = self.model.value model.add(Dense(self.units.value, activation=self.activation.value)) model.add(Dropout(self.dropout.value)) self.model_out.set_value(model) return None
class Filter(Block): family = 'PreProcessing' name = 'Filter' def __init__(self): self.eeg_data = BlockInput(name='EEGData', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EEGDATA) self.low_cutoff_freq = BlockParameter( name='Low Cutoff Frequency', attribute_type=ParameterType.NUMBER, defaultvalue='None', description='If None the data are only low-passed') self.high_cutoff_freq = BlockParameter( name='High Cutoff Frequency', attribute_type=ParameterType.NUMBER, defaultvalue='None', description='If None the data are only high-passed') self.eeg_data_output = BlockOutput( name='EEGData', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.EEGDATA) def input_params(self, data): self.eeg_data.set_value(data['EEGData']) if (data['Low Cutoff Frequency'] == 'None'): self.low_cutoff_freq.set_value(None) else: self.low_cutoff_freq.set_value(float(data['Low Cutoff Frequency'])) if (data['High Cutoff Frequency'] == 'None'): self.high_cutoff_freq.set_value(None) else: self.high_cutoff_freq.set_value( float(data['High Cutoff Frequency'])) def execute(self): raw = self.eeg_data.value raw.filter(self.low_cutoff_freq.value, self.high_cutoff_freq.value, fir_design='firwin') self.eeg_data_output.set_value(raw) return None
class EventAndIds(Block): family = 'PreProcessing' name = 'EventAndIds' description = "Dictionary of 'Name' : 'Id' pair" def __init__(self): self.eeg_data = BlockInput(name='EEGData', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EEGDATA) def input_params(self, data): self.eeg_data.set_value(data['EEGData']) def execute(self): raw = self.eeg_data.value events, event_ids = mne.events_from_annotations(raw) return (event_ids, 'STRING')
class ChannelNames(Block): family = 'PreProcessing' name = 'ChannelNames' def __init__(self): self.eeg_data = BlockInput( name='EEGData', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EEGDATA ) def input_params(self,data): self.eeg_data.set_value(data['EEGData']) def execute(self): value = self.eeg_data.value return (value.ch_names,'STRING')
class ChannelSelection(Block): family = 'PreProcessing' name = 'ChannelSelection' def __init__(self): self.eeg_data = BlockInput( name='EEGData', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EEGDATA ) self.channels = BlockParameter( name='Channels', attribute_type=ParameterType.STRING_ARRAY, defaultvalue='', description='Select channel' ) self.eeg_data_output = BlockOutput( name='EEGData', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.EEGDATA ) def input_params(self,data): self.channels.set_value(data['Channels']) self.eeg_data.set_value(data['EEGData']) def execute(self): value = self.eeg_data.value value = value.pick_channels(self.channels.value) self.eeg_data_output.set_value(value) return (value.get_data().shape,'STRING')
class SaveModel(Block): family = 'Classification' name = 'SaveModel' def __init__(self): self.model = BlockInput(name='Model', min_cardinality=0, max_cardinality=1, attribute_type=ParameterType.MODEL) self.model_out = BlockOutput(name='Model', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.MODEL) def input_params(self, data): if ('Model' not in data.keys()): self.model.set_value(None) else: self.model.set_value(data['Model']) def execute(self): self.model_out.set_value(self.model.value) return (self.model_out.value, 'MODEL')
class Multiplication(Block): family = 'MultiDiv' name = 'Multiplication' def __init__(self): self.num1 = BlockInput( name='num1', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.NUMBER ) self.num2 = BlockInput( name='num2', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.NUMBER ) self.output = BlockOutput( name='output', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.NUMBER ) def input_params(self,data): # time.sleep(10) # list(2) self.num1.set_value(data['num1']) self.num2.set_value(data['num2']) def execute(self): value = self.num1.value * self.num2.value self.output.set_value(value) return (value,'STRING')
class EpochExtraction(Block): family = 'PreProcessing' name = 'EpochExtraction' def __init__(self): self.eeg_data = BlockInput(name='EEGData', min_cardinality=1, max_cardinality=1, attribute_type=ParameterType.EEGDATA) self.pre_stimulus_onset = BlockParameter( name='PreStimulus onset', attribute_type=ParameterType.NUMBER, defaultvalue='-0.2', description='') self.post_stimulus_onset = BlockParameter( name='PostStimulus onset', attribute_type=ParameterType.NUMBER, defaultvalue='0.5', description='') self.baseline_start_time = BlockParameter( name='Baseline Correction Start Time', attribute_type=ParameterType.STRING, defaultvalue='None', description='None means beginning of the data') self.baseline_end_time = BlockParameter( name='Baseline Correction End Time', attribute_type=ParameterType.STRING, defaultvalue='0', description='None means end of the data') self.event_id = BlockParameter(name='Event Id', attribute_type=ParameterType.STRING, defaultvalue='None', description='None means all the events') self.eeg_data_output = BlockOutput(name='Epochs', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.EPOCHS) def input_params(self, data): self.eeg_data.set_value(data['EEGData']) self.pre_stimulus_onset.set_value(float(data['PreStimulus onset'])) self.post_stimulus_onset.set_value(float(data['PostStimulus onset'])) if (data['Baseline Correction Start Time'] == 'None'): self.baseline_start_time.set_value(None) else: self.baseline_start_time.set_value( float(data['Baseline Correction Start Time'])) if (data['Baseline Correction End Time'] == 'None'): self.baseline_end_time.set_value(None) else: self.baseline_end_time.set_value( float(data['Baseline Correction End Time'])) if (data['Event Id'] == 'None'): self.event_id.set_value(None) else: self.event_id.set_value(int(data['Event Id'])) def execute(self): raw = self.eeg_data.value events, event_id = mne.events_from_annotations(raw) # https://mne.tools/stable/generated/mne.Epochs.html epochs = mne.Epochs(raw, events, event_id=self.event_id.value, tmin=self.pre_stimulus_onset.value, tmax=self.post_stimulus_onset.value, baseline=(self.baseline_start_time.value, self.baseline_end_time.value), preload=True) self.eeg_data_output.set_value(epochs) return (epochs.get_data().shape, 'STRING')
class NeuralNetworkClassifier(Block): family = 'Classification' name = 'NeuralNetworkClassifier' def __init__(self): self.model = BlockInput(name='Model', min_cardinality=0, max_cardinality=1, attribute_type=ParameterType.MODEL) self.feature_vector = BlockInput( name='FeatureVector', min_cardinality=0, max_cardinality=1, attribute_type=ParameterType.FEATUREVECTOR) self.optimizer = BlockParameter( name='Optimizer', attribute_type=ParameterType.STRING, defaultvalue='adam', description="Either, 'adam', 'adagrad', 'rmsprop'") self.test_size = BlockParameter( name='Test Size', attribute_type=ParameterType.NUMBER, defaultvalue='0.33', description="Test Train Split. Ratio of test size") self.epochs = BlockParameter(name='Number of Epochs', attribute_type=ParameterType.NUMBER, defaultvalue='100', description="") self.classes = BlockParameter( name='Number of Classes', attribute_type=ParameterType.NUMBER, defaultvalue='', description="Number of Classification classes") self.model_out = BlockOutput(name='Model', min_cardinality=1, max_cardinality=100, attribute_type=ParameterType.MODEL) def input_params(self, data): self.model.set_value(data['Model']) self.feature_vector.set_value(data['FeatureVector']) self.optimizer.set_value(data['Optimizer']) self.test_size.set_value(float(data['Test Size'])) self.epochs.set_value(int(data['Number of Epochs'])) self.classes.set_value(int(data['Number of Classes'])) def execute(self): model = self.model.value model.compile(loss='categorical_crossentropy', optimizer=self.optimizer.value, metrics=['accuracy']) X = [] Y = [] for datapoint in self.feature_vector.value: X.append(datapoint.features) Y.append(datapoint.class_id) X_train, X_test, y_train, y_test = train_test_split( np.array(X), np.array(Y), test_size=self.test_size.value, random_state=42) number_of_training_sample = X_train.shape print(number_of_training_sample) print(X_test.shape) print(set(y_train)) print(set(y_test)) y_train = keras.utils.to_categorical(y_train, self.classes.value) y_test = keras.utils.to_categorical(y_test, self.classes.value) # X_train = X_test = np.array(X) # y_test = y_train = keras.utils.to_categorical(np.array(Y),self.classes.value) history = model.fit(X_train, y_train, epochs=self.epochs.value, validation_data=(X_test, y_test)) self.model_out.set_value(model) validation_acc = history.history['val_accuracy'][-1] training_acc = history.history['accuracy'][-1] stdout = "<br>Training Accuracy: {}<br>Validation Accuracy: {}<br>No. of Training Samples: {}".format( training_acc, validation_acc, number_of_training_sample[0]) return (stdout, 'STRING')