Exemple #1
0
class MainWindow(QtGui.QWidget):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.initUI()

    def initUI(self, params=None):

        if params == None:
            self.params = {
                "subjects": [
                    "P03",
                    "P04",
                    "P05",
                    "P06",
                    "P07",
                    "P08",
                    "P09",
                    "eeg_plot0",
                    "eeg_plot1",
                    "eeg_plot2",
                    "eeg_plot3",
                    "eeg_plot4",
                    "eeg_plot5",
                    "eeg_plot6",
                    "eeg_plot7",
                ],
                "channels": ["Cz", "Pz", "Fz"],
                "base_offset": 0,
                "chan_offset": 150,
                "gain": 1,
                "features": ["theta", "alpha", "beta", "means", "kurtosis", "skewness", "svd_entropy"],
                #'features' : ['alpha', 'means', 'entropy',  'kurtosis'],
                "envir": ["luxmetre", "sonometre"],
                "data_repo": "./data/",
                "fe": 256.0,  # Hz
                "featCalc_win_size": 30.0,  # s
                "featCalc_win_overlap": 1.0 / 2,
                "eegView_win_size": 30,  # s
                "feat_offset": 1,  # because feat data are normalized
            }
        self.selected = collections.OrderedDict(
            {
                "subject": "P03",
                "channels": [2, 2, 2],
                "features": [2, 2, 2, 2, 2, 2, 2],
                "feat_chan": "Cz",
                "envir": [2, 2],
            }
        )
        self.last_selected = self.selected.copy()
        # Usefull params
        self.nb_win_EEG_values = self.params["eegView_win_size"] * self.params["fe"]
        print "nb EEG values : ", self.nb_win_EEG_values
        self.EEG_Xpos = np.round(self.nb_win_EEG_values / 2)
        print "EEG_Xpos: ", self.EEG_Xpos
        self.Feat_Xpos = 0

        self.dialogPlotEdit = DialogWindow(self, self.params, self.selected)

        # Main Window and Layout
        self.main_win = QtGui.QWidget()
        self.main_win.setWindowTitle("EEG Super Viewer")
        self.main_win.resize(1200, 1000)
        self.main_layout = QtGui.QGridLayout()
        self.main_win.setLayout(self.main_layout)

        # Graph Properties Options
        self.prop_layout = QtGui.QHBoxLayout()
        # Subject selected
        vb_txt_subject = QtGui.QLabel("Subject selected :")
        self.prop_layout.addWidget(vb_txt_subject)
        subject_combo = QtGui.QComboBox()
        subject_combo.addItems(self.params["subjects"])
        # TODO set combo initial to self.selected['subject']
        self.prop_layout.addWidget(subject_combo)
        self.connect(subject_combo, QtCore.SIGNAL("activated(QString)"), self.change_subject)
        # EEG Time #TODO
        vb_time_EEG = QtGui.QLabel("EEG time :")
        self.prop_layout.addWidget(vb_time_EEG)
        # Edition windows
        self.EditButton = QtGui.QPushButton("Edit Plots properties")
        self.EditButton.clicked.connect(self.on_push_Edit_Button)
        self.prop_layout.addWidget(self.EditButton)
        self.main_layout.addLayout(self.prop_layout, 0, 0)

        # ~ self.dialogPlotEdit = DialogWindow(self, self.params, self.selected)

        # Grapfics window
        self.gWin = pg.GraphicsWindow()
        # ~ self.label = pg.LabelItem(justify='right')
        # ~ self.gWin.addItem(self.label)
        axisEEG = EEGAxis(
            sampling_rate=self.params["fe"], eegView_win_size=self.params["eegView_win_size"], orientation="bottom"
        )
        # eeg_plot and feat_plot are viewbox
        self.eeg_plot = self.gWin.addPlot(row=1, col=0, axisItems={"bottom": axisEEG})
        self.eeg_plot.invertY()
        self.eeg_plot.setMouseEnabled(x=True, y=True)
        ##axis in date
        s_rate = 1 / (self.params["featCalc_win_size"] * self.params["featCalc_win_overlap"])
        print "sample_rate : ", 1 / self.params["featCalc_win_size"]
        axisFeat = DateAxisFeat(rec_datetime0=dt.datetime.now(), sampling_rate=s_rate, orientation="bottom")
        self.feat_plot = self.gWin.addPlot(row=2, col=0, axisItems={"bottom": axisFeat})
        self.feat_plot.setMouseEnabled(x=True, y=True)
        self.main_layout.addWidget(self.gWin, 1, 0)

        # Line EEG : always in the center
        self.vLine_eeg = pg.InfiniteLine(pos=np.round(self.nb_win_EEG_values / 2), angle=90, movable=False)
        self.eeg_plot.addItem(self.vLine_eeg, ignoreBounds=True)
        # Line feat (movable and update EEG view)
        self.vLine_feat = pg.InfiniteLine(pos=self.Feat_Xpos, angle=90, movable=True)
        self.feat_plot.addItem(self.vLine_feat, ignoreBounds=True)
        self.vLine_feat.sigPositionChangeFinished.connect(self.update_cursor_pos)

        # Load and init plots
        self.nbEEGsamples = 0  # updated in loadSubjectdata
        self.nbFeatSamples = 0
        self.env_sigs = 0
        self.loadSubjectdata()
        self.update_eeg_plots()
        self.load_feat_plots()

        self.main_win.show()

    def on_push_Edit_Button(self):
        print "Properties Pushed"
        self.dialogPlotEdit.exec_()

    def on_valid_dialogWindow(self):
        print "validation dialogWindow"
        self.dialogPlotEdit.close()

    def update_cursor_pos(self, evt):
        win = self.params["featCalc_win_size"]
        featCalc_win_overlap = self.params["featCalc_win_overlap"]
        fe = self.params["fe"]
        # Or int, depends how you want to proceed betwen feat dots ?
        self.Feat_Xpos = np.round(self.vLine_feat.value())
        if self.Feat_Xpos < 0:
            self.Feat_Xpos = 0
        if self.Feat_Xpos > self.nbEEGsamples:
            self.Feat_Xpos = self.nbEEGsamples
        print "new feat pos is : ", self.Feat_Xpos  # TODO put it in time
        self.EEG_Xpos = self.Feat_Xpos * (win * featCalc_win_overlap * fe)
        print "new eeg pos is : ", self.EEG_Xpos  # TODO put it in time

        self.update_eeg_plots()

    def load_feat_plots(self):
        nb_feat = len(self.params["features"])
        self.feat_plot.clear()
        for j in range(nb_feat):
            data = self.feat_df[self.params["features"][j]][self.selected["subject"]][
                self.selected["feat_chan"]
            ].values.reshape((self.nbFeatSamples))
            min_feat = min(data)
            max_feat = np.percentile(data, 90)
            data = (data - max_feat) / (max_feat - min_feat) + (nb_feat - j) * self.params["feat_offset"]
            print np.shape(data)[0]
            self.feat_plot.plot(x=range(np.shape(data)[0]), y=data, pen=(j, nb_feat * 1.3))
        self.vLine_feat.setValue(self.Feat_Xpos)
        self.feat_plot.addItem(self.vLine_feat, ignoreBounds=True)
        self.feat_plot.setLimits(yMin=0, yMax=nb_feat + 1)

    def update_eeg_plots(self):
        print "update EEG plots, self.EEG_Xpos is :", self.EEG_Xpos
        # EEG params
        nb_chan = len(self.params["channels"])
        base_offset = self.params["base_offset"]
        chan_offset = self.params["chan_offset"]
        gain = self.params["gain"]

        x0 = np.int(self.EEG_Xpos - self.nb_win_EEG_values / 2)
        x1 = np.int(self.EEG_Xpos + self.nb_win_EEG_values / 2)
        print "x0 : ", x0
        print "x1 : ", x1
        eeg_win = np.empty((x1 - x0))

        # EEG Lines plots
        self.eeg_plot.clear()
        for i, name_chan in enumerate(self.params["channels"]):
            eeg_win = self.eeg_df[name_chan][x0:x1].values * gain + (nb_chan - i) * chan_offset
            self.eeg_plot.plot(eeg_win, pen="g")

        # Update EEG central Line
        self.eeg_plot.addItem(self.vLine_eeg, ignoreBounds=True)

    def change_subject(self, text):
        self.selected["subject"] = str(text)
        print "Patient selected : ", self.selected["subject"]
        self.loadSubjectdata()
        self.update_eeg_plots()
        self.load_feat_plots()

    def loadSubjectdata(self):
        # load eeg data
        print "subject file : ", join(
            self.params["data_repo"], self.selected["subject"], self.selected["subject"] + ".h5"
        )
        eeg_Store = pd.HDFStore(
            join(self.params["data_repo"], self.selected["subject"], self.selected["subject"] + ".h5")
        )
        self.eeg_df = eeg_Store.df

        # load features data
        self.feat_df = {}
        for feat in self.params["features"]:
            print "file : ", join(self.params["data_repo"], feat + ".h5")
            feat_Store = pd.HDFStore(join(self.params["data_repo"], feat + ".h5"))  # read_hdf ??
            self.feat_df[feat] = feat_Store.df.dropna()

        # load environment data
        env_raw = join(self.params["data_repo"], self.selected["subject"], self.selected["subject"] + ".raw")
        env_raw_header = join(self.params["data_repo"], self.selected["subject"], self.selected["subject"] + ".header")
        d = self.read_header(env_raw_header)

        # (re)set params
        self.nbEEGsamples = np.shape(self.eeg_df["Cz"])[0]
        print "size EEG : ", self.nbEEGsamples
        self.nbFeatSamples = np.shape(self.feat_df[self.params["features"][0]])[0]
        print "nb feat samples : ", self.nbFeatSamples
        self.env_sigs = np.fromfile(env_raw, dtype=d["dtype"]).reshape(-1, d["nbvoies"])
        print "size env sigs : ", np.shape(self.env_sigs)[0]
        self.EEG_Xpos = np.round(self.nb_win_EEG_values / 2)
        self.Feat_Xpos = 0

    def read_header(self, header_filename):
        d = {}
        for line in open(header_filename):
            k, v = line.replace("\n", "").replace("\r", "").split(":")
            d[k] = v
        if "frequence" in d:
            d["frequence"] = float(d["frequence"])
        if "dtype" in d:
            d["dtype"] = np.dtype(d["dtype"])
        if "nbvoies" in d:
            d["nbvoies"] = int(d["nbvoies"])
            channelnames = []
            for i in range(d["nbvoies"]):
                channelnames.append(d["nom" + str(i + 1)])
            d["channelnames"] = channelnames
        return d