Пример #1
0
class RTQAWindow(QtWidgets.QWidget):

    def __init__(self, sz, xrange, indBas, indCond, musterInfo, parent=None):
        super().__init__(parent=parent, flags=QtCore.Qt.Window)

        uic.loadUi(utils.get_ui_file('rtqa.ui'), self)

        self._fd = FD(xrange)
        self.names = ['X', 'Y', 'Z', 'Pitch', 'Roll', 'Yaw', 'FD']
        self.indBas = indBas
        self.indCond = indCond
        self.iterBas = 0
        self.iterCond = 0

        self.musterInfo = musterInfo

        self.mcrRadioButton.toggled.connect(self.onRadioButtonStateChanged)

        self.snrplot = pg.PlotWidget(self)
        self.snrplot.setBackground((255, 255, 255))
        self.snrPlot.addWidget(self.snrplot)

        p = self.snrplot.getPlotItem()
        p.setLabel('left', "SNR [a.u.]")
        p.setMenuEnabled(enableMenu=False)
        p.setMouseEnabled(x=False, y=False)
        p.showGrid(x=True, y=True, alpha=1)
        p.installEventFilter(self)
        p.disableAutoRange(axis=pg.ViewBox.XAxis)
        p.setXRange(1, xrange, padding=0.0)

        if not parent.P['isRestingState']:

            self.cnrplot = pg.PlotWidget(self)
            self.cnrplot.setBackground((255, 255, 255))
            self.cnrPlot.addWidget(self.cnrplot)

            p = self.cnrplot.getPlotItem()
            p.setLabel('left', "CNR [a.u.]")
            p.setMenuEnabled(enableMenu=False)
            p.setMouseEnabled(x=False, y=False)
            p.showGrid(x=True, y=True, alpha=1)
            p.installEventFilter(self)
            p.disableAutoRange(axis=pg.ViewBox.XAxis)
            p.setXRange(1, xrange, padding=0.0)

            self.meanplot = pg.PlotWidget(self)
            self.meanplot.setBackground((255, 255, 255))
            self.meanPlot.addWidget(self.meanplot)

            p = self.meanplot.getPlotItem()
            p.setLabel('left', "Mean [a.u.]")
            p.setMenuEnabled(enableMenu=False)
            p.setMouseEnabled(x=False, y=False)
            p.showGrid(x=True, y=True, alpha=1)
            p.installEventFilter(self)
            p.disableAutoRange(axis=pg.ViewBox.XAxis)
            p.setXRange(1, xrange, padding=0.0)

            names = ['ROI_1 rMean', ' bas', ' cond']
            color = [config.STAT_PLOT_COLORS[0], config.ROI_BAS_COLORS[0], config.ROI_COND_COLORS[0]]
            for i in range(sz-1):
                names.append('ROI_' + str(i + 2) + ' rMean')
                names.append(' bas')
                names.append(' cond')
                color = color + [config.STAT_PLOT_COLORS[i + 1]] + [config.ROI_BAS_COLORS[i + 1]] + [config.ROI_COND_COLORS[i + 1]]
            pens = []
            for i in range(sz*3):
                pens = pens + [pg.mkPen(color[i], width=1.2)]
            self.makeRoiPlotLegend(self.labelMean, names, pens)

            self.varplot = pg.PlotWidget(self)
            self.varplot.setBackground((255, 255, 255))
            self.varPlot.addWidget(self.varplot)

            p = self.varplot.getPlotItem()
            p.setLabel('left', "Variance [a.u.]")
            p.setMenuEnabled(enableMenu=False)
            p.setMouseEnabled(x=False, y=False)
            p.showGrid(x=True, y=True, alpha=1)
            p.installEventFilter(self)
            p.disableAutoRange(axis=pg.ViewBox.XAxis)
            p.setXRange(1, xrange, padding=0.0)

            names = ['ROI_1 rVariance', ' bas', ' cond']
            for i in range(sz - 1):
                names.append('ROI_' + str(i + 2) + ' rVariance')
                names.append(' bas')
                names.append(' cond')
            self.makeRoiPlotLegend(self.labelVar, names, pens)

        self.spikes_plot = pg.PlotWidget(self)
        self.spikes_plot.setBackground((255, 255, 255))
        self.spikesPlot.addWidget(self.spikes_plot)

        p = self.spikes_plot.getPlotItem()
        p.setLabel('left', "Amplitude [a.u.]")
        p.setMenuEnabled(enableMenu=False)
        p.setMouseEnabled(x=False, y=False)
        p.showGrid(x=True, y=True, alpha=1)
        p.installEventFilter(self)
        p.disableAutoRange(axis=pg.ViewBox.XAxis)
        p.setXRange(1, xrange, padding=0.0)

        self._plot_translat = pg.PlotWidget(self)
        self._plot_translat.setBackground((255, 255, 255))
        self.tdPlot.addWidget(self._plot_translat)

        p = self._plot_translat.getPlotItem()
        p.setLabel('left', "Amplitude [mm]")
        p.setMenuEnabled(enableMenu=True)
        p.setMouseEnabled(x=False, y=False)
        p.showGrid(x=True, y=True, alpha=1)
        p.installEventFilter(self)
        p.disableAutoRange(axis=pg.ViewBox.XAxis)
        p.setXRange(1, xrange, padding=0.0)
        names = ['Translationals: ']
        pens = [config.PLOT_PEN_COLORS[6]]
        for i in range(3):
            names.append(self.names[i])
            pens.append(config.PLOT_PEN_COLORS[i])

        self.makeRoiPlotLegend(self.tdLabel, names, pens)

        self._plot_rotat = pg.PlotWidget(self)
        self._plot_rotat.setBackground((255, 255, 255))
        self.rdPlot.addWidget(self._plot_rotat)

        p = self._plot_rotat.getPlotItem()
        p.setLabel('left', "Angle [rad]")
        p.setMenuEnabled(enableMenu=True)
        p.setMouseEnabled(x=False, y=False)
        p.showGrid(x=True, y=True, alpha=1)
        p.installEventFilter(self)
        p.disableAutoRange(axis=pg.ViewBox.XAxis)
        p.setXRange(1, xrange, padding=0.0)
        names = ['Rotations: ']
        pens = [config.PLOT_PEN_COLORS[6]]
        for i in range(3):
            names.append(self.names[i+3])
            pens.append(config.PLOT_PEN_COLORS[i + 3])

        self.makeRoiPlotLegend(self.rdLabel, names, pens)

        self._plot_fd = pg.PlotWidget(self)
        self._plot_fd.setBackground((255, 255, 255))
        self.fdPlot.addWidget(self._plot_fd)

        p = self._plot_fd.getPlotItem()
        p.setLabel('left', "FD [mm]")
        p.setMenuEnabled(enableMenu=True)
        p.setMouseEnabled(x=False, y=False)
        p.showGrid(x=True, y=True, alpha=1)
        p.installEventFilter(self)
        p.disableAutoRange(axis=pg.ViewBox.XAxis)
        p.setXRange(1, xrange, padding=0.0)
        names = ['Framewise Displacement']
        pens = [config.PLOT_PEN_COLORS[0]]
        for i in range(len(config.DEFAULT_FD_THRESHOLDS)-1):
            names.append('Threshold ' + str(i+1))
            pens.append(config.PLOT_PEN_COLORS[i + 1])

        self.makeRoiPlotLegend(self.fdLabel, names, pens)

        self.tsCheckBox.setChecked(True)

        self.iteration = 1;
        self.rMean = np.zeros((sz, xrange))
        self.m2 = np.zeros((sz, 1))
        self.rVar = np.zeros((sz, xrange))
        self.rSNR = np.zeros((sz, xrange))
        self.meanBas = np.zeros((sz, xrange))
        self.varBas = np.zeros((sz, xrange))
        self.m2Bas = np.zeros((sz, 1))
        self.meanCond = np.zeros((sz, xrange))
        self.varCond = np.zeros((sz, xrange))
        self.m2Cond = np.zeros((sz, 1))
        self.rCNR = np.zeros((sz, xrange))
        self.glmProcTimeSeries = np.zeros((sz, 1))
        self.posSpikes = dict.fromkeys(['{:d}'.format(x) for x in range(sz)], np.array(0))
        self.negSpikes = dict.fromkeys(['{:d}'.format(x) for x in range(sz)], np.array(0))

        self.currentMode = 0;

    def onComboboxChanged(self):

        state = self.comboBox.currentIndex()

        if state == 0:

            names = ['SNR ']
            pens = [config.PLOT_PEN_COLORS[6]]
            sz = len(self.rSNR)
            for i in range(sz):
                names.append('ROI_' + str(i + 1) + ':  ' + '{0:.3f}'.format(float(self.rSNR[i][self.iteration])))
                pens.append(pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))

            self.makeTextValueLabel(self.valuesLabel, names, pens)

            self.currentMode = 0;

            return
        if state == 1:
            return
        if state == 2:
            self.stackedWidgetOptions.setCurrentIndex(0);

            names = ['СNR ']
            pens = [config.PLOT_PEN_COLORS[6]]
            sz = len(self.rCNR)
            for i in range(sz):
                names.append('ROI_' + str(i + 1) + ':  ' + '{0:.3f}'.format(float(self.rCNR[i][self.iteration])))
                pens.append(pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))

            self.makeTextValueLabel(self.valuesLabel, names, pens)

            self.currentMode = 2;

            return
        if state == 3:
            return
        if state == 4:
            return

    def onRadioButtonStateChanged(self):

        if self.mcrRadioButton.isChecked():
            names = ['Micro Displacement']
            pens = [config.PLOT_PEN_COLORS[0]]
            names.append('Threshold')
            pens.append(config.PLOT_PEN_COLORS[2])

            self.makeRoiPlotLegend(self.fdLabel, names, pens)
        else:
            names = ['Framewise Displacement']
            pens = [config.PLOT_PEN_COLORS[0]]
            for i in range(len(config.DEFAULT_FD_THRESHOLDS)-1):
                names.append('Threshold ' + str(i+1))
                pens.append(config.PLOT_PEN_COLORS[i + 1])

            self.makeRoiPlotLegend(self.fdLabel, names, pens)

        self._fd.draw_mc_plots(self.mcrRadioButton.isChecked(), self._plot_translat, self._plot_rotat, self._plot_fd)

    def makeRoiPlotLegend(self, label, names, pens):
        label.setText('')
        legendText = '<html><head/><body><p>'

        for n, c in zip(names, pens):
            cname = c.color().name()
            legendText += (
                    '<span style="font-weight:600;color:{};">'.format(cname) + '{}</span> '.format(n))

        legendText += '</p></body></html>'

        label.setText(legendText)

    def makeTextValueLabel(self, label, names, pens):

        label.setText('')
        text = '<html><head/><body><p>'
        for n, c in zip(names, pens):
            cname = c.color().name()
            text += (
                    '<span style="font-weight:600;color:{};">'.format(cname) + '{}</span><br>'.format(n))

        text += '</p></body></html>'

        label.setText(text)

    def closeEvent(self, event):
        self.hide()
        event.accept()

    def plot_ts(self, init, plotitem, data):

        if self.tsCheckBox.isChecked():

            sz, l = data.shape

            if init:

                plotitem.clear()
                plots = []

                muster = self.drawMusterPlot(plotitem)

                for i, c in zip(range(sz), config.ROI_PLOT_COLORS):
                    pen = pg.mkPen(color=c, width=config.ROI_PLOT_WIDTH)
                    p = plotitem.plot(pen=pen)
                    plots.append(p)

                self.plot_ts.__dict__[plotitem] = plots, muster

            x = np.arange(1, l+1, dtype=np.float64)

            for p, y in zip(self.plot_ts.__dict__[plotitem][0], data):
                p.setData(x=x, y=np.array(y))

            items = plotitem.listDataItems()

            for m in self.plot_ts.__dict__[plotitem][1]:
                items.remove(m)

            if data.any():
                plotitem.setYRange(np.min(data), np.max(data), padding=0.0)

    def plot_rtQA(self, init, n):

        plotitem = self.snrplot.getPlotItem()
        data = self.rSNR[:, 0:n]
        self.plot_ts(init, plotitem, data)

        if self.comboBox.model().item(2).isEnabled():
            plotitem = self.cnrplot.getPlotItem()
            data = self.rCNR[:, 0:n]
            self.plot_ts(init, plotitem, data)

            plotitem = self.meanplot.getPlotItem()
            data = np.append(self.rMean[:, 0:n], self.meanBas[:, 0:n], axis=0)
            data = np.append(data, self.meanCond[:, 0:n], axis=0)
            m = len(self.rSNR[:, 1])
            color = config.STAT_PLOT_COLORS[0:m] + config.ROI_BAS_COLORS[0:m] + config.ROI_COND_COLORS[0:m]
            style = [QtCore.Qt.SolidLine, QtCore.Qt.DashLine, QtCore.Qt.DashLine]
            self.plot_rStatValues(init, plotitem, data, color, style)

            plotitem = self.varplot.getPlotItem()
            data = np.append(self.rVar[:, 0:n], self.varBas[:, 0:n], axis=0)
            data = np.append(data, self.varCond[:, 0:n], axis=0)
            self.plot_rStatValues(init, plotitem, data, color, style)

    def plot_rStatValues(self, init, plotitem, data, color, style):

        if self.tsCheckBox.isChecked():

            sz, l = data.shape

            if init:

                plotitem.clear()
                plots = []

                muster = self.drawMusterPlot(plotitem)

                style = np.repeat(style, sz/3)

                for i, c, s in zip(range(sz), color, style):
                    pen = pg.mkPen(c, width=3.0, style=QtCore.Qt.PenStyle(s))
                    p = plotitem.plot(pen=pen)
                    plots.append(p)

                self.plot_ts.__dict__[plotitem] = plots, muster

            x = np.arange(1, l+1, dtype=np.float64)

            for p, y in zip(self.plot_ts.__dict__[plotitem][0], data):
                p.setData(x=x, y=np.array(y))

            items = plotitem.listDataItems()

            for m in self.plot_ts.__dict__[plotitem][1]:
                items.remove(m)

            if data.any():
                plotitem.setYRange(np.min(data[np.nonzero(data)]), np.max(data), padding=0.0)

    def drawMusterPlot(self, plotitem):
        ylim = config.MUSTER_Y_LIMITS

        if self.comboBox.model().item(2).isEnabled():
            muster = [
                plotitem.plot(x=self.musterInfo['xCond1'],
                              y=self.musterInfo['yCond1'],
                              fillLevel=ylim[0],
                              pen=config.MUSTER_PEN_COLORS[0],
                              brush=config.MUSTER_BRUSH_COLORS[0]),

                plotitem.plot(x=self.musterInfo['xCond2'],
                              y=self.musterInfo['yCond2'],
                              fillLevel=ylim[0],
                              pen=config.MUSTER_PEN_COLORS[1],
                              brush=config.MUSTER_BRUSH_COLORS[1]),
            ]

            if ("xCond3" in self.musterInfo) and (self.musterInfo['xCond3'][0] != -1):
                muster.append(
                    plotitem.plot(x=self.musterInfo['xCond3'],
                                  y=self.musterInfo['yCond3'],
                                  fillLevel=ylim[0],
                                  pen=config.MUSTER_PEN_COLORS[2],
                                  brush=config.MUSTER_BRUSH_COLORS[2])
                )
        else:
            muster = [
                plotitem.plot(x=[1, self._fd.xmax],
                              y=[-1000, 1000],
                              fillLevel=ylim[0],
                              pen=config.MUSTER_PEN_COLORS[3],
                              brush=config.MUSTER_BRUSH_COLORS[3])
            ]

        return muster

    def calculate_snr(self, data, iteration):
        sz = data.size
        snr = np.zeros((sz, 1))
        n = iteration

        variance = self.rVar[:, n-1]
        mean = self.rMean[:, n-1]
        m2 = self.m2

        meanPrev = mean

        if n:

            for i in range(sz):
                mean[i] = mean[i] + (data[i] - mean[i]) / n
                if n == 1:
                    variance[i] = 0
                else:
                    m2[i] = m2[i] + (data[i] - meanPrev[i]) * (data[i] - mean[i])
                    variance[i] = m2[i] / (n - 1)
                if variance[i] == 0:
                    snr[i] = 0
                else:
                    snr[i] = mean[i] / (variance[i] ** (.5))

        else:

            mean = data

        self.rMean[:, n] = mean
        self.m2 = m2
        self.rVar[:, n] = variance
        if iteration < 8:
            snr = np.zeros((sz, 1))
        for i in range(sz):
            self.rSNR[i][n] = snr[i]

        if not self.comboBox.currentIndex():

            names = ['SNR ']
            pens = [config.PLOT_PEN_COLORS[6]]
            for i in range(sz):
                names.append('ROI_' + str(i + 1) + ': ' + '{0:.3f}'.format(float(snr[i])))
                pens.append(pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))

            self.makeTextValueLabel(self.valuesLabel, names, pens)

        self.iteration = n;

    def calculate_cnr(self, data, indexVolume):

        sz = data.size

        if indexVolume in self.indBas:
            if not self.iterBas:
                self.meanBas[:, indexVolume] = data
                self.varBas[:, indexVolume] = np.zeros(sz)
                self.iterBas += 1

            else:

                self.iterBas += 1

                for i in range(sz):
                    self.meanBas[i, indexVolume] = self.meanBas[i, indexVolume-1] + (data[i] - self.meanBas[i,indexVolume-1]) / self.iterBas
                    self.m2Bas[i] = self.m2Bas[i] + (data[i] - self.meanBas[i, indexVolume-1]) * (data[i] - self.meanBas[i, indexVolume])
                    self.varBas[i, indexVolume] = self.m2Bas[i] / (self.iterBas - 1)

        else:

            self.meanBas[:, indexVolume] = self.meanBas[:, indexVolume-1]
            self.varBas[:, indexVolume] = self.varBas[:, indexVolume-1]

        if indexVolume in self.indCond:

            if not self.iterCond:
                self.meanCond[:, indexVolume] = data
                self.varCond[:, indexVolume] = np.zeros(sz)
                self.iterCond += 1

            else:

                self.iterCond += 1

                for i in range(sz):
                    self.meanCond[i, indexVolume] = self.meanCond[i, indexVolume-1] + (data[i] - self.meanCond[i, indexVolume-1]) / self.iterCond
                    self.m2Cond[i] = self.m2Cond[i] + (data[i] - self.meanCond[i, indexVolume-1]) * (data[i] - self.meanCond[i, indexVolume])
                    self.varCond[i, indexVolume] = self.m2Cond[i] / (self.iterCond - 1)

        else:

            self.meanCond[:, indexVolume] = self.meanCond[:, indexVolume - 1]
            self.varCond[:, indexVolume] = self.varCond[:, indexVolume - 1]

        if self.iterCond:

            for i in range(sz):
                self.rCNR[i, indexVolume] = (self.meanCond[i, indexVolume] - self.meanBas[i, indexVolume]) / (np.sqrt(self.varCond[i, indexVolume] + self.varBas[i, indexVolume]))

            if self.comboBox.currentIndex() == 2:

                names = ['СNR ']
                pens = [config.PLOT_PEN_COLORS[6]]
                for i in range(sz):
                    names.append('ROI_' + str(i + 1) + ': ' + '{0:.3f}'.format(float(self.rCNR[i][indexVolume-1])))
                    pens.append(pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))

                self.makeTextValueLabel(self.valuesLabel, names, pens)

    def plot_mcmd(self, data):

        self._fd.calc_mc_plots(data)
        self._fd.draw_mc_plots(self.mcrRadioButton.isChecked(), self._plot_translat, self._plot_rotat, self._plot_fd)
        names = ['<u>FD</u> ']
        pens = [config.PLOT_PEN_COLORS[6]]
        names.append('Threshold 1: ' + str(int(self._fd.excFD[0])))
        pens.append(config.PLOT_PEN_COLORS[1])
        names.append('Threshold 2: ' + str(int(self._fd.excFD[1])))
        pens.append(config.PLOT_PEN_COLORS[2])
        names.append('<br><u>MD</u> ')
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('Threshold: ' + str(int(self._fd.excVD)))
        pens.append(config.PLOT_PEN_COLORS[2])
        names.append('<br><u>Mean FD</u> ')
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('{0:.3f}'.format(self._fd.meanFD))
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('<br><u>Mean MD</u> ')
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('{0:.3f}'.format(self._fd.meanMD))
        pens.append(config.PLOT_PEN_COLORS[6])
        self.makeTextValueLabel(self.mcmdValuesLabel, names, pens)

    def plot_stepsAndSpikes(self, data, posSpike, negSpike):

        self.glmProcTimeSeries = np.append(self.glmProcTimeSeries, data, axis=1)
        sz, l = self.glmProcTimeSeries.shape

        for i in range(sz):
            if posSpike[i] == 1:
                if self.posSpikes[str(i)].any():
                    self.posSpikes[str(i)] = np.append(self.posSpikes[str(i)], l-1)
                else:
                    self.posSpikes[str(i)] = np.array([l-1])
            if negSpike[i] == 1:
                if self.negSpikes[str(i)].any():
                    self.negSpikes[str(i)] = np.append(self.negSpikes[str(i)], l-1)
                else:
                    self.negSpikes[str(i)] = np.array([l-1])

        x = np.arange(0, l, dtype=np.float64)

        plotitem = self.spikes_plot.getPlotItem()
        plotitem.clear()
        plots = []

        muster = self.drawMusterPlot(plotitem)

        for i, c in zip(range(sz), config.ROI_PLOT_COLORS):
            pen = pg.mkPen(color=c, width=config.ROI_PLOT_WIDTH)
            p = plotitem.plot(pen=pen)
            plots.append(p)

        self.plot_stepsAndSpikes.__dict__[plotitem] = plots, muster

        for p, y in zip(self.plot_stepsAndSpikes.__dict__[plotitem][0], self.glmProcTimeSeries):
            p.setData(x=x, y=np.array(y))

        for i, c in zip(range(sz), config.ROI_PLOT_COLORS):

            if self.posSpikes[str(i)].any():
                brush = pg.mkBrush(color=c)
                p = plotitem.scatterPlot(symbol='o', size=20, brush=brush)
                plots.append(p)
                plots[-1].setData(x=x[self.posSpikes[str(i)]], y=self.glmProcTimeSeries[i, self.posSpikes[str(i)]])

                pen = pg.mkPen(color=pg.mkColor(0, 0, 0), width=1.5*config.ROI_PLOT_WIDTH)
                p = plotitem.plot(pen=pen)
                plots.append(p)

                inds = self.posSpikes[str(i)]
                inds = np.array(list(itertools.chain.from_iterable(zip(inds, inds-1))))

                y = np.array(self.glmProcTimeSeries[i,inds])
                x1 = inds

                plots[-1].setData(x=x1, y=y, connect='pairs')

            if self.negSpikes[str(i)].any():
                brush = pg.mkBrush(color=c)
                p = plotitem.scatterPlot(symbol='d', size=20, brush=brush)
                plots.append(p)
                plots[-1].setData(x=x[self.negSpikes[str(i)]], y=self.glmProcTimeSeries[i, self.negSpikes[str(i)]])

                pen = pg.mkPen(color=pg.mkColor(0, 0, 0), width=1.5*config.ROI_PLOT_WIDTH)
                p = plotitem.plot(pen=pen)
                plots.append(p)

                inds = self.negSpikes[str(i)]
                inds = np.array(list(itertools.chain.from_iterable(zip(inds, inds - 1))))

                y = np.array(self.glmProcTimeSeries[i,inds])
                x1 = inds

                plots[-1].setData(x=x1, y=y, connect='pairs')

        cnt = 0;
        for i in range(sz):
            cnt = cnt + np.count_nonzero(self.posSpikes[str(i)])
        names = ['( Circles ) <br>Positive spikes: ' + str(int(cnt))]

        cnt = 0;
        for i in range(sz):
            cnt = cnt + np.count_nonzero(self.negSpikes[str(i)])
        names.append('<br>( Diamonds )<br>Negative spikes: ' + str(int(cnt)))
        pens = [pg.mkPen(color=config.STAT_PLOT_COLORS[9], width=1.2), pg.mkPen(color=config.STAT_PLOT_COLORS[9], width=1.2)]
        self.makeTextValueLabel(self.spikesLabel, names, pens)

        items = plotitem.listDataItems()

        for m in self.plot_stepsAndSpikes.__dict__[plotitem][1]:
            items.remove(m)

        if data.any():
            plotitem.setYRange(np.min(self.glmProcTimeSeries)-1, np.max(self.glmProcTimeSeries)+1, padding=0.0)

    def data_packing(self):

        tsRTQA = dict.fromkeys(['rMean', 'rVar', 'rSNR',
                                'meanBas', 'varBas', 'meanCond', 'varCond', 'rCNR',
                                'excFDIndexes_1', 'excFDIndexes_2', 'excMDIndexes', 'FD', 'MD'])

        tsRTQA['rMean'] = matlab.double(self.rMean.tolist())
        tsRTQA['rVar'] = matlab.double(self.rVar.tolist())
        tsRTQA['rSNR'] = matlab.double(self.rSNR.tolist())
        tsRTQA['meanBas'] = matlab.double(self.meanBas.tolist())
        tsRTQA['varBas'] = matlab.double(self.varBas.tolist())
        tsRTQA['meanCond'] = matlab.double(self.meanCond.tolist())
        tsRTQA['varCond'] = matlab.double(self.varCond.tolist())
        tsRTQA['rCNR'] = matlab.double(self.rCNR.tolist())
        tsRTQA['excFDIndexes_1'] = matlab.double(self._fd.excFDIndexes_1.tolist())
        tsRTQA['excFDIndexes_2'] = matlab.double(self._fd.excFDIndexes_2.tolist())
        tsRTQA['excMDIndexes'] = matlab.double(self._fd.excMDIndexes.tolist())
        tsRTQA['FD'] = matlab.double(self._fd.FD.tolist())
        tsRTQA['MD'] = matlab.double(self._fd.MD.tolist())

        return tsRTQA
Пример #2
0
class RTQAWindow(QtWidgets.QWidget):
    """Real-time quality assessment GUI and methods application class
    """

    # --------------------------------------------------------------------------
    def __init__(self, parent=None):
        super().__init__(parent=parent, flags=QtCore.Qt.Window)

        uic.loadUi(utils.get_ui_file('rtqa.ui'), self)

        # parent data transfer block
        sz = int(parent.P['NrROIs'])
        if parent.P['isRestingState']:
            xrange = (parent.P['NrOfVolumes'] - parent.P['nrSkipVol'])
            self.comboBox.model().item(2).setEnabled(False)
            self.indBas = 0
            self.indCond = 0
        else:
            parent.computeMusterPlotData(config.MUSTER_Y_LIMITS)
            xrange = max(parent.musterInfo['tmpCond1'][-1][1],
                         parent.musterInfo['tmpCond2'][-1][1])
            self.indBas = np.array(parent.P['inds'][0]) - 1
            self.indCond = np.array(parent.P['inds'][1]) - 1

        # main class data initialization block
        self._fd = FD(xrange)
        self.names = ['X', 'Y', 'Z', 'Pitch', 'Roll', 'Yaw', 'FD']
        self.iterBas = 0
        self.iterCond = 0
        self.init = True
        self.isStopped = True
        self.iteration = 1
        self.blockIter = 0
        self.rMean = np.zeros((sz, xrange))
        self.m2 = np.zeros((sz, 1))
        self.rVar = np.zeros((sz, xrange))
        self.rSNR = np.zeros((sz, xrange))
        self.meanBas = np.zeros((sz, xrange))
        self.varBas = np.zeros((sz, xrange))
        self.m2Bas = np.zeros((sz, 1))
        self.meanCond = np.zeros((sz, xrange))
        self.varCond = np.zeros((sz, xrange))
        self.m2Cond = np.zeros((sz, 1))
        self.rCNR = np.zeros((sz, xrange))
        self.glmProcTimeSeries = np.zeros((sz, xrange))
        self.posSpikes = dict.fromkeys(['{:d}'.format(x) for x in range(sz)],
                                       np.array(0))
        self.negSpikes = dict.fromkeys(['{:d}'.format(x) for x in range(sz)],
                                       np.array(0))
        self.rMSE = np.zeros((sz, xrange))
        self.linTrendCoeff = np.zeros((sz, xrange))
        self.checkedBoxesInd = []
        self.currentMode = 0

        # Additional GUI elements connection and initialization
        groupBoxLayout = self.roiGroupBox.layout()
        for i in range(sz):
            checkbox = QtWidgets.QCheckBox('ROI_' + str(i + 1))
            checkbox.setStyleSheet("color: " +
                                   config.ROI_PLOT_COLORS[i].name())
            if not i:
                checkbox.setChecked(True)
            checkbox.stateChanged.connect(self.roiCheckBoxStateChanged)
            groupBoxLayout.addWidget(checkbox)
        self.roiCheckBoxes = self.roiGroupBox.findChildren(QtWidgets.QCheckBox)
        self.musterInfo = parent.musterInfo
        self.mcrRadioButton.toggled.connect(self.onRadioButtonStateChanged)

        # Plots initialization
        self.snrPlot = pg.PlotWidget(self)
        self.snrPlot.setBackground((255, 255, 255))
        self.snrPlotLayout.addWidget(self.snrPlot)
        p = self.snrPlot.getPlotItem()
        self.plotsSetup(p, "SNR [a.u.]", xrange)
        self.drawMusterPlot(p)
        p.setYRange(-1, 1, padding=0.0)

        self.msePlot = pg.PlotWidget(self)
        self.msePlot.setBackground((255, 255, 255))
        self.msePlotLayout.addWidget(self.msePlot)
        p = self.msePlot.getPlotItem()
        self.plotsSetup(p, "Mean squared error [a.u.]", xrange)
        self.drawMusterPlot(p)
        p.setYRange(-1, 1, padding=0.0)

        self.trendPlot = pg.PlotWidget(self)
        self.trendPlot.setBackground((255, 255, 255))
        self.linearTreandPlotLayout.addWidget(self.trendPlot)
        p = self.trendPlot.getPlotItem()
        self.plotsSetup(p, "Beta regressor amplitude [a.u.]", xrange)
        self.drawMusterPlot(p)
        p.setYRange(-1, 1, padding=0.0)

        self.fdPlot = pg.PlotWidget(self)
        self.fdPlot.setBackground((255, 255, 255))
        self.fdPlotLayout.addWidget(self.fdPlot)
        p = self.fdPlot.getPlotItem()
        self.plotsSetup(p, "FD [mm]", xrange)

        self.translatPlot = pg.PlotWidget(self)
        self.translatPlot.setBackground((255, 255, 255))
        self.tdPlotLayout.addWidget(self.translatPlot)
        p = self.translatPlot.getPlotItem()
        self.plotsSetup(p, "Amplitude [mm]", xrange)

        self.rotatPlot = pg.PlotWidget(self)
        self.rotatPlot.setBackground((255, 255, 255))
        self.rdPlotLayout.addWidget(self.rotatPlot)
        p = self.rotatPlot.getPlotItem()
        self.plotsSetup(p, "Amplitude [mm]", xrange)

        self.spikesPlot = pg.PlotWidget(self)
        self.spikesPlot.setBackground((255, 255, 255))
        self.spikesPlotLayout.addWidget(self.spikesPlot)
        p = self.spikesPlot.getPlotItem()
        self.plotsSetup(p, "Amplitude [a.u.]", xrange)
        self.drawMusterPlot(p)
        p.setYRange(-1, 1, padding=0.0)

        # CNR, means and variances plots and labels
        if not parent.P['isRestingState']:

            self.cnrPlot = pg.PlotWidget(self)
            self.cnrPlot.setBackground((255, 255, 255))
            self.cnrPlotLayout.addWidget(self.cnrPlot)
            p = self.cnrPlot.getPlotItem()
            self.plotsSetup(p, "CNR [a.u.]", xrange)
            self.drawMusterPlot(p)
            p.setYRange(-1, 1, padding=0.0)

            self.meanPlot = pg.PlotWidget(self)
            self.meanPlot.setBackground((255, 255, 255))
            self.meanPlotLayout.addWidget(self.meanPlot)
            p = self.meanPlot.getPlotItem()
            self.plotsSetup(p, "Mean [a.u.]", xrange)
            self.drawMusterPlot(p)
            p.setYRange(-1, 1, padding=0.0)

            self.varPlot = pg.PlotWidget(self)
            self.varPlot.setBackground((255, 255, 255))
            self.varPlotLayout.addWidget(self.varPlot)
            p = self.varPlot.getPlotItem()
            self.plotsSetup(p, "Variance [a.u.]", xrange)
            self.drawMusterPlot(p)
            p.setYRange(-1, 1, padding=0.0)

            names = ['ROI_1 rMean', ' bas', ' cond']
            color = [
                config.STAT_PLOT_COLORS[0], config.ROI_BAS_COLORS[0],
                config.ROI_COND_COLORS[0]
            ]
            for i in range(sz - 1):
                names.append('ROI_' + str(i + 2) + ' rMean')
                names.append(' bas')
                names.append(' cond')
                color = color + [config.STAT_PLOT_COLORS[i + 1]] + [
                    config.ROI_BAS_COLORS[i + 1]
                ] + [config.ROI_COND_COLORS[i + 1]]
            pens = []
            for i in range(sz * 3):
                pens = pens + [pg.mkPen(color[i], width=1.2)]
            self.makeTextValueLabel(self.labelMean, names, pens)

            names = ['ROI_1 rVariance', ' bas', ' cond']
            for i in range(sz - 1):
                names.append('ROI_' + str(i + 2) + ' rVariance')
                names.append(' bas')
                names.append(' cond')
            self.makeTextValueLabel(self.labelVar, names, pens)

        # Other labels initialization
        names = ['Translationals: ']
        pens = [config.PLOT_PEN_COLORS[6]]
        for i in range(3):
            names.append(self.names[i])
            pens.append(config.PLOT_PEN_COLORS[i])
        self.makeTextValueLabel(self.tdLabel, names, pens)

        names = ['Rotations: ']
        pens = [config.PLOT_PEN_COLORS[6]]
        for i in range(3):
            names.append(self.names[i + 3])
            pens.append(config.PLOT_PEN_COLORS[i + 3])
        self.makeTextValueLabel(self.rdLabel, names, pens)

        names = ['Framewise Displacement']
        pens = [config.PLOT_PEN_COLORS[0]]
        for i in range(len(config.DEFAULT_FD_THRESHOLDS) - 1):
            names.append('Threshold ' + str(i + 1))
            pens.append(config.PLOT_PEN_COLORS[i + 1])
        self.makeTextValueLabel(self.fdLabel, names, pens)

    # --------------------------------------------------------------------------
    def closeEvent(self, event):

        self.hide()
        event.accept()

    # --------------------------------------------------------------------------
    def plotsSetup(self, p, yName, xrange):

        p.setLabel('left', yName)
        p.setMenuEnabled(enableMenu=False)
        p.setMouseEnabled(x=False, y=False)
        p.showGrid(x=True, y=True, alpha=1)
        p.installEventFilter(self)
        p.disableAutoRange(axis=pg.ViewBox.XAxis)
        p.setXRange(1, xrange, padding=0.0)

    # --------------------------------------------------------------------------
    def onComboboxChanged(self):
        """  SNR/CNR label switching. Both modes use the same label
        """

        state = self.comboBox.currentIndex()

        # SNR state
        if state == 0:

            names = ['SNR ']
            pens = [config.PLOT_PEN_COLORS[6]]
            sz = len(self.rSNR)
            for i in range(sz):
                names.append(
                    'ROI_' + str(i + 1) + ':  ' +
                    '{0:.3f}'.format(float(self.rSNR[i][self.iteration])))
                pens.append(
                    pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))
            self.makeTextValueLabel(self.valuesLabel,
                                    names,
                                    pens,
                                    lineBreak='<br>')
            self.currentMode = 0

        # CNR state
        elif state == 2:

            self.stackedWidgetOptions.setCurrentIndex(0)

            names = ['СNR ']
            pens = [config.PLOT_PEN_COLORS[6]]
            sz = len(self.rCNR)
            for i in range(sz):
                names.append(
                    'ROI_' + str(i + 1) + ':  ' +
                    '{0:.3f}'.format(float(self.rCNR[i][self.iteration])))
                pens.append(
                    pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))
            self.makeTextValueLabel(self.valuesLabel,
                                    names,
                                    pens,
                                    lineBreak='<br>')
            self.currentMode = 2

    # --------------------------------------------------------------------------
    def onRadioButtonStateChanged(self):
        """ FD and MD mode change. Mode changing switch plots and plot title
        """

        if self.mcrRadioButton.isChecked():
            names = ['Micro Displacement']
            pens = [config.PLOT_PEN_COLORS[0]]
            names.append('Threshold')
            pens.append(config.PLOT_PEN_COLORS[2])
            self.makeTextValueLabel(self.fdLabel, names, pens)

        else:
            names = ['Framewise Displacement']
            pens = [config.PLOT_PEN_COLORS[0]]
            for i in range(len(config.DEFAULT_FD_THRESHOLDS) - 1):
                names.append('Threshold ' + str(i + 1))
                pens.append(config.PLOT_PEN_COLORS[i + 1])
            self.makeTextValueLabel(self.fdLabel, names, pens)

        self._fd.draw_mc_plots(self.mcrRadioButton.isChecked(),
                               self.translatPlot, self.rotatPlot, self.fdPlot)

    # --------------------------------------------------------------------------
    def makeTextValueLabel(self, label, names, pens, lineBreak=' '):
        """ Dynamic generation of titles and value labels

        :param label: label for text update
        :param names: set of names
        :param pens: set of pens for each name
        :param lineBreak: line break for value labels, space by default for title labels
        """

        label.setText('')
        legendText = '<html><head/><body><p>'

        for n, c in zip(names, pens):
            cname = c.color().name()
            legendText += (
                '<span style="font-weight:600;color:{};">'.format(cname) +
                '{}</span>'.format(n) + lineBreak)

        legendText += '</p></body></html>'

        label.setText(legendText)

    # --------------------------------------------------------------------------
    def roiCheckBoxStateChanged(self):
        """ Redrawing plots when the set of selected ROIs is changed even if run is stopped
        """

        self.init = True
        if self.isStopped:
            self.plotRTQA(self.rSNR.size)

    # --------------------------------------------------------------------------
    def drawMusterPlot(self, plotitem):

        ylim = config.MUSTER_Y_LIMITS

        if self.comboBox.model().item(2).isEnabled():
            muster = [
                plotitem.plot(x=self.musterInfo['xCond1'],
                              y=self.musterInfo['yCond1'],
                              fillLevel=ylim[0],
                              pen=config.MUSTER_PEN_COLORS[0],
                              brush=config.MUSTER_BRUSH_COLORS[0]),
                plotitem.plot(x=self.musterInfo['xCond2'],
                              y=self.musterInfo['yCond2'],
                              fillLevel=ylim[0],
                              pen=config.MUSTER_PEN_COLORS[1],
                              brush=config.MUSTER_BRUSH_COLORS[1]),
            ]

            if ("xCond3" in self.musterInfo) and (self.musterInfo['xCond3'][0]
                                                  != -1):
                muster.append(
                    plotitem.plot(x=self.musterInfo['xCond3'],
                                  y=self.musterInfo['yCond3'],
                                  fillLevel=ylim[0],
                                  pen=config.MUSTER_PEN_COLORS[2],
                                  brush=config.MUSTER_BRUSH_COLORS[2]))
        else:
            muster = [
                plotitem.plot(x=[1, self._fd.xmax],
                              y=[-1000, 1000],
                              fillLevel=ylim[0],
                              pen=config.MUSTER_PEN_COLORS[3],
                              brush=config.MUSTER_BRUSH_COLORS[3])
            ]

        return muster

    # --------------------------------------------------------------------------
    def plotTs(self, init, plotitem, data, checkedBoxesInd):
        """ Time-series plot method

        :param init: flag for plot initializtion
        :param plotitem: time-series plotitem
        :param data: time-series value for drawing
        :param checkedBoxesInd: indexes of selected ROIs
        """

        if self.tsCheckBox.isChecked():

            sz, l = data.shape

            if init:

                plotitem.clear()
                plots = []

                muster = self.drawMusterPlot(plotitem)

                for i, c in zip(
                        range(sz),
                        np.array(config.ROI_PLOT_COLORS)[checkedBoxesInd]):
                    pen = pg.mkPen(color=c, width=config.ROI_PLOT_WIDTH)
                    p = plotitem.plot(pen=pen)
                    plots.append(p)

                self.plotTs.__dict__[plotitem] = plots, muster

            x = np.arange(1, l + 1, dtype=np.float64)

            plotitems = self.plotTs.__dict__[plotitem][0]
            for p, y in zip(plotitems, data):
                p.setData(x=x, y=np.array(y))

            items = plotitem.listDataItems()

            for m in self.plotTs.__dict__[plotitem][1]:
                items.remove(m)

            if data.any():
                if plotitem.vb.state["targetRange"][1] == [-1, 1]:
                    plotitem.enableAutoRange(enable=True, x=False, y=True)
                plotitem.setYRange(np.min(data), np.max(data), padding=0.0)

    # --------------------------------------------------------------------------
    def plotRTQA(self, n):
        """ Encapsulated plots drawing

        :param n: last volume index
        """

        # The set of active ROIs changing
        if self.init:
            sz, l = self.rSNR.shape
            checkedBoxes = [
                self.roiCheckBoxes[i].isChecked() for i in range(sz)
            ]
            self.checkedBoxesInd = [
                j for j, val in enumerate(checkedBoxes) if val
            ]

        # SNR plot
        plotitem = self.snrPlot.getPlotItem()
        data = self.rSNR[self.checkedBoxesInd, 0:n]
        self.plotTs(self.init, plotitem, data, self.checkedBoxesInd)

        if self.comboBox.model().item(2).isEnabled():

            # CNR plot
            plotitem = self.cnrPlot.getPlotItem()
            data = self.rCNR[self.checkedBoxesInd, 0:n]
            self.plotTs(self.init, plotitem, data, self.checkedBoxesInd)

            # Means plot
            plotitem = self.meanPlot.getPlotItem()
            data = np.append(self.rMean[self.checkedBoxesInd, 0:n],
                             self.meanBas[self.checkedBoxesInd, 0:n],
                             axis=0)
            data = np.append(data,
                             self.meanCond[self.checkedBoxesInd, 0:n],
                             axis=0)
            color = np.array(config.STAT_PLOT_COLORS)[self.checkedBoxesInd]
            color = np.append(
                color,
                np.array(config.ROI_BAS_COLORS)[self.checkedBoxesInd])
            color = np.append(
                color,
                np.array(config.ROI_COND_COLORS)[self.checkedBoxesInd])
            style = [
                QtCore.Qt.SolidLine, QtCore.Qt.DashLine, QtCore.Qt.DashLine
            ]
            self.plotStatValues(self.init, plotitem, data, color, style)

            # Variances plot
            plotitem = self.varPlot.getPlotItem()
            data = np.append(self.rVar[self.checkedBoxesInd, 0:n],
                             self.varBas[self.checkedBoxesInd, 0:n],
                             axis=0)
            data = np.append(data,
                             self.varCond[self.checkedBoxesInd, 0:n],
                             axis=0)
            self.plotStatValues(self.init, plotitem, data, color, style)

        # Spikes plot
        plotitem = self.spikesPlot.getPlotItem()
        data = self.glmProcTimeSeries[self.checkedBoxesInd, 0:n]
        self.plotSpikes(self.init, plotitem, data, self.checkedBoxesInd)

        # Kalman filter MSE plot
        plotitem = self.msePlot.getPlotItem()
        data = self.rMSE[self.checkedBoxesInd, 0:n]
        self.plotTs(self.init, plotitem, data, self.checkedBoxesInd)

        # Linear trend coefficients plot
        plotitem = self.trendPlot.getPlotItem()
        data = self.linTrendCoeff[self.checkedBoxesInd, 0:n]
        self.plotTs(self.init, plotitem, data, self.checkedBoxesInd)

        # Linear trend coefficients value label
        if self.comboBox.currentIndex() == 5:

            names = ['Linear trend beta ']
            pens = [config.PLOT_PEN_COLORS[6]]
            sz = self.linTrendCoeff.shape[0]
            for i in range(sz):
                names.append(
                    'ROI_' + str(i + 1) + ': ' +
                    '{0:.3f}'.format(float(self.linTrendCoeff[i, n - 1])))
                pens.append(
                    pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))
            self.makeTextValueLabel(self.trendLabel,
                                    names,
                                    pens,
                                    lineBreak='<br>')

        self.init = False

    # --------------------------------------------------------------------------
    def plotStatValues(self, init, plotitem, data, color, style):
        """ Drawing method for mean and variance statistics

        :param init: flag for plot initializtion
        :param plotitem: mean or variance plotitem
        :param data: signal values for drawing
        :param color: color of each ROI line
        :param style: style of each ROI line
        """

        if self.tsCheckBox.isChecked():

            sz, l = data.shape

            if init:

                plotitem.clear()
                plots = []

                muster = self.drawMusterPlot(plotitem)

                style = np.repeat(style, sz / 3)

                for i, c, s in zip(range(sz), color, style):
                    pen = pg.mkPen(c, width=3.0, style=QtCore.Qt.PenStyle(s))
                    p = plotitem.plot(pen=pen)
                    plots.append(p)

                self.plotTs.__dict__[plotitem] = plots, muster

            x = np.arange(1, l + 1, dtype=np.float64)

            for p, y in zip(self.plotTs.__dict__[plotitem][0], data):
                p.setData(x=x, y=np.array(y))

            items = plotitem.listDataItems()

            for m in self.plotTs.__dict__[plotitem][1]:
                items.remove(m)

            if data.any():
                plotitem.setYRange(np.min(data[np.nonzero(data)]),
                                   np.max(data),
                                   padding=0.0)

    # --------------------------------------------------------------------------
    def plotDisplacements(self, data, isNewDCMBlock):
        """ Calculation and drawing of Framewise and Micro Displacements

        :param data: motion correction data
        :param isNewDCMBlock: flag of new dcm block
        """

        self._fd.calc_mc_plots(data, isNewDCMBlock)

        self._fd.draw_mc_plots(self.mcrRadioButton.isChecked(),
                               self.translatPlot, self.rotatPlot, self.fdPlot)

        names = ['<u>FD</u> ']
        pens = [config.PLOT_PEN_COLORS[6]]
        names.append('Threshold 1: ' + str(int(self._fd.excFD[0])))
        pens.append(config.PLOT_PEN_COLORS[1])
        names.append('Threshold 2: ' + str(int(self._fd.excFD[1])))
        pens.append(config.PLOT_PEN_COLORS[2])
        names.append('<br><u>MD</u> ')
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('Threshold: ' + str(int(self._fd.excVD)))
        pens.append(config.PLOT_PEN_COLORS[2])
        names.append('<br><u>Mean FD</u> ')
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('{0:.3f}'.format(self._fd.meanFD))
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('<br><u>Mean MD</u> ')
        pens.append(config.PLOT_PEN_COLORS[6])
        names.append('{0:.3f}'.format(self._fd.meanMD))
        pens.append(config.PLOT_PEN_COLORS[6])
        self.makeTextValueLabel(self.mcmdValuesLabel,
                                names,
                                pens,
                                lineBreak='<br>')

    # --------------------------------------------------------------------------
    def plotSpikes(self, init, plotitem, data, checkedBoxesInd):
        """ Spikes plot drawing

        :param init: flag for plot initializtion
        :param plotitem: spikes plotitem
        :param data: signal values for drawing
        :param checkedBoxesInd: indexes of selected ROIs
        """

        # First part - line drawing
        sz, l = data.shape
        x = np.arange(1, l + 1, dtype=np.float64)

        if init:
            plotitem.clear()
            plots = []

            muster = self.drawMusterPlot(plotitem)

            for i, c in zip(range(sz),
                            np.array(config.ROI_PLOT_COLORS)[checkedBoxesInd]):
                pen = pg.mkPen(color=c, width=config.ROI_PLOT_WIDTH)
                p = plotitem.plot(pen=pen)
                plots.append(p)

            self.plotSpikes.__dict__[plotitem] = plots, muster

        plots = self.plotSpikes.__dict__[plotitem][0]
        for p, y in zip(plots, data):
            p.setData(x=x, y=np.array(y))

        # Second part - spikes marking
        for i, c in zip(range(sz),
                        np.array(config.ROI_PLOT_COLORS)[checkedBoxesInd]):

            roiInd = checkedBoxesInd[i]
            if self.posSpikes[str(roiInd)].any():
                brush = pg.mkBrush(color=c)
                p = plotitem.scatterPlot(symbol='o', size=20, brush=brush)
                plots.append(p)
                plots[-1].setData(
                    x=self.posSpikes[str(roiInd)] + 1,
                    y=self.glmProcTimeSeries[roiInd,
                                             self.posSpikes[str(roiInd)]])

                pen = pg.mkPen(color=pg.mkColor(0, 0, 0),
                               width=1.5 * config.ROI_PLOT_WIDTH)
                p = plotitem.plot(pen=pen)
                plots.append(p)

                inds = self.posSpikes[str(roiInd)]
                indX = np.array(
                    list(itertools.chain.from_iterable(zip(inds, inds + 1))))
                indY = np.array(
                    list(itertools.chain.from_iterable(zip(inds - 1, inds))))

                y = np.array(self.glmProcTimeSeries[roiInd, indY])
                x1 = indX

                plots[-1].setData(x=x1, y=y, connect='pairs')

            if self.negSpikes[str(roiInd)].any():
                brush = pg.mkBrush(color=c)
                p = plotitem.scatterPlot(symbol='d', size=20, brush=brush)
                plots.append(p)
                plots[-1].setData(
                    x=self.negSpikes[str(roiInd)] + 1,
                    y=self.glmProcTimeSeries[roiInd,
                                             self.negSpikes[str(roiInd)]])

                pen = pg.mkPen(color=pg.mkColor(0, 0, 0),
                               width=1.5 * config.ROI_PLOT_WIDTH)
                p = plotitem.plot(pen=pen)
                plots.append(p)

                inds = self.negSpikes[str(roiInd)]
                indX = np.array(
                    list(itertools.chain.from_iterable(zip(inds, inds + 1))))
                indY = np.array(
                    list(itertools.chain.from_iterable(zip(inds - 1, inds))))

                y = np.array(self.glmProcTimeSeries[roiInd, indY])
                x1 = indX

                plots[-1].setData(x=x1, y=y, connect='pairs')

        items = plotitem.listDataItems()

        for m in self.plotSpikes.__dict__[plotitem][1]:
            items.remove(m)

        if data.any():
            plotitem.setYRange(np.min(self.glmProcTimeSeries) - 1,
                               np.max(self.glmProcTimeSeries) + 1,
                               padding=0.0)

        # number of spikes label
        sz, l = self.glmProcTimeSeries.shape
        cnt = 0
        for i in range(sz):
            cnt = cnt + np.count_nonzero(self.posSpikes[str(i)])
        names = ['( Circles ) <br>Positive spikes: ' + str(int(cnt))]

        cnt = 0
        for i in range(sz):
            cnt = cnt + np.count_nonzero(self.negSpikes[str(i)])
        names.append('<br>( Diamonds )<br>Negative spikes: ' + str(int(cnt)))
        pens = [
            pg.mkPen(color=config.STAT_PLOT_COLORS[9], width=1.2),
            pg.mkPen(color=config.STAT_PLOT_COLORS[9], width=1.2)
        ]
        self.makeTextValueLabel(self.spikesLabel,
                                names,
                                pens,
                                lineBreak='<br>')

    # --------------------------------------------------------------------------
    def calculateSNR(self, data, indexVolume, isNewDCMBlock):
        """ Recursive time-series SNR calculation

        :param data: new value of raw time-series
        :param indexVolume: current volume index
        :param isNewDCMBlock: flag of new dcm block
        :return: calculated SNR are written in RTQA class
        """

        sz = data.size
        if isNewDCMBlock:
            self.blockIter = 0

        if self.blockIter:

            for i in range(sz):
                self.rMean[i, indexVolume] = self.rMean[i, indexVolume - 1] + (
                    data[i] -
                    self.rMean[i, indexVolume - 1]) / (self.blockIter + 1)
                self.m2[i] = self.m2[i] + (
                    data[i] - self.rMean[i, indexVolume - 1]) * (
                        data[i] - self.rMean[i, indexVolume])
                self.rVar[i, indexVolume] = self.m2[i] / self.blockIter
                self.rSNR[i, indexVolume] = self.rMean[i, indexVolume] / (
                    self.rVar[i, indexVolume]**(.5))

            self.blockIter += 1

        else:

            self.rVar[:, indexVolume] = np.zeros((sz, ))
            self.m2 = np.zeros((sz, ))
            self.rMean[:, indexVolume] = data
            self.blockIter = 1

        if self.blockIter < 8:
            self.rSNR[:, indexVolume] = np.zeros((sz, ))

        if not self.comboBox.currentIndex():

            names = ['SNR ']
            pens = [config.PLOT_PEN_COLORS[6]]
            for i in range(sz):
                names.append('ROI_' + str(i + 1) + ': ' +
                             '{0:.3f}'.format(float(self.rSNR[i,
                                                              indexVolume])))
                pens.append(
                    pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))

            self.makeTextValueLabel(self.valuesLabel,
                                    names,
                                    pens,
                                    lineBreak='<br>')

        self.iteration = indexVolume

    # --------------------------------------------------------------------------
    def calculateCNR(self, data, indexVolume, isNewDCMBlock):
        """ Recursive time-series CNR calculation

        :param data: new value of raw time-series
        :param indexVolume: current volume index
        :param isNewDCMBlock: flag of new dcm block
        :return: calculated CNR are written in RTQA class
        """

        sz = data.size

        if isNewDCMBlock:
            self.iterBas = 0
            self.iterCond = 0
            return

        if indexVolume in self.indBas:
            if not self.iterBas:
                self.meanBas[:, indexVolume] = data
                self.varBas[:, indexVolume] = np.zeros(sz)
                self.m2Bas = np.zeros(sz)
                self.iterBas += 1

            else:

                for i in range(sz):
                    self.meanBas[i, indexVolume] = self.meanBas[
                        i, indexVolume -
                        1] + (data[i] - self.meanBas[i, indexVolume - 1]) / (
                            self.iterBas + 1)
                    self.m2Bas[i] = self.m2Bas[i] + (
                        data[i] - self.meanBas[i, indexVolume - 1]) * (
                            data[i] - self.meanBas[i, indexVolume])
                    self.varBas[i, indexVolume] = self.m2Bas[i] / self.iterBas

                self.iterBas += 1

        else:

            self.meanBas[:, indexVolume] = self.meanBas[:, indexVolume - 1]
            self.varBas[:, indexVolume] = self.varBas[:, indexVolume - 1]

        if indexVolume in self.indCond:

            if not self.iterCond:
                self.meanCond[:, indexVolume] = data
                self.varCond[:, indexVolume] = np.zeros(sz)
                self.m2Cond = np.zeros(sz)
                self.iterCond += 1

            else:

                for i in range(sz):
                    self.meanCond[i, indexVolume] = self.meanCond[
                        i, indexVolume -
                        1] + (data[i] - self.meanCond[i, indexVolume - 1]) / (
                            self.iterCond + 1)
                    self.m2Cond[i] = self.m2Cond[i] + (
                        data[i] - self.meanCond[i, indexVolume - 1]) * (
                            data[i] - self.meanCond[i, indexVolume])
                    self.varCond[i,
                                 indexVolume] = self.m2Cond[i] / self.iterCond

                self.iterCond += 1

        else:

            self.meanCond[:, indexVolume] = self.meanCond[:, indexVolume - 1]
            self.varCond[:, indexVolume] = self.varCond[:, indexVolume - 1]

        if self.iterCond:

            for i in range(sz):
                self.rCNR[
                    i,
                    indexVolume] = (self.meanCond[i, indexVolume] -
                                    self.meanBas[i, indexVolume]) / (
                                        np.sqrt(self.varCond[i, indexVolume] +
                                                self.varBas[i, indexVolume]))

            if self.comboBox.currentIndex() == 2:

                names = ['СNR ']
                pens = [config.PLOT_PEN_COLORS[6]]
                for i in range(sz):
                    names.append(
                        'ROI_' + str(i + 1) + ': ' +
                        '{0:.3f}'.format(float(self.rCNR[i][indexVolume - 1])))
                    pens.append(
                        pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))

                self.makeTextValueLabel(self.valuesLabel,
                                        names,
                                        pens,
                                        lineBreak='<br>')

    # --------------------------------------------------------------------------
    def calculateSpikes(self, data, indexVolume, posSpikes, negSpikes):
        """ Spikes and GLM signal recording

        :param data: signal values after GLM process
        :param indexVolume: current volume index
        :param posSpikes: flags of positive spikes
        :param negSpikes: flags of negative spikes
        """

        sz, l = data.shape
        self.glmProcTimeSeries[:, indexVolume] = data[:, 0]

        for i in range(sz):
            if posSpikes[i] == 1:
                if self.posSpikes[str(i)].any():
                    self.posSpikes[str(i)] = np.append(self.posSpikes[str(i)],
                                                       indexVolume)
                else:
                    self.posSpikes[str(i)] = np.array([indexVolume])
            if negSpikes[i] == 1 and l > 2:
                if self.negSpikes[str(i)].any():
                    self.negSpikes[str(i)] = np.append(self.negSpikes[str(i)],
                                                       indexVolume)
                else:
                    self.negSpikes[str(i)] = np.array([indexVolume])

    # --------------------------------------------------------------------------
    def calculateMSE(self, indexVolume, inputSignal, outputSignal):
        """ Low pass filter performance estimated by recursive mean squared error

        :param indexVolume: current volume index
        :param inputSignal: signal value before filtration
        :param outputSignal: signal value after filtration

        """

        sz = inputSignal.size
        n = self.blockIter - 1

        for i in range(sz):
            self.rMSE[i, indexVolume] = (
                n / (n + 1)) * self.rMSE[i, indexVolume - 1] + (
                    (inputSignal[i] - outputSignal[i])**2) / (n + 1)

        if self.comboBox.currentIndex() == 4:

            names = ['MSE ']
            pens = [config.PLOT_PEN_COLORS[6]]
            for i in range(sz):
                names.append('ROI_' + str(i + 1) + ': ' +
                             '{0:.3f}'.format(float(self.rMSE[i,
                                                              indexVolume])))
                pens.append(
                    pg.mkPen(color=config.ROI_PLOT_COLORS[i], width=1.2))

            self.makeTextValueLabel(self.mseLabel,
                                    names,
                                    pens,
                                    lineBreak='<br>')

    # --------------------------------------------------------------------------
    def dataPacking(self):
        """ Packaging of python RTQA data for following save
        """

        tsRTQA = dict.fromkeys([
            'rMean', 'rVar', 'rSNR', 'meanBas', 'varBas', 'meanCond',
            'varCond', 'rCNR', 'excFDIndexes_1', 'excFDIndexes_2',
            'excMDIndexes', 'FD', 'MD', 'rMSE'
        ])

        tsRTQA['rMean'] = matlab.double(self.rMean.tolist())
        tsRTQA['rVar'] = matlab.double(self.rVar.tolist())
        tsRTQA['rSNR'] = matlab.double(self.rSNR.tolist())
        tsRTQA['meanBas'] = matlab.double(self.meanBas.tolist())
        tsRTQA['varBas'] = matlab.double(self.varBas.tolist())
        tsRTQA['meanCond'] = matlab.double(self.meanCond.tolist())
        tsRTQA['varCond'] = matlab.double(self.varCond.tolist())
        tsRTQA['rCNR'] = matlab.double(self.rCNR.tolist())
        tsRTQA['excFDIndexes_1'] = matlab.double(
            self._fd.excFDIndexes_1.tolist())
        tsRTQA['excFDIndexes_2'] = matlab.double(
            self._fd.excFDIndexes_2.tolist())
        tsRTQA['excMDIndexes'] = matlab.double(self._fd.excMDIndexes.tolist())
        tsRTQA['FD'] = matlab.double(self._fd.FD.tolist())
        tsRTQA['MD'] = matlab.double(self._fd.MD.tolist())
        tsRTQA['rMSE'] = matlab.double(self.rMSE.tolist())

        return tsRTQA