예제 #1
0
    def __init__(self, name: str, *, start: float = None, end: float = None):
        from gui import PALMS
        from logic.databases.DatabaseHandler import Database
        track = Database.get().tracks[Database.get().main_track_label]

        super().__init__((start, end))
        self.setBounds([start, end])
        self.track = track
        self.start = start
        self.end = end
        self.mid = self.start + (self.end - self.start) / 2
        self.name = name
        self.label = pg.TextItem(name)

        self.label.setFont(
            QFont("", PALMS.config['epoch_labels_font_size'], QFont.Bold))
        self.label.setAnchor((0.5, 1))
        # self.label.setColor(QColor('k'))

        try:
            label_y = EpochModeConfig.get().label_to_ypos[name]
        except:
            label_y = self.track.get_yrange_between(self.start, self.end)[0]
        self.label.setPos(self.mid, label_y)

        # self.sigRegionChangeFinished.connect(self.region_moved)
        EpochWindow._instance = weakref.ref(self)()
        qInfo('Window at [{:0.2f}; {:0.2f}] '.format(self.start, self.end))
예제 #2
0
    def from_click(cls, name: str, *, click_x: float):
        """construct SinglePartition from single point: calculate its start/end considering other partitions"""
        from logic.databases.DatabaseHandler import Database
        from gui import PALMS
        track = Database.get().tracks[Database.get().main_track_label]
        initial_span = (track.maxX - track.minX) * 0.01
        initial_span = PALMS.config['initial_partition_span_sec']  # NB: set initial span of just created partition
        left_bound, right_bound = Partitions.calculate_boundaries(click_x, click_x)
        left_bound = left_bound if left_bound is not None else track.minX
        right_bound = right_bound if right_bound is not None else track.maxX

        start = max([max([click_x - initial_span / 2, track.minX]), left_bound])
        end = min([min([click_x + initial_span / 2, track.maxX]), right_bound])
        return cls(name, start=start, end=end)
예제 #3
0
    def zoomChanged(self):
        try:  # this is to avoid redrawing if it is already zoomed out to max
            newRange = self.main_window.selectedView.renderer.vb.targetRange(
            )[0]
            viewRange = self.main_window.selectedView.renderer.vb.viewRange(
            )[0]
            # newRange = self.main_vb.viewRange()[0]
            if newRange[-1] >= Database.get().get_longest_track_duration(
            ) and newRange[0] <= 0:  # TODO what if offset not 0
                if self.FLAG_full_zoom_out:
                    return
                else:
                    self.FLAG_full_zoom_out = True
            else:
                self.FLAG_full_zoom_out = False
        except:
            pass

        if self.main_vb.geometry():
            try:
                pixel_width = self.main_vb.viewPixelSize()[0]
                self.main_vb.setLimits(xMin=-pixel_width)
                for vb in self.vbs.values():
                    vb.setLimits(xMin=-pixel_width)
                self.redraw_fiducials()
                if self.display_panel is not None and len(
                        self.display_panel.panel.views) > 0:
                    self.setYRange()
                EpochModeConfig.get().redraw_epochs()
            except Exception as e:
                Dialog().warningMessage(
                    'Exception occured\r\n'
                    'Using more than one frame may have caused this!\r\n' +
                    str(e))
예제 #4
0
 def from_csv(cls, csv):
     from gui import PALMS
     settings_init = pd.read_csv(csv)
     db = Database.get()
     fiducials = []
     for _, row_data in settings_init.iterrows():
         assert all([k in row_data for k in PALMS.config['annotationConfig_columns']])
         # NB: recover aConf.pinned_to changes from json
         #  it is not needed as one can rewrite annotation config from AnnotationConfigDialog Save button
         # see also AnnotationConfigDialog where applied data is saved
         # try:
         #     tmp_singleFiducialConfig = SingleFiducialConfig(row_data)
         #     pinned_to_prev_state = PALMS.config['pinned_to_last_state'][tmp_singleFiducialConfig.name]
         #     pinned_to_prev_state = pinned_to_prev_state.split()
         #     if pinned_to_prev_state[0] in PALMS.config['pinned_to_options'] and \
         #         pinned_to_prev_state[1] in db.tracks_to_plot_initially:
         #         row_data['pinned_to'] = " ".join(pinned_to_prev_state)
         #     qInfo('Annotation Config updated with config.json data')
         # except Exception as e:
         #     pass
         fiducials.append(SingleFiducialConfig(row_data))
     aConf = AnnotationConfig.get()
     aConf.reset_fiducials_config(fiducials)
     try:  # NB: nice to do it here, but Viewer object might still not be created
         from gui.viewer import Viewer
         Viewer.get().annotationConfig.aConf_to_table(aConf)
         Viewer.get().annotationConfig.reset_pinned_to_options_to_existing_views()
     except:
         pass
     return aConf
예제 #5
0
    def move_left():
        EpochWindow.hide()
        from logic.databases.DatabaseHandler import Database
        from gui.viewer import Viewer
        from gui.plot_area import PlotArea
        track = Database.get().tracks[Database.get().main_track_label]

        success = EpochModeConfig.CURRENT_WINDOW_IDX.decrease()
        if success:
            st, en, label = EpochModeConfig.get().get_window_data(
                EpochModeConfig.CURRENT_WINDOW_IDX.get())
            EpochWindow(label, start=st, end=en)
            while EpochWindow.is_out_of_scope():
                Viewer.get().shiftLeft()

        EpochWindow.show()
        PlotArea.get_main_view().renderer.plot_area.setFocus()
예제 #6
0
 def select_main_view(self):
     try:
         all_views = [
             v.track.label for v in self.main_window.selectedPanel.views
         ]
         self.selectRow(all_views.index(Database.get().main_track_label)
                        )  # select the main signal again
     except:
         pass
예제 #7
0
    def __init__(self, name: str, *, start: float = None, end: float = None):
        """
        constructor when start/end are given explicitly. when created from mouse click (single point) see self.from_click
        """
        from gui import PALMS
        from logic.databases.DatabaseHandler import Database
        track = Database.get().tracks[Database.get().main_track_label]
        left_bound, right_bound = Partitions.calculate_boundaries(start, end)
        left_bound = left_bound if left_bound is not None else track.minX
        right_bound = right_bound if right_bound is not None else track.maxX

        start = max([max([start, track.minX]), left_bound])
        end = min([min([end, track.maxX]), right_bound])

        super().__init__((start, end))
        self.setBounds([left_bound, right_bound])
        self.track = track
        self.start = start
        self.end = end
        self.mid = self.start + (self.end - self.start) / 2
        self.name = name
        self.label = pg.TextItem(name)

        self.label.setFont(QFont("", PALMS.config['partition_labels_font_size'], QFont.Bold))
        # self.label.setColor(QColor('k'))
        self.label.setAnchor((0.5, 1))
        self.label.setPos(self.mid, self.track.get_yrange_between(self.start, self.end)[0])
        Partitions.add(self)

        Partitions.update_all_bounds(self)

        # # update config with new partition name
        # from gui.viewer import PALMS
        # PALMS.config['default_partition_labels'] = list(
        #     unique_everseen(PALMS.config['default_partition_labels'] + Partitions.unique_labels()))

        self.sigRegionChangeFinished.connect(self.region_moved)
        qInfo('Region {} [{:0.2f}; {:0.2f}] created'.format(self.name, self.start, self.end))
예제 #8
0
 def toggleAllViewsExceptMain(self):
     # TODO: make a method to get all views over all panels
     from logic.databases.DatabaseHandler import Database
     all_views = [v for v in self.main_window.selectedPanel.views]
     if self.ALL_VIEWS_HIDDEN:
         for v in all_views:
             v.show = True
             self.showView(v)
         self.ALL_VIEWS_HIDDEN = False
     else:
         for v in all_views:
             if not v.track.label is Database.get().main_track_label:
                 v.show = False
                 self.hideView(v)
         self.ALL_VIEWS_HIDDEN = True
     self.display_panel.view_table.update_showCheckbox_state()
예제 #9
0
    def get_main_view():
        from gui.viewer import Viewer
        from logic.databases.DatabaseHandler import Database
        main_track_label = Database.get().main_track_label

        if Viewer.get() is None:
            return None
        for frame in Viewer.get().frames:
            all_views = [v for v in frame.displayPanel.panel.views]
            all_views_labels = [v.track.label for v in all_views]
            main_track_idx = all_views_labels.index(
                main_track_label
            ) if main_track_label in all_views_labels else None
            if main_track_idx is not None:
                break
        if main_track_idx is None:  # in case main view is not created yet
            return None
        main_view = all_views[main_track_idx]
        return main_view
예제 #10
0
    def split_pinned_to(self):
        try:
            from gui.viewer import PALMS
            if self.pinned_to in PALMS.config['pinned_to_options']:
                self.pinned_to = self.pinned_to + ' ' + Database.get().main_track_label

            pinned_to_split = self.pinned_to.split()
            # TODO: make it more generic and foolproof, now it is assumed that pinned_to consists of two words: peak\valley + track_label
            assert_text = '{} pinned_to setting must consist of two words:\r\n' \
                          '"peak" or "valley" + track_label from the database;\r\n' \
                          'Current pinned_to value is {}\r\n' \
                          'Check your AnnotationConfig file {} and run the tool again'.format(self.name, self.pinned_to,
                                                                                              Database.get().annotation_config_file.stem)
            assert len(pinned_to_split) == 2, assert_text
            assert pinned_to_split[0] in PALMS.config['pinned_to_options'], assert_text
            self.pinned_to_location = pinned_to_split[0]
            self.pinned_to_track_label = pinned_to_split[1]
        except Exception as e:
            from utils.utils_gui import Dialog
            Dialog().warningMessage('Error in split_pinned_to():\r\n' + str(e))
            raise ValueError
예제 #11
0
    def create_RRinterval_track(self):
        db = Database.get()
        to_HR = db.RR_interval_as_HR
        track_fs = db.tracks[db.main_track_label].fs
        track_ts = db.tracks[db.main_track_label].ts
        closest_int_fs = int(min([np.ceil(1 / min(np.diff(self.x))), track_fs]))

        fs = track_fs  # maximum zooming is defined by the lowest sampling freq of all tracks
        rr_ts = np.arange(track_ts[0], track_ts[-1], 1 / fs)
        new_ts_idx = np.arange(bisect.bisect_right(rr_ts, self.x[1]), bisect.bisect_left(rr_ts, self.x[-1]))
        rr = np.zeros_like(rr_ts)

        from gui.tracking import Wave
        if to_HR:
            rr[new_ts_idx] = np.interp(rr_ts[new_ts_idx], self.x[1:], 60 / np.diff(self.x))
            rr_int_wave = Wave(rr, fs, rr_ts, offset=0, label='HR(' + self.name + ')', unit='BPM')
            rr_int_wave.type = 'HR'
        else:
            rr[new_ts_idx] = np.interp(rr_ts[new_ts_idx], self.x[1:], np.diff(self.x))
            rr_int_wave = Wave(rr, fs, rr_ts, offset=0, label='RR(' + self.name + ')', unit='sec')
            rr_int_wave.type = 'RR'

        return rr_int_wave
예제 #12
0
    def __init__(self,
                 *,
                 winLen=10,
                 labels: List[str] = None,
                 keys: List[str] = None,
                 default_label=None,
                 description: List[str] = None):
        if labels is None:
            labels = ['low', 'good']
        if keys is None:
            keys = list(np.arange(len(labels)).astype(str))
        if description is None:
            description = labels
        if default_label is not None:
            if isinstance(default_label, str):
                if default_label not in labels:
                    default_label = labels[0]
                    qInfo(
                        'Given default_label is not in given labels. Changed to {} '
                        .format(default_label))
            elif isinstance(default_label, int):
                if default_label <= len(labels):
                    default_label = labels[default_label]
                else:
                    default_label = labels[0]
                    qInfo(
                        'Given default_label is not in given labels. Changed to {} '
                        .format(default_label))
        else:
            default_label = EpochModeConfig.NONE_LABEL

        from logic.databases.DatabaseHandler import Database
        track = Database.get().tracks[Database.get().main_track_label]
        self.window_data = pd.DataFrame(columns={'start', 'end', 'label'})
        self.visuals = []
        self.label_to_ypos = {}
        self.labels_to_keys = {}
        self.keys_to_labels = {}
        self.labels_to_color = {}
        self.toggle_fiducials = True

        self.window_overlap = 0  # sec

        self.window_length = winLen  # sec
        self.labels = labels
        self.default_label = default_label
        self.keys = keys
        self.description = description

        all_starts = np.arange(track.time[0], track.time[-1],
                               self.window_length)
        all_ends = all_starts + self.window_length
        if all_ends[-1] > track.time[-1]:
            all_ends[-1] = track.time[-1]

        self.window_data['start'] = all_starts
        self.window_data['end'] = all_ends
        self.window_data['is_modified'] = 0
        self.window_data['label'] = self.default_label

        self.test_epoch_config()

        # colors to be assigned to different labels, colors do not mean anything and can be counterintuitive as Good=Red, Bad=Green
        colors = cycle(['r', 'g', 'b', 'c', 'm', 'y', 'w'])
        for l, k in zip(self.labels, self.keys):
            self.labels_to_keys[l] = k
            self.keys_to_labels[k] = l
            self.labels_to_color[l] = next(colors)

        st, en, label = self.get_window_data(
            EpochModeConfig.CURRENT_WINDOW_IDX.get())
        EpochWindow(label, start=st, end=en)

        self.redraw_epochs()
        EpochModeConfig._instance = weakref.ref(self)()
예제 #13
0
    def viewPopup(self, point):
        if isinstance(self.sender(), QtWidgets.QHeaderView):
            row = self.sender().logicalIndexAt(point)
        elif isinstance(self.sender(), QtWidgets.QLabel):
            row = self.rowFromWidget(self.sender())
        else:
            logging.error(f'do not know how to handle getting index of ',
                          f'{self.sender()} object')
            self.main_window.application.viewer.status(
                f'do not know how to handle getting index of ',
                f'{self.sender()} object')
            raise TypeError
        view = self.panel.views[row]
        menu = QtWidgets.QMenu(self.verticalHeader())
        menu.clear()
        move_menu = menu.addMenu('&Move View')
        link_menu = menu.addMenu("&Link Track")
        copy_menu = menu.addMenu("Copy View")

        derive_menu = menu.addMenu("Add derived tracks")

        linkAction = QtWidgets.QAction('Create Link in this Panel', self)
        linkAction.triggered.connect(
            partial(self.display_panel.linkTrack, view,
                    self.main_window.model.panels.index(self.panel)))
        link_menu.addAction(linkAction)
        link_menu.addSeparator()
        link_menu.setEnabled(False)

        copyAction = QtWidgets.QAction("Duplicate View in this Panel", self)
        copyAction.triggered.connect(
            partial(self.display_panel.copyView, view,
                    self.main_window.model.panels.index(self.panel)))
        copy_menu.addAction(copyAction)
        copy_menu.addSeparator()
        copy_menu.setEnabled(False)

        addDerivativeAction = QtWidgets.QAction('1st derivative', self)
        addDerivativeAction.triggered.connect(
            partial(self.display_panel.addDerivative, view,
                    self.main_window.model.panels.index(self.panel), 1))
        # TODO: derivative filters GUI
        derive_menu.addAction(addDerivativeAction)

        addDerivativeAction = QtWidgets.QAction('2nd derivative', self)
        addDerivativeAction.triggered.connect(
            partial(self.display_panel.addDerivative, view,
                    self.main_window.model.panels.index(self.panel), 2))
        derive_menu.addAction(addDerivativeAction)

        menu.addSeparator()

        try:
            addRRintervalMenu = menu.addMenu('RR-intevals')
            from logic.operation_mode.annotation import AnnotationConfig
            RRintervalMenu_actions = []
            for f in AnnotationConfig.all_fiducials():
                f_idx = AnnotationConfig.get().find_idx_by_name(f)
                if AnnotationConfig.get(
                ).fiducials[f_idx].annotation.x.size > 2:
                    action = QtWidgets.QAction(f,
                                               self,
                                               checkable=False,
                                               enabled=True)
                    action.triggered.connect(
                        partial(
                            self.main_window.application.add_view_from_track,
                            AnnotationConfig.get().fiducials[f_idx].annotation.
                            create_RRinterval_track(),
                            self.main_window.model.panels.index(self.panel)))
                    RRintervalMenu_actions.append(action)
                    addRRintervalMenu.addAction(action)
        except Exception as e:
            Dialog().warningMessage('Creating RR interval plot failed\r\n'
                                    'The error was:\r\n' + str(e))

        # TODO: load another track
        # TODO: move existing view

        db = Database.get()
        add_menu = menu.addMenu("Add tracks from DB")
        add_menu.setEnabled(False)
        if db is not None and db.ntracks() > 0:
            add_menu.setEnabled(True)
            for label, track in db.tracks.items():
                plot_signal_action = QtWidgets.QAction(label, self)
                plot_signal_action.triggered.connect(
                    partial(self.main_window.application.add_view_from_track,
                            track,
                            self.main_window.model.panels.index(self.panel)))
                add_menu.addAction(plot_signal_action)
                if label not in self.allViewsTrackLabels():
                    plot_signal_action.setEnabled(True)
                else:
                    plot_signal_action.setEnabled(False)

        menu.addSeparator()
        process_action = QtWidgets.QAction('Processor Config', self)
        process_action.triggered.connect(
            partial(self.main_window.application.viewer.processorConfig.show,
                    self.selectedView()))
        menu.addAction(process_action)
        process_action.setEnabled(False)

        menu.addSeparator()
        invertAction = QtWidgets.QAction('&Invert Track', self)
        invertAction.triggered.connect(self.main_window.invertView)
        invertAction.setEnabled(False)
        menu.addAction(invertAction)

        menu.addSeparator()
        deleteAction = QtWidgets.QAction('&Delete Track', self)
        deleteAction.triggered.connect(self.main_window.guiDelView)
        menu.addAction(deleteAction)

        for index, panel in enumerate(self.main_window.model.panels):
            if panel is self.panel:
                continue
            linkAction = QtWidgets.QAction(f'Link to Panel {index + 1}', self)
            linkAction.triggered.connect(
                partial(self.display_panel.linkTrack, view, index))
            link_menu.addAction(linkAction)

            moveAction = QtWidgets.QAction(f'Move To Panel {index + 1}', self)
            moveAction.triggered.connect(
                partial(self.display_panel.moveView, view, index))
            move_menu.addAction(moveAction)

            copyAction = QtWidgets.QAction(f'Copy to Panel {index + 1}', self)
            copyAction.triggered.connect(
                partial(self.display_panel.copyView, view, index))
            copy_menu.addAction(copyAction)

        moveAction = QtWidgets.QAction(f'Move to New Panel', self)
        moveAction.triggered.connect(
            partial(self.display_panel.moveView, view, -1))

        linkAction = QtWidgets.QAction(f'Link to New Panel', self)
        linkAction.triggered.connect(
            partial(self.display_panel.linkTrack, view, -1))

        copyAction = QtWidgets.QAction(f'Copy to New Panel', self)
        copyAction.triggered.connect(
            partial(self.display_panel.copyView, view, -1))

        move_menu.addSeparator()
        link_menu.addSeparator()
        copy_menu.addSeparator()
        move_menu.addAction(moveAction)
        link_menu.addAction(linkAction)
        copy_menu.addAction(copyAction)
        menu.popup(QtGui.QCursor.pos())
예제 #14
0
 def is_main_view_in_current_panel(self):
     from logic.databases.DatabaseHandler import Database
     main_track_label = Database.get().main_track_label
     return main_track_label in [
         s.track.label for s in self.display_panel.panel.views
     ]
예제 #15
0
    def mousePressEvent(self, event: QtGui.QMouseEvent):
        """
        The following only has effect if the main track is selected in the track table view on the right
        Annotation mode:
            **LeftMouseButton** places a new fiducial. By default it is the first fiducial as set in the annotationConfig,
            unless before that a keyboard button was pressed corresponding to another fiducial or "sticky fiducial" mode is on.
            **RightMouseButton** removes the nearest fiducial (default), unless "sticky fiducial" mode is on. Keyboard has no effect
        Partition mode:
            **CTRL + LeftMouseButton** creates a new partition which takes 2% of the whole track duration or less to avoid overlapping
            partiotions;
            **CTRL + RightMouseButton** removes partition under the click
            **SHIFT + LeftMouseButton** to drag partition borders or move the partition. Repositioning is possible within the limits of
            neighboring partition. Moving the partition fully inside another one or reducing its size to 1 sample deletes the partition.
            #NOTE: creating partition of desired size directly by click and drag might not be that convenient and harder to implement
        Epoch mode:

        # NB: when adding\removing mouse click operations also adapt self.mouseReleaseEvent() and self.mouseMoveEvent()
        """
        def which_fiducial_to_add(last_keypress_event_key):
            from gui.viewer import Viewer
            # first check if 'sticky' fiducial option is enabled for one of the fiducials
            sticky_fiducial = [
                item.isChecked() for item in
                Viewer.get().annotation_menu.sticky_fiducial_menu.actions()
            ]
            if any(sticky_fiducial):
                idx = np.argwhere(sticky_fiducial)[0]
                return AnnotationConfig.get().find_idx_by_name(
                    Viewer.get().annotation_menu.sticky_fiducial_menu.actions(
                    )[idx[0]].text())
            # if 'sticky' fiducial option is off, check what key was pressed the last
            default_fiducial_idx = 0  # default: first fiducial
            if last_keypress_event_key is not None:
                qInfo('Last pressed: ' + str(last_keypress_event_key[1]))
                for fiducial_idx, f in enumerate(
                        AnnotationConfig.get().fiducials):
                    if f.key.lower() == last_keypress_event_key[1].lower():
                        return fiducial_idx
                return default_fiducial_idx
            else:
                return default_fiducial_idx

        def which_fiducial_to_delete(click_x):
            from gui.viewer import Viewer
            # first check if 'sticky' fiducial option is enabled for one of the fiducials
            sticky_fiducial = [
                item.isChecked() for item in
                Viewer.get().annotation_menu.sticky_fiducial_menu.actions()
            ]
            if any(sticky_fiducial):
                idx = np.argwhere(sticky_fiducial)[0]
                return AnnotationConfig.get().find_idx_by_name(
                    Viewer.get().annotation_menu.sticky_fiducial_menu.actions(
                    )[idx[0]].text())

            dist = np.inf
            fiducial_name, fiducial_idx = None, None
            for f_idx, f in enumerate(AnnotationConfig.get().fiducials):
                if f.annotation.x.size > 0:
                    closest_idx, _, _ = find_closest(f.annotation.x,
                                                     np.array([click_x]))
                    dist_new = abs(click_x - f.annotation.x[closest_idx])
                    if dist_new < dist:
                        dist = dist_new
                        fiducial_name, fiducial_idx = f.name, f_idx
            if not dist == np.inf:
                return fiducial_idx

        try:
            from gui.viewer import Viewer
            Viewer.get().selectFrame(self.display_panel.parent(
            ))  # first select the frame where the click was made

            if Mode.is_epoch_mode():
                EpochModeConfig.get().process_mouseclick(event)
                return

            vb = self.vbs[self.selected_view()]
            click_x = vb.mapSceneToView(event.pos()).x()
            if self.selected_view().track.label is Database.get(
            ).main_track_label:  # TODO: do this check properly and uniformly everywhere
                if Mode.is_annotation_mode():
                    if AnnotationConfig.get().is_valid():
                        if event.button(
                        ) == QtCore.Qt.LeftButton:  # Left click to mark
                            fiducial_idx = which_fiducial_to_add(
                                self.last_keypress_event_key)
                            AnnotationConfig.get().fiducials[
                                fiducial_idx].annotation.signal_annotate.emit(
                                    click_x)
                        elif event.button(
                        ) == pg.QtCore.Qt.RightButton:  # right click to delete
                            fiducial_idx = which_fiducial_to_delete(click_x)
                            if fiducial_idx is not None:
                                AnnotationConfig.get().fiducials[
                                    fiducial_idx].annotation.signal_delete_annotation.emit(
                                        click_x)
                            else:
                                qInfo('No annotation found to be deleted')
                        self.last_keypress_event_key = None  # need to press extra key every time to annotate secondary fiducial

                elif Mode.is_partition_mode():
                    if event.button() == QtCore.Qt.LeftButton:
                        if event.modifiers() == QtCore.Qt.ControlModifier:
                            self.create_new_partition(event)
                        else:
                            super().mousePressEvent(event)
                            qInfo(
                                'CTRL+Left: create region; SHIFT+Left: move region'
                            )  # event.accept()
                    elif event.button() == QtCore.Qt.RightButton:
                        if event.modifiers() == QtCore.Qt.ControlModifier:
                            p = Partitions.find_partition_by_point(click_x)
                            if p is not None:
                                p.region_deleted()  # event.accept()
                        elif event.modifiers() == QtCore.Qt.ShiftModifier:
                            p = Partitions.find_partition_by_point(click_x)
                            if p is not None:
                                self.partition_context_menu(event)
                            else:
                                qInfo(
                                    'No partition found...CTRL+Right: delete region; SHIFT+Right: region context menu'
                                )
                        else:
                            super().mousePressEvent(event)
                            qInfo(
                                'CTRL+Right: delete region; SHIFT+Right: region context menu'
                            )
                    else:
                        super().mousePressEvent(event)
                elif Mode.mode == Modes.browse:
                    super().mousePressEvent(event)

            else:
                if not self.is_main_view_in_current_panel(
                ):  # click on a panel, without the main track
                    Dialog().warningMessage(
                        'Selected display panel does not contain the main track ({}).\r\n'
                        .format(Database.get().main_track_label) +
                        'Try clicking on another display panel')
                else:  # click on a correct panel, but the main track is not selected
                    Dialog().warningMessage(
                        'Selected signal is not the main one.\r\n'
                        'Click on the '
                        '{}'
                        ' track in the control area on the right.'.format(
                            Database.get().main_track_label))
                return
        except Exception as e:
            Dialog().warningMessage('Mouse click processing failed\r\n'
                                    'What unusual did you do?\r\n' + str(e))
            return