Source code for src.statistics.statistics_snr.statistics_snr_view

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Statistics SNR view
"""

import numpy as np
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, QHBoxLayout, QLabel, QComboBox, QButtonGroup, QCheckBox, \
    QScrollArea
from matplotlib import pyplot as plt

from utils.elements_selector.elements_selector_controller import multipleSelectorController
from utils.view.separator import create_layout_separator

__author__ = "Lemahieu Antoine"
__copyright__ = "Copyright 2022"
__credits__ = ["Lemahieu Antoine"]
__license__ = "GNU General Public License v3.0"
__maintainer__ = "Lemahieu Antoine"
__email__ = "Antoine.Lemahieu@ulb.be"
__status__ = "Dev"


[docs]class statisticsSnrView(QWidget): def __init__(self, all_channels_names, event_values, event_ids): """ Window displaying the parameters for computing the SNR on the dataset. :param all_channels_names: All the channels' names :type all_channels_names: list of str :param event_values: The events' information. Each event is represented by a list of 3 elements: First the latency time of the event; Second a "0" for MNE backwards compatibility; Third the event id. :type event_values: list of, list of int :param event_ids: The events' ids :type event_ids: dict """ super().__init__() self.snr_listener = None self.all_channels_names = all_channels_names self.event_values = event_values self.event_ids = event_ids self.channels_selected = None self.snr_methods = None self.trials_selected = None self.snr_selector_controller = None self.channels_selector_controller = None self.events_selector_controller = None self.setWindowTitle("Statistics and Signal-To-Noise Ratio") self.vertical_layout = QVBoxLayout() self.setLayout(self.vertical_layout) # Statistics and on what to compute self.statistics_widget = QWidget() self.statistics_global_layout = QVBoxLayout() self.statistics_title_label = QLabel("Select the two independent variables to compute the statistics on :") # Independent variables self.statistics_independent_variables_widget = QWidget() self.statistics_independent_variables_layout = QHBoxLayout() # First independent variable self.first_independent_variable_widget = QWidget() self.first_independent_variable_layout = QVBoxLayout() self.first_independent_variable_label = QLabel("First independent variable :") self.first_independent_variable_layout.addWidget(self.first_independent_variable_label) self.first_independent_variable_button = QButtonGroup() self.create_first_independent_variable_check_boxes() self.first_independent_variable_widget.setLayout(self.first_independent_variable_layout) self.first_independent_variable_scroll_area = QScrollArea() self.first_independent_variable_scroll_area.setWidgetResizable(True) self.first_independent_variable_scroll_area.setWidget(self.first_independent_variable_widget) self.statistics_independent_variables_layout.addWidget(self.first_independent_variable_scroll_area) # Second independent variable self.second_independent_variable_widget = QWidget() self.second_independent_variable_layout = QVBoxLayout() self.second_independent_variable_label = QLabel("Second independent variable :") self.second_independent_variable_layout.addWidget(self.second_independent_variable_label) self.second_independent_variable_button = QButtonGroup() self.create_second_independent_variable_check_boxes() self.second_independent_variable_widget.setLayout(self.second_independent_variable_layout) self.second_independent_variable_scroll_area = QScrollArea() self.second_independent_variable_scroll_area.setWidgetResizable(True) self.second_independent_variable_scroll_area.setWidget(self.second_independent_variable_widget) self.statistics_independent_variables_layout.addWidget(self.second_independent_variable_scroll_area) self.statistics_independent_variables_widget.setLayout(self.statistics_independent_variables_layout) self.statistics_global_layout.addWidget(self.statistics_title_label) self.statistics_global_layout.addWidget(self.statistics_independent_variables_widget) self.statistics_widget.setLayout(self.statistics_global_layout) # SNR Methods self.snr_selection_widget = QWidget() self.snr_selection_layout = QHBoxLayout() self.snr_selection_button = QPushButton("&SNR methods ...", self) self.snr_selection_button.clicked.connect(self.snr_selection_trigger) self.snr_selection_layout.addWidget(QLabel("SNR Methods selection : ")) self.snr_selection_layout.addWidget(self.snr_selection_button) self.snr_selection_widget.setLayout(self.snr_selection_layout) # Channels self.channels_selection_widget = QWidget() self.channels_selection_layout = QHBoxLayout() self.channels_selection_button = QPushButton("&Channels ...", self) self.channels_selection_button.clicked.connect(self.channels_selection_trigger) self.channels_selection_layout.addWidget(QLabel("Channels : ")) self.channels_selection_layout.addWidget(self.channels_selection_button) self.channels_selection_widget.setLayout(self.channels_selection_layout) # Source Method self.method_widget = QWidget() self.method_layout = QHBoxLayout() self.method_box = QComboBox() self.method_box.addItems(["MNE", "dSPM", "sLORETA", "eLORETA"]) self.method_layout.addWidget(QLabel("Source estimation method : ")) self.method_layout.addWidget(self.method_box) self.method_widget.setLayout(self.method_layout) # How to compute self.save_load_widget = QWidget() self.check_box_layout = QVBoxLayout() self.save_load_buttons = QButtonGroup() self.check_box_compute_from_scratch = QCheckBox() self.check_box_compute_from_scratch.setText("Compute source estimation from scratch and don't save") self.check_box_compute_from_scratch.setChecked(True) self.save_load_buttons.addButton(self.check_box_compute_from_scratch, 0) # Button with ID 0 self.check_box_save = QCheckBox() self.check_box_save.setText("Save source estimation files") self.save_load_buttons.addButton(self.check_box_save, 1) # Button with ID 1 self.check_box_load = QCheckBox() self.check_box_load.setText("Load source estimation files") self.save_load_buttons.addButton(self.check_box_load, 2) # Button with ID 2 self.check_box_layout.addWidget(self.check_box_compute_from_scratch) self.check_box_layout.addWidget(self.check_box_save) self.check_box_layout.addWidget(self.check_box_load) self.save_load_widget.setLayout(self.check_box_layout) # Cancel confirm self.cancel_confirm_widget = QWidget() self.cancel_confirm_layout = QHBoxLayout() self.cancel = QPushButton("&Cancel", self) self.cancel.clicked.connect(self.cancel_snr_trigger) self.confirm = QPushButton("&Confirm", self) self.confirm.clicked.connect(self.confirm_snr_trigger) self.cancel_confirm_layout.addWidget(self.cancel) self.cancel_confirm_layout.addWidget(self.confirm) self.cancel_confirm_widget.setLayout(self.cancel_confirm_layout) # Layout self.vertical_layout.addWidget(self.statistics_widget) self.vertical_layout.addWidget(create_layout_separator()) self.vertical_layout.addWidget(self.snr_selection_widget) self.vertical_layout.addWidget(self.channels_selection_widget) self.vertical_layout.addWidget(create_layout_separator()) self.vertical_layout.addWidget(self.method_widget) self.vertical_layout.addWidget(self.save_load_widget) self.vertical_layout.addWidget(create_layout_separator()) self.vertical_layout.addWidget(self.cancel_confirm_widget)
[docs] def create_first_independent_variable_check_boxes(self): event_ids = self.event_ids self.first_independent_variable_button.setExclusive(True) for i, event_id in enumerate(event_ids): check_box = QCheckBox() check_box.setText(event_id) if i == 0: check_box.setChecked(True) self.first_independent_variable_layout.addWidget(check_box) self.first_independent_variable_button.addButton(check_box, i)
[docs] def create_second_independent_variable_check_boxes(self): event_ids = self.event_ids self.second_independent_variable_button.setExclusive(True) for i, event_id in enumerate(event_ids): check_box = QCheckBox() check_box.setText(event_id) if i == 0: check_box.setChecked(True) self.second_independent_variable_layout.addWidget(check_box) self.second_independent_variable_button.addButton(check_box, i)
""" Triggers """
[docs] def cancel_snr_trigger(self): """ Send the information to the controller that the computation is cancelled. """ self.snr_listener.cancel_button_clicked()
[docs] def confirm_snr_trigger(self): """ Retrieve the parameters and send the information to the controller. """ source_method = self.method_box.currentText() write, read = self.get_save_load_button_checked() if self.snr_methods is None: self.snr_methods = ['Mean-Std', "Sample Correlation Coefficient", "Maximum Likelihood", "Amplitude", "Plus-Minus Averaging", "Response Repetition", "MNE Source", "MNE Frequency"] if self.channels_selected is None: self.channels_selected = self.all_channels_names stats_first_variable = self.get_first_independent_variable_selected() stats_second_variable = self.get_second_independent_variable_selected() self.snr_listener.confirm_button_clicked(self.snr_methods, source_method, read, write, self.channels_selected, stats_first_variable, stats_second_variable)
[docs] def snr_selection_trigger(self): """ Open the multiple selector window. The user can select a multiple pipelines used for the classification. """ title = "Select the SNR methods used for the computation :" all_snr_methods = ['Mean-Std', "Sample Correlation Coefficient", "Maximum Likelihood", "Amplitude", "Plus-Minus Averaging", "Response Repetition", "MNE Source", "MNE Frequency"] self.snr_selector_controller = multipleSelectorController(all_snr_methods, title, box_checked=True, element_type="snr") self.snr_selector_controller.set_listener(self.snr_listener)
[docs] def channels_selection_trigger(self): """ Open the multiple selector window. The user can select multiple channels. """ title = "Select the channels used for the SNR computation :" self.channels_selector_controller = multipleSelectorController(self.all_channels_names, title, box_checked=True, element_type="channels") self.channels_selector_controller.set_listener(self.snr_listener)
[docs] def trial_selection_indexes_trigger(self): """ Open the multiple selector window. The user can select the trials indexes he wants the source estimation to be computed on. """ title = "Select the trial's events used for computing the source estimation:" indexes_list = [str(i+1) for i in range(len(self.event_values))] self.events_selector_controller = multipleSelectorController(indexes_list, title, box_checked=True, element_type="indexes") self.events_selector_controller.set_listener(self.snr_listener)
[docs] def trial_selection_events_trigger(self): """ Open the multiple selector window. The user can select the events he wants the source estimation to be computed on. """ title = "Select the trial's events used for computing the source estimation:" events_ids_list = list(self.event_ids.keys()) self.events_selector_controller = multipleSelectorController(events_ids_list, title, box_checked=True, element_type="events") self.events_selector_controller.set_listener(self.snr_listener)
""" Plots """ # noinspection PyTypeChecker
[docs] @staticmethod def plot_SNRs(first_SNRs, second_SNRs, t_values, SNR_methods): """ Plot the SNRs :param first_SNRs: The SNRs computed over the first independent variable. :type first_SNRs: list of, list of float :param second_SNRs: The SNRs computed over the second independent variable. :type second_SNRs: list of, list of float :param t_values: T-values computed over the SNRs of the two independent variables. :type t_values: list of float :param SNR_methods: SNR methods :type SNR_methods: list of str """ res = [] for i in range(len(first_SNRs)): res.append([]) res[i].append(str(round(np.mean(first_SNRs[i]), 3))) res[i].append(str(round(np.std(first_SNRs[i]), 3))) res[i].append(str(round(np.mean(second_SNRs[i]), 3))) res[i].append(str(round(np.std(second_SNRs[i]), 3))) res[i].append(str(round(t_values[i], 3))) for i in range(len(SNR_methods)): if SNR_methods[i] == "Sample Correlation Coefficient": SNR_methods[i] = "Sample Correlation\nCoefficient" fig, ax = plt.subplots() fig.patch.set_visible(False) # hide axes ax.axis('off') ax.axis('tight') ax.table(cellText=res, rowLabels=SNR_methods, colLabels=['First variable\nSNR mean\nvalue (dB)', 'First variable\nSNR standard\ndeviation (dB)', 'Second variable\nSNR mean\nvalue (dB)', 'Second variable\nSNR standard\ndeviation (dB)', 'P-values'], cellLoc='center', rowLoc='center', colLoc='center', loc='center') fig.tight_layout() plt.show()
""" Utils """
[docs] def check_element_type(self, elements_selected, element_type): if element_type == "snr": self.set_snr_methods_selected(elements_selected) elif element_type == "channels": self.set_channels_selected(elements_selected) elif element_type == "indexes" or element_type == "events": self.set_trials_selected(elements_selected, element_type)
""" Setters """
[docs] def set_listener(self, listener): """ Set the listener to the controller. :param listener: Listener to the controller. :type listener: signalToNoiseRatioController """ self.snr_listener = listener
[docs] def set_snr_methods_selected(self, snr_methods): """ Set the SNR methods selected in the multiple selector window. :param snr_methods: SNR methods selected :type snr_methods: list of str """ self.snr_methods = snr_methods
[docs] def set_channels_selected(self, channels_selected): """ Set the channels selected in the multiple selector window. :param channels_selected: Channels selected. :type channels_selected: list of str """ self.channels_selected = channels_selected
[docs] def set_trials_selected(self, elements_selected, element_type): """ Set the channels selected in the multiple selector window. :param elements_selected: Trials or Events selected. :type elements_selected: list of str :param element_type: Type of the element selected, used in case multiple element selector windows can be open in a window. Can thus distinguish the returned elements. :type element_type: str """ trials_to_use = [] if element_type == "indexes": for trial in elements_selected: trials_to_use.append(int(trial) - 1) # -1 To get index in the list, not "position" elif element_type == "events": # Get ids of the events selected event_ids_selected = [] for event in elements_selected: event_ids_selected.append(self.event_ids[event]) # Get indexes of the trials if their event is selected. for i in range(len(self.event_values)): if self.event_values[i][2] in event_ids_selected: trials_to_use.append(i) self.trials_selected = trials_to_use
""" Getters """
[docs] def get_save_load_button_checked(self): """ Get the values of the save and load buttons. :return: save_data: True if the data must be saved. Otherwise, False. load_data: True if the data must be loaded. Otherwise, False. :rtype: boolean, boolean """ checked_button = self.save_load_buttons.checkedButton() button_id = self.save_load_buttons.id(checked_button) save_data = None load_data = None if button_id == 0: save_data = False load_data = False elif button_id == 1: save_data = True load_data = False elif button_id == 2: save_data = False load_data = True return save_data, load_data
[docs] def get_first_independent_variable_selected(self): """ Get the first independent variable selected by the user. :return: First independent variable selected :rtype: str """ for i in range(1, self.first_independent_variable_layout.count()): # Being at 1 because of the label check_box = self.first_independent_variable_layout.itemAt(i).widget() if check_box.isChecked(): return check_box.text()
[docs] def get_second_independent_variable_selected(self): """ Get the second independent variable selected by the user. :return: Second independent variable selected :rtype: str """ for i in range(1, self.second_independent_variable_layout.count()): # Being at 1 because of the label check_box = self.second_independent_variable_layout.itemAt(i).widget() if check_box.isChecked(): return check_box.text()