def __init__(self):
        super().__init__()

        # settings
        self.setBackground("#fff")
        self.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken)
        self.setAntialiasing(True)

        # create custom view box
        view_box = ViewBox()
        view_box.setMouseEnabled(False, False)
        view_box.setLimits(xMin=0, yMin=0, minXRange=10, minYRange=100)
        view_box.setRange(xRange=(0, 400), yRange=(0, 5000))
        view_box.enableAutoRange()

        # create natural axis items
        self.x_axis = NaturalAxis("bottom")
        self.x_axis.setLabel(QApplication.translate("NaturalPlotView", "Fence length"), "m")
        self.y_axis = NaturalAxis("left")
        self.y_axis.setLabel(QApplication.translate("NaturalPlotView", "Number of plants"))

        # create fence information text
        self.fenceItem = TextItem(border=pyqtgraph.mkPen(width=2, color="#555"),
                fill=pyqtgraph.mkBrush((255, 255, 255, 200)))

        # create tube information text
        self.tubeItem = TextItem(border=pyqtgraph.mkPen(width=2, color="#555"),
                fill=pyqtgraph.mkBrush((255, 255, 255, 200)),
                anchor=(1,1))

        # create plot item with custom view box and natural axis items
        self.plotItem = PlotItem(viewBox=view_box,
                axisItems={"bottom" : self.x_axis, "left" : self.y_axis}, enableMenu=False)
        self.plotItem.setContentsMargins(5, 5, 12, 5)
        self.plotItem.hideButtons()
        self.plotItem.hide()
        self.setCentralWidget(self.plotItem)

        # connect actions
        view_box.sigResized.connect(self.updateTubeLegendPosition)

        # translate the plot item
        self.retranslateUi()
class HistogramLUTItem_overlay(GraphicsWidget):
    """
    This is a graphicsWidget which provides controls for adjusting the display of an image.
    
    Includes:

    - Image histogram 
    - Movable region over histogram to select black/white levels
    - Gradient editor to define color lookup table for single-channel images
    
    Parameters
    ----------
    image : ImageItem or None
        If *image* is provided, then the control will be automatically linked to
        the image and changes to the control will be immediately reflected in
        the image's appearance.
    fillHistogram : bool
        By default, the histogram is rendered with a fill.
        For performance, set *fillHistogram* = False.    
    rgbHistogram : bool
        Sets whether the histogram is computed once over all channels of the
        image, or once per channel.
    levelMode : 'mono' or 'rgba'
        If 'mono', then only a single set of black/whilte level lines is drawn,
        and the levels apply to all channels in the image. If 'rgba', then one
        set of levels is drawn for each channel.
    """
    
    sigLookupTableChanged = QtCore.Signal(object)
    sigLevelsChanged = QtCore.Signal(object)
    sigLevelChangeFinished = QtCore.Signal(object)
    
    def __init__(self, image=None, fillHistogram=True, rgbHistogram=False, levelMode='mono'):
        GraphicsWidget.__init__(self)
        self.overlay = False
        self.lut = None
        self.imageItem = lambda: None  # fake a dead weakref
        self.levelMode = levelMode
        self.rgbHistogram = rgbHistogram
        
        self.layout = QtGui.QGraphicsGridLayout()
        self.setLayout(self.layout)
        self.layout.setContentsMargins(1,1,1,1)
        self.layout.setSpacing(0)
        self.vb = ViewBox(parent=self)
        self.vb.setMaximumWidth(152)
        self.vb.setMinimumWidth(45)
        self.vb.setMouseEnabled(x=False, y=True)
        self.gradient = GradientEditorItem()
        self.gradient.setOrientation('right')
        self.gradient.loadPreset('grey')
        self.regions = [
            LinearRegionItem([0, 1], 'horizontal', swapMode='block'),
            LinearRegionItem([0, 1], 'horizontal', swapMode='block', pen='r',
                             brush=fn.mkBrush((255, 50, 50, 50)), span=(0., 1/3.)),
            LinearRegionItem([0, 1], 'horizontal', swapMode='block', pen='g',
                             brush=fn.mkBrush((50, 255, 50, 50)), span=(1/3., 2/3.)),
            LinearRegionItem([0, 1], 'horizontal', swapMode='block', pen='b',
                             brush=fn.mkBrush((50, 50, 255, 80)), span=(2/3., 1.)),
            LinearRegionItem([0, 1], 'horizontal', swapMode='block', pen='w',
                             brush=fn.mkBrush((255, 255, 255, 50)), span=(2/3., 1.))]
        for region in self.regions:
            region.setZValue(1000)
            self.vb.addItem(region)
            region.lines[0].addMarker('<|', 0.5)
            region.lines[1].addMarker('|>', 0.5)
            region.sigRegionChanged.connect(self.regionChanging)
            region.sigRegionChangeFinished.connect(self.regionChanged)
            
        self.region = self.regions[0]  # for backward compatibility.
        
        self.axis = AxisItem('left', linkView=self.vb, maxTickLength=-10, parent=self)
        self.layout.addItem(self.axis, 0, 0)
        self.layout.addItem(self.vb, 0, 1)
        self.layout.addItem(self.gradient, 0, 2)
        self.range = None
        self.gradient.setFlag(self.gradient.ItemStacksBehindParent)
        self.vb.setFlag(self.gradient.ItemStacksBehindParent)
        
        self.gradient.sigGradientChanged.connect(self.gradientChanged)
        self.vb.sigRangeChanged.connect(self.viewRangeChanged)
        add = QtGui.QPainter.CompositionMode_Plus
        self.plots = [
            PlotCurveItem(pen=(200, 200, 200, 100)),  # mono
            PlotCurveItem(pen=(255, 0, 0, 100), compositionMode=add),  # r
            PlotCurveItem(pen=(0, 255, 0, 100), compositionMode=add),  # g
            PlotCurveItem(pen=(0, 0, 255, 100), compositionMode=add),  # b
            PlotCurveItem(pen=(200, 200, 200, 100), compositionMode=add),  # a
            ]
        
        self.plot = self.plots[0]  # for backward compatibility.
        for plot in self.plots:
            plot.rotate(90)
            self.vb.addItem(plot)
        
        self.fillHistogram(fillHistogram)
        self._showRegions()
            
        self.vb.addItem(self.plot)
        self.autoHistogramRange()
        
        if image is not None:
            self.setImageItem(image)

        
    def fillHistogram(self, fill=True, level=0.0, color=(100, 100, 200)):
        colors = [color, (255, 0, 0, 50), (0, 255, 0, 50), (0, 0, 255, 50), (255, 255, 255, 50)]
        for i,plot in enumerate(self.plots):
            if fill:
                plot.setFillLevel(level)
                plot.setBrush(colors[i])
            else:
                plot.setFillLevel(None)
        
    def paint(self, p, *args):
        if self.levelMode != 'mono':
            return
        
        pen = self.region.lines[0].pen
        rgn = self.getLevels()
        p1 = self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[0]))
        p2 = self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[1]))
        gradRect = self.gradient.mapRectToParent(self.gradient.gradRect.rect())
        for pen in [fn.mkPen((0, 0, 0, 100), width=3), pen]:
            p.setPen(pen)
            p.drawLine(p1 + Point(0, 5), gradRect.bottomLeft())
            p.drawLine(p2 - Point(0, 5), gradRect.topLeft())
            p.drawLine(gradRect.topLeft(), gradRect.topRight())
            p.drawLine(gradRect.bottomLeft(), gradRect.bottomRight())
        
    def setHistogramRange(self, mn, mx, padding=0.1):
        """Set the Y range on the histogram plot. This disables auto-scaling."""
        self.vb.enableAutoRange(self.vb.YAxis, False)
        self.vb.setYRange(mn, mx, padding)

        
    def autoHistogramRange(self):
        """Enable auto-scaling on the histogram plot."""
        self.vb.enableAutoRange(self.vb.XYAxes)


    def setImageItem(self, img):
        """Set an ImageItem to have its levels and LUT automatically controlled
        by this HistogramLUTItem.
        """
        self.imageItem = weakref.ref(img)
        img.sigImageChanged.connect(self.imageChanged)
        img.setLookupTable(self.getLookupTable)  ## send function pointer, not the result
        self.regionChanged()
        self.imageChanged(autoLevel=True)

        
    def viewRangeChanged(self):
        self.update()
    
    def gradientChanged(self):
        if self.imageItem() is not None:
            if self.gradient.isLookupTrivial():
                self.imageItem().setLookupTable(None) #lambda x: x.astype(np.uint8))
            else:
                self.imageItem().setLookupTable(self.getLookupTable)  ## send function pointer, not the result
            
        self.lut = None
        self.sigLookupTableChanged.emit(self)

    def getLookupTable(self, img=None, n=None, alpha=None):
        """Return a lookup table from the color gradient defined by this 
        HistogramLUTItem.
        """
        if self.levelMode is not 'mono':
            return None
        if n is None:
            if img.dtype == np.uint8:
                n = 256
            else:
                n = 512
        if self.lut is None:
            self.lut = self.gradient.getLookupTable(n, alpha=alpha)
        return self.lut


    def regionChanged(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelChangeFinished.emit(self)

    def regionChanging(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelsChanged.emit(self)
        self.update()

    def imageChanged(self, autoLevel=False, autoRange=False):
        if self.imageItem() is None:
            return
            
        if self.levelMode == 'mono':
            for plt in self.plots[1:]:
                plt.setVisible(False)
            self.plots[0].setVisible(True)
            # plot one histogram for all image data
            profiler = debug.Profiler()
            h = self.imageItem().getHistogram()
            profiler('get histogram')
            if h[0] is None:
                return
            self.plot.setData(*h)
            profiler('set plot')
            if autoLevel:
                mn = h[0][0]
                mx = h[0][-1]
                self.region.setRegion([mn, mx])
                profiler('set region')
            else:
                mn, mx = self.imageItem().levels
                self.region.setRegion([mn, mx])
        else:
            # plot one histogram for each channel
            self.plots[0].setVisible(False)
            ch = self.imageItem().getHistogram(perChannel=True)
            if ch[0] is None:
                return
            for i in range(1, 5):
                if len(ch) >= i:
                    h = ch[i-1]
                    self.plots[i].setVisible(True)
                    self.plots[i].setData(*h)
                    if autoLevel:
                        mn = h[0][0]
                        mx = h[0][-1]
                        self.region[i].setRegion([mn, mx])
                else:
                    # hide channels not present in image data
                    self.plots[i].setVisible(False)
            # make sure we are displaying the correct number of channels
            self._showRegions()
            
    def getLevels(self):
        """Return the min and max levels.
        
        For rgba mode, this returns a list of the levels for each channel.
        """
        if self.levelMode == 'mono':
            return self.region.getRegion()
        else:
            nch = self.imageItem().channels()
            if nch is None:
                nch = 3
            return [r.getRegion() for r in self.regions[1:nch+1]]

        
    def setLevels(self, min=None, max=None, rgba=None):
        """Set the min/max (bright and dark) levels.
        
        Arguments may be *min* and *max* for single-channel data, or 
        *rgba* = [(rmin, rmax), ...] for multi-channel data.
        """
        if self.levelMode == 'mono':
            if min is None:
                min, max = rgba[0]
            assert None not in (min, max)
            self.region.setRegion((min, max))
        else:
            if rgba is None:
                raise TypeError("Must specify rgba argument when levelMode != 'mono'.")
            for i, levels in enumerate(rgba):
                self.regions[i+1].setRegion(levels)

        
    def setLevelMode(self, mode):
        """ Set the method of controlling the image levels offered to the user. 
        Options are 'mono' or 'rgba'.
        """
        assert mode in ('mono', 'rgba')
        
        if mode == self.levelMode:
            return
        
        oldLevels = self.getLevels()
        self.levelMode = mode
        self._showRegions()
        
        # do our best to preserve old levels
        if mode == 'mono':
            levels = np.array(oldLevels).mean(axis=0)
            self.setLevels(*levels)
        else:
            levels = [oldLevels] * 4
            self.setLevels(rgba=levels)
            
        # force this because calling self.setLevels might not set the imageItem
        # levels if there was no change to the region item
        self.imageItem().setLevels(self.getLevels())
        
        self.imageChanged()
        self.update()


    def _showRegions(self):
        for i in range(len(self.regions)):
            self.regions[i].setVisible(False)
            
        if self.levelMode == 'rgba':
            imax = 4
            if self.imageItem() is not None:
                # Only show rgb channels if connected image lacks alpha.
                nch = self.imageItem().channels()
                if nch is None:
                    nch = 3
            xdif = 1.0 / nch
            for i in range(1, nch+1):
                self.regions[i].setVisible(True)
                self.regions[i].setSpan((i-1) * xdif, i * xdif)
            self.gradient.hide()
        elif self.levelMode == 'mono':
            self.regions[0].setVisible(True)
            self.gradient.show()
        else:
            raise ValueError("Unknown level mode %r" %  self.levelMode) 
    
    def saveState(self):
        return {
            'gradient': self.gradient.saveState(),
            'levels': self.getLevels(),
            'mode': self.levelMode,
        }
    
    def restoreState(self, state):
        self.setLevelMode(state['mode'])
        self.gradient.restoreState(state['gradient'])
        self.setLevels(*state['levels'])
        
    def setOverlay(self,state=False):
        self.overlay = state
Пример #3
0
class HistogramItem(GraphicsWidget):
    """
    This is a graphicsWidget which provides controls for adjusting the display of an image.

    Includes:

    - Image histogram 
    - Movable region over histogram to select black/white levels

    Parameters
    ----------
    image : ImageItem or None
        If *image* is provided, then the control will be automatically linked to
        the image and changes to the control will be immediately reflected in
        the image's appearance.
    fillHistogram : bool
        By default, the histogram is rendered with a fill.
        For performance, set *fillHistogram* = False.
    """

    sigLevelsChanged = pyqtSignal(object)
    sigLevelChangeFinished = pyqtSignal(object)

    def __init__(self, image=None, fillHistogram=True, bounds: tuple = None):
        GraphicsWidget.__init__(self)
        self.imageItem = lambda: None  # fake a dead weakref

        self.layout = QGraphicsGridLayout()
        self.setLayout(self.layout)
        self.layout.setContentsMargins(1, 1, 1, 1)
        self.layout.setSpacing(0)
        self.vb = ViewBox(parent=self)
        # self.vb.setMaximumHeight(152)
        # self.vb.setMinimumWidth(45)
        self.vb.setMouseEnabled(x=True, y=False)

        self.region = LinearRegionItem([0, 1], 'vertical', swapMode='block', bounds=bounds)
        self.region.setZValue(1000)
        self.vb.addItem(self.region)
        self.region.lines[0].addMarker('<|', 0.5)
        self.region.lines[1].addMarker('|>', 0.5)
        self.region.sigRegionChanged.connect(self.regionChanging)
        self.region.sigRegionChangeFinished.connect(self.regionChanged)

        self.axis = AxisItem('bottom', linkView=self.vb, maxTickLength=-10, parent=self)
        self.layout.addItem(self.axis, 1, 0)
        self.layout.addItem(self.vb, 0, 0)
        self.range = None
        self.vb.sigRangeChanged.connect(self.viewRangeChanged)

        self.plot = PlotCurveItem(pen=(200, 200, 200, 100))
        # self.plot.rotate(90)
        self.vb.addItem(self.plot)

        self.fillHistogram(fillHistogram)
        self._showRegions()

        self.autoHistogramRange()

        if image is not None:
            self.setImageItem(image)

    def fillHistogram(self, fill=True, level=0.0, color=(100, 100, 200)):
        if fill:
            self.plot.setFillLevel(level)
            self.plot.setBrush(color)
        else:
            self.plot.setFillLevel(None)


    def paint(self, p, *args):
        rgn = self.getLevels()
        self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[0]))
        self.vb.mapFromViewToItem(self, Point(self.vb.viewRect().center().x(), rgn[1]))


    def setHistogramRange(self, mn, mx, padding=0.1):
        """Set the Y range on the histogram plot. This disables auto-scaling."""
        self.vb.enableAutoRange(self.vb.XAxis, False)
        self.vb.setYRange(mn, mx, padding)

    def autoHistogramRange(self):
        """Enable auto-scaling on the histogram plot."""
        self.vb.enableAutoRange(self.vb.XYAxes)

    def setImageItem(self, img):
        """Set an ImageItem to have its levels and LUT automatically controlled
        by this HistogramLUTItem.
        """
        self.imageItem = weakref.ref(img)
        img.sigImageChanged.connect(self.imageChanged)
        self.regionChanged()
        self.imageChanged(autoLevel=True)

    def viewRangeChanged(self):
        self.update()

    def regionChanged(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelChangeFinished.emit(self)

    def regionChanging(self):
        if self.imageItem() is not None:
            self.imageItem().setLevels(self.getLevels())
        self.sigLevelsChanged.emit(self)
        self.update()

    def imageChanged(self, autoLevel=False):
        if self.imageItem() is None:
            return

        self.plot.setVisible(True)
        # plot one histogram for all image data
        h = self.imageItem().getHistogram()
        if h[0] is None:
            return
        self.plot.setData(*h)
        if autoLevel:
            mn = h[0][0]
            mx = h[0][-1]
            self.region.setRegion([mn, mx])
        else:
            mn, mx = self.imageItem().levels
            self.region.setRegion([mn, mx])

    def getLevels(self):
        """
        Return the min and max levels.
        """
        return self.region.getRegion()

    def setLevels(self, min=None, max=None):
        """
        Set the min/max (bright and dark) levels.
        """
        assert None not in (min, max)
        self.region.setRegion((min, max))

    def _showRegions(self):
        self.region.setVisible(True)

    def saveState(self):
        return {
            'levels': self.getLevels(),
        }

    def restoreState(self, state):
        self.setLevels(*state['levels'])
class DataWidget(QWidget):
    def __init__(self, parent, shared_data):
        super(DataWidget, self).__init__(parent)
        self.__shared_data = shared_data
        self.__shared_data.update_sync.emit()

        # Add the file selection controls
        self.__dir_picker_button = QPushButton()
        self.__dir_picker_button.setEnabled(True)
        self.__dir_picker_button.setText("Load data")
        self.__dir_picker_button.setIcon(self.style().standardIcon(QStyle.SP_DirIcon))
        self.__dir_picker_button.setToolTip('Select the directory using the file explorer')
        self.__dir_picker_button.clicked.connect(self.__open_dir_picker)

        # Add the sync controls
        self.__sync_time_label = QLabel()
        self.__sync_time_label.setText('Enter the timecode (HH:mm:ss:zzz) : ')

        self.__sync_time_edit = QTimeEdit()
        self.__sync_time_edit.setDisplayFormat('HH:mm:ss:zzz')
        self.__sync_time_edit.setEnabled(False)

        self.__sync_time_button = QPushButton()
        self.__sync_time_button.setText('Sync data')
        self.__sync_time_button.setEnabled(False)
        self.__sync_time_button.clicked.connect(self.__sync_data)

        # Create the layout for the file controls
        dir_layout = QHBoxLayout()
        dir_layout.setContentsMargins(0, 0, 0, 0)
        dir_layout.addWidget(self.__dir_picker_button)
        dir_layout.addStretch(1)
        dir_layout.addWidget(self.__sync_time_label)
        dir_layout.addWidget(self.__sync_time_edit)
        dir_layout.addWidget(self.__sync_time_button)

        # Create the axis and their viewbox
        self.__x_axis_item = AxisItem('left')
        self.__y_axis_item = AxisItem('left')
        self.__z_axis_item = AxisItem('left')

        self.__x_axis_viewbox = ViewBox()
        self.__y_axis_viewbox = ViewBox()
        self.__z_axis_viewbox = ViewBox()

        # Create the widget which will display the data
        self.__graphic_view = GraphicsView(background="#ecf0f1")
        self.__graphic_layout = GraphicsLayout()
        self.__graphic_view.setCentralWidget(self.__graphic_layout)

        # Add the axis to the widget
        self.__graphic_layout.addItem(self.__x_axis_item, row=2, col=3, rowspan=1, colspan=1)
        self.__graphic_layout.addItem(self.__y_axis_item, row=2, col=2, rowspan=1, colspan=1)
        self.__graphic_layout.addItem(self.__z_axis_item, row=2, col=1, rowspan=1, colspan=1)

        self.__plot_item = PlotItem()
        self.__plot_item_viewbox = self.__plot_item.vb
        self.__graphic_layout.addItem(self.__plot_item, row=2, col=4, rowspan=1, colspan=1)

        self.__graphic_layout.scene().addItem(self.__x_axis_viewbox)
        self.__graphic_layout.scene().addItem(self.__y_axis_viewbox)
        self.__graphic_layout.scene().addItem(self.__z_axis_viewbox)

        self.__x_axis_item.linkToView(self.__x_axis_viewbox)
        self.__y_axis_item.linkToView(self.__y_axis_viewbox)
        self.__z_axis_item.linkToView(self.__z_axis_viewbox)

        self.__x_axis_viewbox.setXLink(self.__plot_item_viewbox)
        self.__y_axis_viewbox.setXLink(self.__plot_item_viewbox)
        self.__z_axis_viewbox.setXLink(self.__plot_item_viewbox)

        self.__plot_item_viewbox.sigResized.connect(self.__update_views)
        self.__x_axis_viewbox.enableAutoRange(axis=ViewBox.XAxis, enable=True)
        self.__y_axis_viewbox.enableAutoRange(axis=ViewBox.XAxis, enable=True)
        self.__z_axis_viewbox.enableAutoRange(axis=ViewBox.XAxis, enable=True)

        # Create the final layout
        self.__v_box = QVBoxLayout()
        self.__v_box.addLayout(dir_layout)
        self.__v_box.addWidget(self.__graphic_view)

        self.setLayout(self.__v_box)

        self.__restore_state()

    def __open_dir_picker(self):
        self.__shared_data.data_file_path = QFileDialog.getOpenFileUrl(self, 'Open the Hexoskin data directory',
                                                                       QDir.homePath())[0]
        if self.__shared_data.data_file_path is not None:
            try:
                self.__load_data()
                self.__add_selector_acc_gyr()
                self.__show_data('ACC_X', 'ACC_Y', 'ACC_Z')
            except FileNotFoundError:
                pass
            except UnicodeDecodeError:
                pass

    def __load_data(self):
        if self.__shared_data.data_file_path is not None:
            self.__shared_data.import_parameter()

    def __show_data(self, field1, field2, field3):
        if self.__shared_data.parameter is not None:
            # Generate the timecodes if needed
            if len(self.__shared_data.parameter['TIMECODE']) == 0:
                if self.__shared_data.sampling_rate is None:
                    result = False
                    while not result and result == 0:
                        result = self.__show_sampling_rate_picker()

                self.__shared_data.add_timecode()

            self.__x_axis_viewbox.clear()
            self.__y_axis_viewbox.clear()
            self.__z_axis_viewbox.clear()

            # Show the 3 selected fields
            self.__x_axis_viewbox.addItem(PlotCurveItem(list(map(int, self.__shared_data.parameter.get(field1))),
                                                        pen='#34495e'))
            self.__y_axis_viewbox.addItem(PlotCurveItem(list(map(int, self.__shared_data.parameter.get(field2))),
                                                        pen='#9b59b6'))
            self.__z_axis_viewbox.addItem(PlotCurveItem(list(map(int, self.__shared_data.parameter.get(field3))),
                                                        pen='#3498db'))

            self.__x_axis_item.setLabel(field1, color="#34495e")
            self.__y_axis_item.setLabel(field2, color="#9b59b6")
            self.__z_axis_item.setLabel(field3, color="#3498db")

            # Add the middle line and the bottom timecodes
            timecodes = self.__shared_data.parameter['TIMECODE']
            middle = [0] * len(timecodes)
            self.__plot_item_viewbox.addItem(PlotCurveItem(middle, pen='#000000'))
            self.__plot_item.getAxis('bottom').setTicks(
                self.__generate_time_ticks(timecodes, self.__shared_data.sampling_rate))

            # Enable the controls
            self.__sync_time_edit.setEnabled(True)
            self.__sync_time_button.setEnabled(True)
            self.__dir_picker_button.setEnabled(False)
        self.__update_views()

    def __update_views(self):
        self.__x_axis_viewbox.setGeometry(self.__plot_item_viewbox.sceneBoundingRect())
        self.__y_axis_viewbox.setGeometry(self.__plot_item_viewbox.sceneBoundingRect())
        self.__z_axis_viewbox.setGeometry(self.__plot_item_viewbox.sceneBoundingRect())

    def __generate_time_ticks(self, timecodes, rate):
        ticks = list()

        steps = [rate * 30, rate * 15, rate * 5, rate]
        for step in steps:
            temp = list()
            i = step
            while i in range(len(timecodes)):
                temp.append((i, timecodes[i].strftime('%H:%M:%S:') + str(int(timecodes[i].microsecond / 1000))))
                i += step
            ticks.append(temp)

        return ticks

    def __sync_data(self):
        self.__shared_data.data_sync = self.__sync_time_edit.text()
        self.__shared_data.update_sync.emit()

    def __show_sampling_rate_picker(self) -> bool:
        self.__shared_data.sampling_rate, result = QInputDialog.getInt(self, 'Set sampling rate value', 'Sampling rate')
        return result

    def __add_selector_acc_gyr(self):
        if 'GYR_X' in self.__shared_data.parameter.keys() or 'GYR_Y' in self.__shared_data.parameter.keys() \
                or 'GYR_Z' in self.__shared_data.parameter.keys():
            show_acc = QPushButton()
            show_acc.setText('Show Accelerometer Axis')
            show_acc.clicked.connect(self.__show_acc)

            show_gyr = QPushButton()
            show_gyr.setText('Show Gyroscope Axis')
            show_gyr.clicked.connect(self.__show_gyr)

            layout = QHBoxLayout()
            layout.addWidget(show_acc)
            layout.addWidget(show_gyr)
            layout.addStretch(1)

            self.__v_box.addLayout(layout)

    def __show_acc(self):
        self.__show_data('ACC_X', 'ACC_Y', 'ACC_Z')

    def __show_gyr(self):
        self.__show_data('GYR_X', 'GYR_Y', 'GYR_Z')

    def __restore_state(self):
        if self.__shared_data.parameter is not None:
            self.__add_selector_acc_gyr()
            self.__show_data('ACC_X', 'ACC_Y', 'ACC_Z')
            print('trigger reimport')
        if self.__shared_data.data_sync is not None:
            text_time = self.__shared_data.data_sync.split(':')
            time = QTime()
            time.setHMS(int(text_time[0]), int(text_time[1]), int(text_time[2]), int(text_time[3]))
            self.__sync_time_edit.setTime(time)