from concurrent.futures import ProcessPoolExecutor, as_completedimport h5pyimport matplotlib.cm as cmimport matplotlib.pyplot as pltimport numpy as npimport pandas as pdimport scipy.io as sioimport seaborn as snsfrom scipy.interpolate import interp1dfrom scipy.signal import (butter, correlate, filtfilt, find_peaks, resample, sosfiltfilt, welch)
Loading experiment data
In [3]:
trial ='A0'eeg_filepath =f'../data/{trial}/converted/eeg_matrix.mat'eeg_trialinfo =f'../data/{trial}/converted/trialinfo_matrix_{trial}_cleanedtrials.mat'eeg_raw_data =f'../data/{trial}/experimental/data.mat'eeg_labels_path =f'../data/A0/preprocessing/channel_labels.mat'# always get the labels from A0
In [4]:
f = sio.loadmat(eeg_labels_path)labels = f['channellabels_ADSselection']len(labels) # 37 + 4
41
In [5]:
def load_mat_file(filepath):""" Load a MATLAB .mat file and return its content. """try: mat_contents = sio.loadmat(filepath)return mat_contentsexceptNotImplementedError:# If the file is v7.3, it will need h5py to handle itwith h5py.File(filepath, 'r') asfile:return {key: np.array(value) for key, value infile.items()}def get_eeg_data(eeg_data_path):""" Extract EEG data from the .mat file. """ data = load_mat_file(eeg_data_path) eeg_data = data['data_eeg']return eeg_datadef get_trial_info(trial_info_path):""" Extract trial information from the .mat file. """ data = load_mat_file(trial_info_path) trial_info = data['all_info']return trial_infodef load_raw_data(noise_data_path):""" Load and return the entire noise stimuli structure from the .mat file. """ mat_contents = load_mat_file(noise_data_path)# Extract the 'noise_stims' from the nested structure noise_stims = mat_contents['data'][0, 0]return noise_stimsdef get_specific_raw_data(idx, eeg_raw_data, block_index, trial_index):""" Fetch the specific noise stimulus for the given block, trial, and channel (0 for left, 1 for right). """ idxs = ['reaction_times', 'reaction_err', 'answers', 'base_delay', 'target_timings', 'flicker_sides', 'attend_sides', 'orients_L', 'orients_R', 'angle_magnitude', 'probe_sides', 'missed', 'targets_binary', 'tagging_types', 'noise_stims', 'p_num', 'date']return eeg_raw_data[idxs.index(idx)][block_index, trial_index]def trial_number_to_indices(trial_number):""" Convert trial number to block and trial indices, zero-indexed. """ trial_number =int(trial_number) -1 block_index = trial_number //32+1# +1 block because we've discard the first block trial_index = trial_number %32return block_index, trial_indexdef load_and_process_data(eeg_filepath, trialinfo_filepath, raw_data_filepath): eeg_data = get_eeg_data(eeg_filepath) trial_info = get_trial_info(trialinfo_filepath) eeg_raw_data = load_raw_data(raw_data_filepath) processed_trials = []# Assuming we loop over actual trial data, adjust as necessaryfor trial, eeg_data inzip(trial_info, eeg_data): block_index, trial_index = trial_number_to_indices(trial[14])# Access the corresponding noise stimulus for left and right channels noise_stim_left, noise_stim_right = get_specific_raw_data('noise_stims', eeg_raw_data, block_index, trial_index) trial_data = {'eeg': eeg_data, # Adjust for zero-index and skip block 1'trial_info': trial,'reaction_time_1': trial[2],'reaction_time_2': get_specific_raw_data('reaction_times', eeg_raw_data, block_index, trial_index),'has_noise': bool(int(trial[13])),'has_56|64': int(trial[7]) ==0,'has_56|60': int(trial[7]) ==1,'attended_side': trial[8],'noise_stim_left': noise_stim_left,'noise_stim_right': noise_stim_right,'base_delay': trial[6],'target_timings': trial[5], } processed_trials.append(trial_data)return processed_trialsexperiment_data = load_and_process_data(eeg_filepath, eeg_trialinfo, eeg_raw_data)experiment_data = pd.DataFrame(experiment_data)# These are in the form trials (440), samples (6758), channels (37)eeg_data = np.stack(experiment_data['eeg'])channel_labels = load_mat_file(eeg_labels_path)['channellabels_ADSselection'].flatten()channel_labels = [x[0] for x in channel_labels][:-4] # remove the last 4 channels, they're not used (EXG1 EXG2 EXG3 EXG4)print(' '.join(channel_labels))
num_channels = eeg_data.shape[1]noise_experiments = experiment_data[experiment_data['has_noise']]print(noise_experiments.shape)cross_corrs_all_trials = [[] for _ inrange(num_channels)]def process_experiment(experiment, channel_labels): eeg_data = experiment['eeg'] noise_stim_left = experiment['noise_stim_left'] noise_stim_right = experiment['noise_stim_right'] lags, correlations = compute_best_combined_offset(eeg_data, noise_stim_left, noise_stim_right, channel_labels, upsample_noise=True, eeg_start_time=0.0, eeg_end_time=3.2, noise_start_time=0.0, noise_end_time=2.0, # noise times present in the experiment# noise_start_time=4.0, noise_end_time=6.0, # noise times not present in the experiment bandpass_eeg=(50, 80), bandpass_noise=(50, 80),# mix_noise_strength=0.2, plot_results=False)# correlations = [interpolate_local_maxima(corr, 2048)[0] for corr in correlations]return correlationsdef parallel_process_experiments(experiments, channel_labels, num_channels): cross_corrs_all_trials = [[] for _ inrange(num_channels)]with ProcessPoolExecutor() as executor: futures = {executor.submit(process_experiment, experiment, channel_labels): i for i, experiment in experiments.iterrows()}for future in as_completed(futures): correlations = future.result()for channel inrange(num_channels): cross_corrs_all_trials[channel].append(correlations[channel])return cross_corrs_all_trialscross_corrs_all_trials = parallel_process_experiments(noise_experiments, channel_labels, num_channels)# Plot heatmaps for each channelsampling_rate =2048for channel, channel_label inenumerate(channel_labels):if channel_label notin ['Pz', 'POz', 'Iz', 'O1', 'PO3']: continue# Only plot the interesting occipital channels plt.figure(figsize=(40, 10))# Plot heatmap of cross-correlations for all trials# plt.subplot(2, 1, 1)# sns.heatmap(np.array(cross_corrs_all_trials[channel]), cmap='viridis', cbar=False)# plt.title(f'Heatmap of Cross-Correlations for Channel {channel + 1} / {channel_labels[channel]}')# plt.xlabel('Lag')# plt.ylabel('Trial')# plt.subplot(2, 1, 2)# Calculate and plot cumulative cross-correlation cumulative_corr = np.sum(np.array(cross_corrs_all_trials[channel]), axis=0) time_vector = np.linspace(0, len(cumulative_corr) / sampling_rate, len(cumulative_corr)) plt.plot(time_vector, cumulative_corr, label='Cumulative Cross-Correlation') plt.title(f'Cumulative Cross-Correlation for Channel {channel +1} / {channel_labels[channel]}') plt.xlabel('Time (seconds)') plt.ylabel('Cumulative Correlation') plt.xlim(0, time_vector[-1]) plt.legend() plt.tight_layout() plt.show()
(219, 12)
In [8]:
# Function to plot EEG channel before and after filteringdef plot_signal_filtering(signal, sampling_rate, lowcut, highcut, order=5, signal_name='EEG Signal'):# Apply bandpass filter filtered_signal = bandpass_filter(signal, lowcut, highcut, sampling_rate, order=order)# Time vector for plotting time_vector = np.linspace(0, len(signal) / sampling_rate, len(signal))# Plot EEG signal before and after filtering plt.figure(figsize=(40, 10)) plt.plot(time_vector, signal, label=f'Original {signal_name}') plt.plot(time_vector, filtered_signal, label=f'Filtered {signal_name}', color='orange') plt.title(f'{signal_name} Beforeand After Filtering') plt.xlabel('Time (seconds)') plt.ylabel('Amplitude') plt.xlim(0, len(signal) / sampling_rate) plt.legend() plt.show()# Frequency analysis before and after filtering freqs_before, psd_before = welch(signal, fs=sampling_rate) freqs_after, psd_after = welch(filtered_signal, fs=sampling_rate) plt.figure(figsize=(40, 10)) plt.semilogy(freqs_before, psd_before, label=f'Original {signal_name}') plt.semilogy(freqs_after, psd_after, label=f'Filtered {signal_name}', color='orange') plt.title('Frequency Analysis Before and After Filtering') plt.xlabel('Frequency (Hz)') plt.ylabel('Power Spectral Density (dB/Hz)') plt.xlim(0, 200) plt.legend() plt.show()# Example usage with the provided loopskip =2for _, experiment in experiment_data.iterrows():ifnot experiment['has_noise']: continueif skip >0: skip -=1continue channel =1 eeg_data = experiment['eeg'][:, channel] noise_stim_left = experiment['noise_stim_left']print(eeg_data.shape) plot_signal_filtering(eeg_data, sampling_rate=2048, lowcut=50, highcut=80) plot_signal_filtering(noise_stim_left, sampling_rate=480, lowcut=50, highcut=80, signal_name='Noise Stimulus')break
(6758,)
Topography plot of SNR’s
In [14]:
import mnedef calculate_snr(cross_corrs_all_trials, sampling_rate, expected_peak_time=None): snrs = []for channel_corrs in cross_corrs_all_trials: cumulative_corr = np.sum(channel_corrs, axis=0)# Time vector for the cross-correlation# time_vector = np.linspace(0, len(cumulative_corr) / sampling_rate, len(cumulative_corr))if expected_peak_time isnotNone:# Find the peak closest to the expected peak time peak_signal = np.max(cumulative_corr[int((expected_peak_time -0.0)*sampling_rate):int((expected_peak_time +0.1)*sampling_rate)])else:# Find the highest peak in the cross-correlationprint(np.max(cumulative_corr)) peak_signal = np.max(cumulative_corr)# Calculate the noise as the standard deviation of the cross-correlation noise = np.std(cumulative_corr) # Assuming this represents the noise snr =10* np.log10(peak_signal**2/ noise**2) snrs.append(snr)return snrs# Plot topographydef plot_topography(snr_values, channel_labels, sampling_rate): info = mne.create_info(ch_names=channel_labels, sfreq=sampling_rate, ch_types='eeg')# Use a standard montage for electrode positions montage = mne.channels.make_standard_montage('standard_1020') info.set_montage(montage)# Create Evoked object with SNR values evoked_data = np.array(snr_values).reshape(-1, 1) evoked = mne.EvokedArray(evoked_data, info)# Plot topography fig, ax = plt.subplots(figsize=(8, 6)) im, cn = mne.viz.plot_topomap(evoked.data[:, 0], evoked.info, axes=ax, show=False) fig.colorbar(im, ax=ax, format="%0.1f dB") ax.set_title('Topography of SNR (dB)', fontsize=14) plt.show()# Example usageexpected_peak_time =1.077# Adjust based on where you expect the peaksnr_values = calculate_snr(cross_corrs_all_trials, sampling_rate, expected_peak_time)plot_topography(snr_values, channel_labels, sampling_rate)
Predicting cued side
In [15]:
from sklearn.metrics import accuracy_scorefrom scipy.signal import coherence, resample, sosfilt, butterdef determine_dominant_side_coherence(eeg_data, noise_stim_left, noise_stim_right, channel_labels, lags, sampling_rate=2048, noise_sample_rate=480, upsample_noise=True, eeg_start_time=0.0, eeg_end_time=3.2, noise_start_time=0.0, noise_end_time=2.0, bandpass_eeg=None, bandpass_noise=None): num_samples, num_channels = eeg_data.shape eeg_segment_start =int(eeg_start_time * sampling_rate) eeg_segment_end =int(eeg_end_time * sampling_rate)# Select EEG segment eeg_data_segment = eeg_data[eeg_segment_start:eeg_segment_end, :].copy()# Select noise segment noise_segment_start =int(noise_start_time * noise_sample_rate) noise_segment_end =int(noise_end_time * noise_sample_rate) noise_stim_left_segment = noise_stim_left[noise_segment_start:noise_segment_end].copy() noise_stim_right_segment = noise_stim_right[noise_segment_start:noise_segment_end].copy()# Optionally bandpass filter the signalsif bandpass_eeg: lowcut, highcut = bandpass_eegfor channel inrange(num_channels): eeg_data_segment[:, channel] = bandpass_filter_sos(eeg_data_segment[:, channel], lowcut, highcut, sampling_rate)if bandpass_noise: lowcut, highcut = bandpass_noise noise_stim_left_segment = bandpass_filter_sos(noise_stim_left_segment, lowcut, highcut, noise_sample_rate) noise_stim_right_segment = bandpass_filter_sos(noise_stim_right_segment, lowcut, highcut, noise_sample_rate)# Upsample or downsample the noise signalsif upsample_noise: noise_stim_left_segment = upsample_or_downsample(noise_stim_left_segment, noise_sample_rate, sampling_rate) noise_stim_right_segment = upsample_or_downsample(noise_stim_right_segment, noise_sample_rate, sampling_rate)else: eeg_data_segment = upsample_or_downsample(eeg_data_segment, sampling_rate, noise_sample_rate) sampling_rate = noise_sample_rate# Normalise the signals before calculating coherence noise_stim_left_segment = normalise_signal(noise_stim_left_segment) noise_stim_right_segment = normalise_signal(noise_stim_right_segment) eeg_data_segment = normalise_signal(eeg_data_segment) predictions = []for channel, channel_label inenumerate(channel_labels): lag = lags[channel_label]# Select EEG segment starting from the lagif upsample_noise:# Find the coherent part from lag in EEG to the end eeg_aligned = eeg_data_segment[:, channel][lag+sampling_rate:lag+len(noise_stim_left_segment)]else:# Find the coherent part from lag in EEG to the end eeg_aligned = eeg_data_segment[:, channel][lag+sampling_rate:lag+len(noise_stim_left_segment)] eeg_aligned = upsample_or_downsample(eeg_aligned, noise_sample_rate, sampling_rate)# Compute coherence for left and right noise signals f, coh_left = coherence(eeg_aligned[:sampling_rate], noise_stim_left_segment[:sampling_rate], fs=sampling_rate, nperseg=256) f, coh_right = coherence(eeg_aligned[:sampling_rate], noise_stim_right_segment[:sampling_rate], fs=sampling_rate, nperseg=256)# print(coh_left.shape, coh_right.shape)# Calculate mean coherence value mean_coh_left = np.max(coh_left) mean_coh_right = np.max(coh_right)# Predict side: False for left, True for right predicted_side = mean_coh_right > mean_coh_left predictions.append(predicted_side)return predictionsdef determine_dominant_side(eeg_data, noise_stim_left, noise_stim_right, channel_labels, lags, sampling_rate=2048, noise_sample_rate=480, upsample_noise=True, eeg_start_time=0.0, eeg_end_time=3.2, noise_start_time=0.0, noise_end_time=2.0, bandpass_eeg=None, bandpass_noise=None,): num_samples, num_channels = eeg_data.shape# num_channels = len(channel_labels) eeg_segment_start =int(eeg_start_time * sampling_rate) eeg_segment_end =int(eeg_end_time * sampling_rate)# Select EEG segment eeg_data_segment = eeg_data[eeg_segment_start:eeg_segment_end, :].copy()# Select noise segment noise_segment_start =int(noise_start_time * noise_sample_rate) noise_segment_end =int(noise_end_time * noise_sample_rate) noise_stim_left_segment = noise_stim_left[noise_segment_start:noise_segment_end].copy() noise_stim_right_segment = noise_stim_right[noise_segment_start:noise_segment_end].copy()# Optionally bandpass filter the signalsif bandpass_eeg: lowcut, highcut = bandpass_eegfor channel inrange(num_channels): eeg_data_segment[:, channel] = bandpass_filter_sos(eeg_data_segment[:, channel], lowcut, highcut, sampling_rate)if bandpass_noise: lowcut, highcut = bandpass_noise noise_stim_left_segment = bandpass_filter_sos(noise_stim_left_segment, lowcut, highcut, noise_sample_rate) noise_stim_right_segment = bandpass_filter_sos(noise_stim_right_segment, lowcut, highcut, noise_sample_rate)# Upsample or downsample the noise signalsif upsample_noise: noise_stim_left_segment = upsample_or_downsample(noise_stim_left_segment, noise_sample_rate, sampling_rate) noise_stim_right_segment = upsample_or_downsample(noise_stim_right_segment, noise_sample_rate, sampling_rate)else: eeg_data_segment = upsample_or_downsample(eeg_data_segment, sampling_rate, noise_sample_rate) sampling_rate = noise_sample_rate# Normalise the signals before mixing and cross-correlation noise_stim_left_segment = normalise_signal(noise_stim_left_segment) noise_stim_right_segment = normalise_signal(noise_stim_right_segment) eeg_data_segment = normalise_signal(eeg_data_segment) predictions = []for channel, channel_label inenumerate(channel_labels): lag = lags[channel_label]# Compute correlation for left and right noise signals starting from the lag corr_left = correlate(eeg_data_segment[:, channel], noise_stim_left_segment, mode='full') corr_right = correlate(eeg_data_segment[:, channel], noise_stim_right_segment, mode='full')# print(corr_left.shape, corr_right.shape)# Use lag to index into the correlation corr_left_value = corr_left[lag + (len(noise_stim_left_segment) -1)] corr_right_value = corr_right[lag + (len(noise_stim_right_segment) -1)]print(corr_left_value, corr_right_value)# Predict side: False for left, True for right predicted_side = corr_right_value > corr_left_value predictions.append(predicted_side)return predictionsdef compute_channel_accuracy(experiment_data, cross_corrs_all_trials, sampling_rate): lags = {}for channel_corrs, channel_label inzip(cross_corrs_all_trials, channel_labels): cumulative_corr = np.sum(channel_corrs, axis=0) lag = np.argmax(cumulative_corr) lags[channel_label] = lagprint(sorted(lags.items(), key=lambda x: x[1])) accuracies = {label: [] for label in channel_labels} overall_predictions = []for _, experiment in experiment_data.iterrows(): eeg_data = experiment['eeg'] noise_stim_left = experiment['noise_stim_left'] noise_stim_right = experiment['noise_stim_right'] actual_side = experiment['attended_side'] predictions = determine_dominant_side_coherence(eeg_data, noise_stim_left, noise_stim_right, channel_labels, lags, upsample_noise=True, bandpass_eeg=(50, 80), bandpass_noise=(50, 80), eeg_start_time=0.0, eeg_end_time=3.2, noise_start_time=0.0, noise_end_time=2.0)for channel, predicted_side inzip(channel_labels, predictions):if channel =='Iz'or channel =='POz':print(f'Channel {channel}: Predicted Side = {predicted_side}, Actual Side = {actual_side}') accuracies[channel].append(predicted_side == actual_side) overall_predictions.append(predictions)# Compute accuracy per channel# 'Iz', 2206), ('POz'# print(channel['Iz']) channel_accuracies = {channel: np.mean(acc) for channel, acc in accuracies.items()}return channel_accuracies, overall_predictionsdef majority_voting(overall_predictions, experiment_data, selected_channels): majority_predictions = []for trial_predictions, experiment inzip(overall_predictions, experiment_data.iterrows()): selected_predictions = [trial_predictions[channel_labels.index(channel)] for channel in selected_channels] predicted_side = np.mean(selected_predictions) >0.5 actual_side = experiment[1]['attended_side'] majority_predictions.append(predicted_side == actual_side) overall_accuracy = np.mean(majority_predictions)return overall_accuracy# Example usagenoise_experiments = experiment_data[experiment_data['has_noise']]channel_accuracies, overall_predictions = compute_channel_accuracy(noise_experiments, cross_corrs_all_trials, sampling_rate)# Print accuracy for each channelfor channel, accuracy in channel_accuracies.items():print(f'Channel {channel}: Accuracy = {accuracy:.2f}')# Majority voting across selected channelsselected_channels = channel_labels # Example: use all channelsselected_channels = ['P5', 'PO3', 'O1', 'Iz', 'POz',]overall_accuracy = majority_voting(overall_predictions, experiment_data, selected_channels)print(f'Overall accuracy with majority voting: {overall_accuracy:.2f}')
[('FC5', 2), ('AF7', 3), ('PO8', 79), ('F5', 473), ('P6', 720), ('FT7', 726), ('P7', 787), ('T7', 907), ('Fp1', 934), ('PO7', 1002), ('C3', 1213), ('C5', 1245), ('CP5', 1247), ('F1', 1552), ('P8', 1562), ('FC1', 1691), ('PO4', 1717), ('P4', 1763), ('CP3', 1765), ('O2', 1779), ('F3', 1824), ('P1', 2173), ('Pz', 2174), ('P3', 2175), ('P5', 2206), ('PO3', 2206), ('O1', 2206), ('Iz', 2206), ('POz', 2207), ('AF3', 2371), ('F7', 2444), ('Oz', 2528), ('FC3', 2565), ('C1', 2569), ('TP7', 2875), ('CP1', 3216), ('P2', 3248)]
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 0.0
Channel POz: Predicted Side = True, Actual Side = 0.0
Channel Iz: Predicted Side = False, Actual Side = 0.0
Channel POz: Predicted Side = False, Actual Side = 0.0
Channel Iz: Predicted Side = True, Actual Side = 1.0
Channel POz: Predicted Side = True, Actual Side = 1.0
Channel Iz: Predicted Side = False, Actual Side = 1.0
Channel POz: Predicted Side = False, Actual Side = 1.0
Channel Fp1: Accuracy = 0.51
Channel AF7: Accuracy = 0.49
Channel AF3: Accuracy = 0.55
Channel F1: Accuracy = 0.54
Channel F3: Accuracy = 0.56
Channel F5: Accuracy = 0.49
Channel F7: Accuracy = 0.51
Channel FT7: Accuracy = 0.48
Channel FC5: Accuracy = 0.45
Channel FC3: Accuracy = 0.54
Channel FC1: Accuracy = 0.51
Channel C1: Accuracy = 0.52
Channel C3: Accuracy = 0.47
Channel C5: Accuracy = 0.53
Channel T7: Accuracy = 0.52
Channel TP7: Accuracy = 0.52
Channel CP5: Accuracy = 0.52
Channel CP3: Accuracy = 0.51
Channel CP1: Accuracy = 0.56
Channel P1: Accuracy = 0.48
Channel P3: Accuracy = 0.54
Channel P5: Accuracy = 0.56
Channel P7: Accuracy = 0.58
Channel PO7: Accuracy = 0.50
Channel PO3: Accuracy = 0.53
Channel O1: Accuracy = 0.54
Channel Iz: Accuracy = 0.45
Channel Oz: Accuracy = 0.52
Channel POz: Accuracy = 0.47
Channel Pz: Accuracy = 0.52
Channel P2: Accuracy = 0.55
Channel P4: Accuracy = 0.47
Channel P6: Accuracy = 0.44
Channel P8: Accuracy = 0.54
Channel PO8: Accuracy = 0.55
Channel PO4: Accuracy = 0.43
Channel O2: Accuracy = 0.52
Overall accuracy with majority voting: 0.52
Don’t mind this below :)
In [9]:
def interpolate_local_maxima(signal, sampling_rate):# Find peaks (local maxima) peaks, _ = find_peaks(signal)# Extract peak values and their corresponding times peak_values = signal[peaks] peak_times = peaks / sampling_rate# Create an interpolation function interp_func = interp1d(peak_times, peak_values, kind='cubic', fill_value="extrapolate")# Interpolate over the entire signal duration full_time_vector = np.arange(len(signal)) / sampling_rate interpolated_signal = interp_func(full_time_vector)return interpolated_signal, peakssampling_rate =2048noise_experiments = experiment_data[experiment_data['has_noise']]for _, experiment in noise_experiments.iterrows(): eeg_data = experiment['eeg'] noise_stim_left = experiment['noise_stim_left'] noise_stim_right = experiment['noise_stim_right'] lags, cross_corrs = compute_best_combined_offset(eeg_data, noise_stim_left, noise_stim_right, channel_labels, upsample_noise=True, eeg_start_time=0.0, eeg_end_time=3.2, noise_start_time=0.1, noise_end_time=1.9, bandpass_eeg=(50, 80), bandpass_noise=(50, 80),# mix_noise_strength=0.1, plot_results=False)# Plot the cross-correlation for the first channel channel =26 cross_corr = cross_corrs[channel] interpolated_signal, peaks = interpolate_local_maxima(cross_corr, sampling_rate=sampling_rate)# Plot the original cross-correlation signal and the interpolated local maxima signal plt.figure(figsize=(50, 6))# Time vector for cross-correlation signal corr_time_vector = np.linspace(0, len(cross_corr) / (sampling_rate), len(cross_corr))# Plot original cross-correlation signal plt.plot(corr_time_vector, cross_corr, label='Original Cross-Correlation Signal', color='blue')# Plot interpolated local maxima signal plt.plot(corr_time_vector, interpolated_signal, label='Interpolated Local Maxima Signal', color='orange', linestyle='--')# Mark peaks plt.plot(corr_time_vector[peaks], cross_corr[peaks], 'x', label='Local Maxima', color='red')# Add titles and labels plt.title('Cross-Correlation Signal and Interpolated Local Maxima Signal') plt.xlabel('Time (seconds)') plt.ylabel('Amplitude') plt.legend() plt.xlim(0, len(cross_corr) / sampling_rate) plt.grid(True)# Show plot plt.show()# Compute the FFT of the original cross-correlation signal and the interpolated local maxima signal freqs = np.fft.fftfreq(len(cross_corr), 1/ sampling_rate) fft_original = np.abs(np.fft.fft(cross_corr)) fft_interpolated = np.abs(np.fft.fft(interpolated_signal))# Plot the frequency spectrum before and after interpolation plt.figure(figsize=(14, 6))# Plot original signal frequency spectrum plt.plot(freqs[:len(freqs)//2], fft_original[:len(freqs)//2], label='Original Signal Frequency Spectrum', color='blue')# Plot interpolated signal frequency spectrum plt.plot(freqs[:len(freqs)//2], fft_interpolated[:len(freqs)//2], label='Interpolated Signal Frequency Spectrum', color='orange', linestyle='--')# Add titles and labels plt.title('Frequency Spectrum Before and After Interpolation') plt.xlabel('Frequency (Hz)') plt.ylabel('Amplitude') plt.legend() plt.xlim(0, 100) plt.grid(True) plt.tight_layout()# Show plot plt.show()break