Example #1
0
    def _analyze(self, cellanalyzer):
        n_images = 0
        stopwatch = StopWatch(start=True)
        crd = Coordinate(self.plate_id, self.position, self._frames,
                         list(set(self.ch_mapping.values())))


        for frame, channels in self._imagecontainer( \
            crd, interrupt_channel=True, interrupt_zslice=True):

            if self.isAborted():
                self.clear()
                return 0
            else:
                txt = 'T %d (%d/%d)' % (frame, self._frames.index(frame) + 1,
                                        len(self._frames))
                self.statusUpdate(progress=self._frames.index(frame) + 1,
                                  text=txt,
                                  interval=stopwatch.interim())

            stopwatch.reset(start=True)
            cellanalyzer.initTimepoint(frame)

            self.register_channels(cellanalyzer, channels)

            cellanalyzer.process()
            self.setup_classifiers()

            for chname, clf in self.classifiers.iteritems():
                try:
                    cellanalyzer.classify_objects(clf, chname)
                except KeyError as e:
                    pass
Example #2
0
    def _analyze(self, cellanalyzer):

        thread = QThread.currentThread()
        imax = sum([len(n) for n in self.sample_positions.values()])
        thread.statusUpdate(min=0, max=imax)

        stopwatch = StopWatch(start=True)
        crd = Coordinate(self.plate_id, self.position, self._frames,
                         list(set(self.ch_mapping.values())))

        for frame, channels in self._imagecontainer( \
            crd, interrupt_channel=True, interrupt_zslice=True):

            thread.interruption_point()
            txt = '%s, %s, T %d, (%d/%d)' \
                  %(self.plate_id, self.position,
                    frame, self._frames.index(frame)+1, len(self._frames))

            thread.statusUpdate(meta="Classifier training: ",
                                text=txt,
                                interval=stopwatch.interim(),
                                increment=True)

            stopwatch.reset(start=True)
            # initTimepoint clears channel_registry
            cellanalyzer.initTimepoint(frame)
            self.register_channels(cellanalyzer, channels)

            cellanalyzer.collectObjects(self.plate_id, self.position,
                                        self.sample_readers, self.learner)
Example #3
0
    def _analyze(self, cellanalyzer):
        super(PositionPicker, self)._analyze()
        n_images = 0
        stopwatch = StopWatch(start=True)
        crd = Coordinate(self.plate_id, self.position,
                         self._frames, list(set(self.ch_mapping.values())))

        for frame, channels in self._imagecontainer( \
            crd, interrupt_channel=True, interrupt_zslice=True):
            if self.is_aborted():
                return 0
            else:
                txt = 'T %d (%d/%d)' %(frame, self._frames.index(frame)+1,
                                       len(self._frames))
                self.update_status({'progress': self._frames.index(frame)+1,
                                   'text': txt,
                                   'interval': stopwatch.interim()})

            stopwatch.reset(start=True)
            # initTimepoint clears channel_registry
            cellanalyzer.initTimepoint(frame)
            self.register_channels(cellanalyzer, channels)
            image = cellanalyzer.collectObjects(self.plate_id,
                                                self.position,
                                                self.sample_readers,
                                                self.learner,
                                                byTime=True)

            if image is not None:
                n_images += 1
                msg = 'PL %s - P %s - T %05d' %(self.plate_id, self.position,
                                                frame)
                self.set_image(image, msg)
Example #4
0
 def _on_anntable_changed(self, current, previous):
     if not current is None:
         if self._imagecontainer.has_multiple_plates:
             offset = 0
             plate = self._ann_table.item(current.row(),
                                          self.COLUMN_ANN_PLATE).text()
         else:
             offset = 1
             plate = self._imagecontainer.plates[0]
         col = self.COLUMN_ANN_POSITION - offset
         position = self._ann_table.item(current.row(), col).text()
         col = self.COLUMN_ANN_TIME - offset
         time = int(self._ann_table.item(current.row(), col).text())
         coordinate = Coordinate(plate=plate, position=position, time=time)
         try:
             self.browser.set_coordinate(coordinate)
         except:
             exception(self, "Selected coordinate was not found. "
                             "Make sure the data and annotation match and "
                             "that the data was scanned/imported correctly.")
Example #5
0
File: browser.py Project: jni/cecog
    def __init__(self, settings, imagecontainer, parent=None):
        super(Browser, self).__init__(parent)
        self.setWindowTitle('Annotation Browser')

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer

        # These params are used by process_image and contour visualization
        self._detect_objects = False
        self._show_objects_by = 'color'
        self._object_region = None
        self._contour_color = '#000000'
        self._show_objects = True

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")


        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t-1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewers = {
                             'image'   : ImageViewer(frame, auto_resize=True),
                             'gallery' : GalleryViewer(frame)
                             }

        self.image_viewer = self.image_viewers['image']
        layout.addWidget(self.image_viewer , 0, 0)

        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = TSlider(Qt.Horizontal, frame)

        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)

        self._t_slider.setTickPosition(QSlider.NoTicks)
        self._t_slider.newValue.connect(self.on_time_changed_by_slider,
                                        Qt.DirectConnection)
        self._t_slider.valueChanged.connect(self.timeToolTip)
        self._imagecontainer.check_dimensions()

        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus
        act_close = self.create_action('Close',
                                        shortcut=QKeySequence('CTRL+C'),
                                        slot=self.close)

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action(
            'Next Plate', shortcut=QKeySequence('Shift+Alt+Down'),
                                            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action(
            'Previous Plate', shortcut=QKeySequence('Shift+Alt+Up'),
                                            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                         shortcut=QKeySequence('SHIFT+CTRL+R'),
                                         slot=self.on_act_autoresize,
                                         signal='triggered(bool)',
                                         checkable=True,
                                         checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action(
            'Full Screen',
            shortcut=QKeySequence('CTRL+F'),
            slot=self.on_act_fullscreen,
            signal='triggered(bool)',
            checkable=True,
            checked=False
            )
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action(
            'Show Object Contours',
            shortcut=QKeySequence('ALT+C'),
            slot=self.on_act_show_contours,
            signal='triggered(bool)',
            checkable=True,
            checked=self.image_viewer.show_contours
            )
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(view_menu, (act_resize, None,
                                     act_zoom100, act_zoomfit,
                                     act_zoomin, act_zoomout,
                                     None,
                                     act_prev_t, act_next_t,
                                     act_prev_pos, act_next_pos,
                                     act_prev_plate, act_next_plate,
                                     None,
                                     act_refresh,
                                     act_fullscreen, None,
                                     act_show_contours, None,
                                     act_anti, act_smooth,
                                     None, act_close))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)

        toolbar = self.addToolBar('Toolbar')
        toolbar.setObjectName('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        # fallback if no Segmentation plugins have been specified
        rdict = self._region_names()
        if len(rdict) > 0:
            self._object_region = rdict.keys()[0].split(' - ')
        else:
            self._object_region = ('Primary', 'primary')

        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)
        defautl_display_module = DisplayModule(
            self._module_manager, self, self._imagecontainer, rdict)

        self.set_display_module(defautl_display_module)
        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        try:
            CellH5EventModule(self._module_manager,
                              self, self._settings, self._imagecontainer)
        except Exception as e:
            warning(self, str(e))

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        self.layout = layout
        # process and display the first image
        self._restore_geometry()
        self._process_image()
Example #6
0
    def __init__(self, settings, imagecontainer):
        super(Browser, self).__init__()

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer
        self._show_objects = False
        self._object_region = None

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")


        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        #splitter.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,
        #                                   QSizePolicy.Expanding))
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        #splitter.setChildrenCollapsible(False)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t-1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewer = ImageViewer(frame, auto_resize=True)
        layout.addWidget(self.image_viewer, 0, 0)

        #self.image_viewer.image_mouse_dblclk.connect(self._on_dbl_clk)
        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = QSlider(Qt.Horizontal, frame)
        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)
#        self._t_slider.setMaximum(self.max_frame)

        self._t_slider.setTickPosition(QSlider.TicksBelow)
        self._t_slider.valueChanged.connect(self.on_time_changed_by_slider,
                                            Qt.DirectConnection)
        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action('Next Plate',
                                            shortcut=QKeySequence('Shift+Alt+Down'),
                                            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action('Previous Plate',
                                            shortcut=QKeySequence('Shift+Alt+Up'),
                                            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                         shortcut=QKeySequence('SHIFT+CTRL+R'),
                                         slot=self.on_act_autoresize,
                                         signal='triggered(bool)',
                                         checkable=True,
                                         checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action('Full Screen',
                                            shortcut=QKeySequence('CTRL+F'),
                                            slot=self.on_act_fullscreen,
                                            signal='triggered(bool)',
                                            checkable=True,
                                            checked=False)
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action('Show Object Contours',
                                               shortcut=QKeySequence('ALT+C'),
                                               slot=self.on_act_show_contours,
                                               signal='triggered(bool)',
                                               checkable=True,
                                               checked=self.image_viewer.show_contours)
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(view_menu, (act_resize, None,
                                     act_zoom100, act_zoomfit,
                                     act_zoomin, act_zoomout,
                                     None,
                                     act_prev_t, act_next_t,
                                     act_prev_pos, act_next_pos,
                                     act_prev_plate, act_next_plate,
                                     None,
                                     act_refresh,
                                     act_fullscreen, None,
                                     act_show_contours, None,
                                     act_anti, act_smooth,
                                     ))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)


        # tool bar
        toolbar = self.addToolBar('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        region_names = []
        for prefix in ['primary', 'secondary', 'tertiary']:
            region_names.extend(['%s - %s' % (prefix.capitalize(), name) \
                                 for name in REGION_INFO.names[prefix]])

        # FIXME: something went wrong with setting up the current region
        self._object_region = region_names[0].split(' - ')


        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)

        DisplayModule(self._module_manager, self, self._imagecontainer, region_names)

        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        # process and display the first image
        self._process_image()
Example #7
0
class Browser(QMainWindow):

    ZOOM_STEP = 1.05

    show_objects_toggled = pyqtSignal('bool')
    show_contours_toggled = pyqtSignal('bool')
    coordinates_changed = pyqtSignal(Coordinate)

    def __init__(self, settings, imagecontainer):
        super(Browser, self).__init__()

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer
        self._show_objects = False
        self._object_region = None

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")


        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        #splitter.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,
        #                                   QSizePolicy.Expanding))
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        #splitter.setChildrenCollapsible(False)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t-1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewer = ImageViewer(frame, auto_resize=True)
        layout.addWidget(self.image_viewer, 0, 0)

        #self.image_viewer.image_mouse_dblclk.connect(self._on_dbl_clk)
        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = QSlider(Qt.Horizontal, frame)
        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)
#        self._t_slider.setMaximum(self.max_frame)

        self._t_slider.setTickPosition(QSlider.TicksBelow)
        self._t_slider.valueChanged.connect(self.on_time_changed_by_slider,
                                            Qt.DirectConnection)
        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action('Next Plate',
                                            shortcut=QKeySequence('Shift+Alt+Down'),
                                            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action('Previous Plate',
                                            shortcut=QKeySequence('Shift+Alt+Up'),
                                            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                         shortcut=QKeySequence('SHIFT+CTRL+R'),
                                         slot=self.on_act_autoresize,
                                         signal='triggered(bool)',
                                         checkable=True,
                                         checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action('Full Screen',
                                            shortcut=QKeySequence('CTRL+F'),
                                            slot=self.on_act_fullscreen,
                                            signal='triggered(bool)',
                                            checkable=True,
                                            checked=False)
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action('Show Object Contours',
                                               shortcut=QKeySequence('ALT+C'),
                                               slot=self.on_act_show_contours,
                                               signal='triggered(bool)',
                                               checkable=True,
                                               checked=self.image_viewer.show_contours)
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(view_menu, (act_resize, None,
                                     act_zoom100, act_zoomfit,
                                     act_zoomin, act_zoomout,
                                     None,
                                     act_prev_t, act_next_t,
                                     act_prev_pos, act_next_pos,
                                     act_prev_plate, act_next_plate,
                                     None,
                                     act_refresh,
                                     act_fullscreen, None,
                                     act_show_contours, None,
                                     act_anti, act_smooth,
                                     ))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)


        # tool bar
        toolbar = self.addToolBar('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        region_names = []
        for prefix in ['primary', 'secondary', 'tertiary']:
            region_names.extend(['%s - %s' % (prefix.capitalize(), name) \
                                 for name in REGION_INFO.names[prefix]])

        # FIXME: something went wrong with setting up the current region
        self._object_region = region_names[0].split(' - ')


        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)

        DisplayModule(self._module_manager, self, self._imagecontainer, region_names)

        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        # process and display the first image
        self._process_image()


    def create_action(self, text, slot=None, shortcut=None, icon=None,
                      tooltip=None, checkable=None, signal='triggered()',
                      checked=False):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(':/%s.png' % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tooltip is not None:
            action.setToolTip(tooltip)
            action.setStatusTip(tooltip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot, Qt.DirectConnection)
        if checkable is not None:
            action.setCheckable(True)
        action.setChecked(checked)
        return action

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def set_coords(self, coords):
        self.image_viewer.remove_objects()
        self.image_viewer.set_objects_by_crackcoords(coords)
        widget = self._module_manager.get_widget(AnnotationModule.NAME)
        widget.set_coords()

    def show_image(self, image_dict):
        widget = self._module_manager.get_widget(DisplayModule.NAME)
        widget.set_image_dict(image_dict)
        self.update_statusbar()

    def update_statusbar(self):
        meta_data = self._imagecontainer.get_meta_data()
        if meta_data.has_timelapse:
            timestamp = meta_data.get_timestamp_relative(self.coordinate)
            time_info = ' | Frame: %d' % self.coordinate.time

            if not numpy.isnan(timestamp):
                time_info += ' (%.1f min)' % (timestamp / 60)
        else:
            time_info = ''
        msg = 'Plate: %s | Position: %s%s ||  Zoom: %.1f%%' % \
              (self.coordinate.plate, self.coordinate.position, time_info,
               self.image_viewer.scale_factor*100)
        self._statusbar.showMessage(msg)

    def get_coordinate(self):
        return self.coordinate.copy()

    def on_coordinate_changed(self, coordinate):
        """
        All coordinate changes are handled via the Navigator. The change event
        from the Navigator is processed here and further propagated via
        a new Browser event (the Modules are not supposed to know each other).
        """

        self.coordinate = coordinate.copy()
        self._t_slider.blockSignals(True)
        self._imagecontainer.set_plate(coordinate.plate)

        # the slider is always working with frames.
        # reason: it is difficult to forbid slider values between allowed values.

        frame = int(round(self.max_frame * (coordinate.time - self.min_time) /
                          max(float(self.max_time - self.min_time), 1)))

        self._t_slider.setValue(frame)

        self._t_slider.blockSignals(False)
        self._process_image()
        # propagate the signal further to other modules
        self.coordinates_changed.emit(coordinate)

    def set_coordinate(self, coordinate):
        """
        Changes the Navigator to a fixed coordinate
        """
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_coordinate(coordinate)

    def _process_image(self):
        settings = _ProcessorMixin.get_special_settings(self._settings)
        settings.set_section('General')
        settings.set2('constrain_positions', True)
        settings.set2('positions', self.coordinate.position)
        settings.set2('redofailedonly', False)
        settings.set2('framerange', True)
        settings.set2('framerange_begin', self.coordinate.time)
        settings.set2('framerange_end', self.coordinate.time)

        settings.set_section('ObjectDetection')
        prim_id = PrimaryChannel.NAME
        #sec_id = SecondaryChannel.NAME
        #sec_regions = settings.get2('secondary_regions')
        settings.set_section('Processing')
        settings.set2('primary_classification', False)
        settings.set2('secondary_classification', False)
        settings.set2('tertiary_classification', False)
        settings.set2('merged_classification', False)
        settings.set2('primary_featureextraction', False)
        settings.set2('secondary_featureextraction', False)

        settings.set2('objectdetection', self._show_objects)
        settings.set2('tracking', False)
        settings.set_section('Output')
        settings.set2('rendering_contours_discwrite', False)
        settings.set2('rendering_class_discwrite', False)
        settings.set2('export_object_counts', False)
        settings.set2('export_object_details', False)
        settings.set2('export_track_data', False)
        settings.set2('hdf5_create_file', False)
        settings.set_section('Classification')
        settings.set2('collectsamples', False)
        settings.set('General', 'rendering', {})
        settings.set('General', 'rendering_class', {})
        settings.set('Output', 'events_export_gallery_images', False)

        # turn of output:
        settings.set('Output', 'export_object_counts', False)
        settings.set('Output', 'export_object_details', False)
        settings.set('Output', 'export_file_names', False)
        settings.set('Output', 'events_export_gallery_images', False)
        settings.set('Output', 'export_track_data', False)
        settings.set('Output', 'export_tracking_as_dot', False)

        nchannels = len(self._imagecontainer.channels)

        # XXX channel mapping unclear
        # processing channel <--> color channel
        # i.e problems if 2 processing channels have the
        # same color
        if nchannels == 2:
            settings.set('Processing', 'secondary_processChannel', True)
        elif nchannels == 3:
            settings.set('Processing', 'secondary_processChannel', True)
            settings.set('Processing', 'tertiary_processChannel', True)
        # need turn of virtual channels
        settings.set('Processing', 'merged_processChannel', False)

        settings.set('General', 'rendering', {})
        analyzer = AnalyzerCore(self.coordinate.plate, settings,
                                self._imagecontainer)

        # as long the GIL is not released, if GIL is released
        # just use self.setCursor
        
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            analyzer.processPositions(myhack=self)
        except Exception, e:
            import traceback
            traceback.print_exc()
            raise(e)
        finally:
Example #8
0
    def _analyze(self, cellanalyzer):
        super(PositionAnalyzer, self)._analyze()
        n_images = 0
        stopwatch = StopWatch(start=True)
        crd = Coordinate(self.plate_id, self.position,
                         self._frames, list(set(self.ch_mapping.values())))

        minimal_effort = self.settings.get('Output', 'minimal_effort') and self.settings.get('Output', 'hdf5_reuse')

        for frame, channels in self._imagecontainer( \
            crd, interrupt_channel=True, interrupt_zslice=True):

            if self.is_aborted():
                self.clear()
                return 0
            else:
                txt = 'T %d (%d/%d)' %(frame, self._frames.index(frame)+1,
                                       len(self._frames))
                self.update_status({'progress': self._frames.index(frame)+1,
                                    'text': txt,
                                    'interval': stopwatch.interim()})

            stopwatch.reset(start=True)
            cellanalyzer.initTimepoint(frame)
            self.register_channels(cellanalyzer, channels)

            cellanalyzer.process()

            self.logger.info(" - Frame %d, cellanalyzer.process (ms): %3d" \
                             %(frame, stopwatch.interval()*1000))

            n_images += 1
            images = []

            if self.settings('Processing', 'tracking'):
                region = self.settings('Tracking', 'region')
                samples = self.timeholder[frame][PrimaryChannel.NAME].get_region(region)
                self._tracker.track_next_frame(frame, samples)

                if self.settings('Tracking', 'tracking_visualization'):
                    size = cellanalyzer.getImageSize(PrimaryChannel.NAME)
                    nframes = self.settings('Tracking', 'tracking_visualize_track_length')
                    radius = self.settings('Tracking', 'tracking_centroid_radius')
                    img_conn, img_split = self._tracker.render_tracks(
                        frame, size, nframes, radius)
                    images += [(img_conn, '#FFFF00', 1.0),
                               (img_split, '#00FFFF', 1.0)]

            self.logger.info(" - Frame %d, Tracking (ms): %3d" \
                             %(frame, stopwatch.interval()*1000))

            # can't cluster on a per frame basis
            if self.settings("EventSelection", "supervised_event_selection"):
                for clf in self.classifiers.itervalues():
                    cellanalyzer.classify_objects(clf)

            self.logger.info(" - Frame %d, Classification (ms): %3d" \
                             % (frame, stopwatch.interval()*1000))

            self.settings.set_section('General')
            # want emit all images at once
            if not minimal_effort:
                imgs = {}
                imgs.update(self.render_classification_images(cellanalyzer, images, frame))
                imgs.update(self.render_contour_images(cellanalyzer, images, frame))
                msg = 'PL %s - P %s - T %05d' %(self.plate_id, self.position, frame)
                self.set_image(imgs, msg, 50)

                if self.settings('Output', 'rendering_channel_gallery'):
                    self.render_channel_gallery(cellanalyzer, frame)

                if self.settings('Output', 'rendering_labels_discwrite'):
                    cellanalyzer.exportLabelImages(self._labels_dir)

            cellanalyzer.purge(features=self.export_features)
            self.logger.info(" - Frame %d, rest (ms): %3d" \
                                 %(frame, stopwatch.interval()*1000))
            self.logger.info(" - Frame %d, duration (ms): %3d" \
                                 %(frame, stopwatch.interim()*1000))


        return n_images
Example #9
0
    def full_tracks(self, timeholder, visitor_data, position, outdir):
        shutil.rmtree(outdir, True)
        makedirs(outdir)

        for start_id, data in visitor_data.iteritems():
            for idx, track in enumerate(data['_full_tracks']):
                has_header = False
                line1 = []
                line2 = []
                line3 = []

                frame, obj_label = Tracker.split_nodeid(start_id)[:2]
                filename = 'P%s__T%05d__O%04d__B%02d.txt' \
                    %(position, frame, obj_label, idx+1)
                f = file(join(outdir, filename), 'w')

                for node_id in track:
                    frame, obj_id = Tracker.split_nodeid(node_id)

                    coordinate = Coordinate(position=position, time=frame)
                    prefix = [
                        frame,
                        self.meta_data.get_timestamp_relative(coordinate),
                        obj_id
                    ]
                    prefix_names = ['frame', 'time', 'objID']
                    items = []

                    for channel in timeholder[frame].values():
                        for region_id in channel.region_names():
                            region = channel.get_region(region_id)
                            if obj_id in region:
                                flkp = self._map_feature_names(
                                    region.feature_names)
                                if not has_header:
                                    keys = ['classLabel', 'className']
                                    if channel.NAME == 'Primary':
                                        keys += ['centerX', 'centerY']
                                    keys += flkp.keys()
                                    line1 += [channel.NAME.upper()] * len(keys)
                                    line2 += [str(region_id)] * len(keys)
                                    line3 += keys
                                obj = region[obj_id]
                                features = region.features_by_name(
                                    obj_id, flkp.values())
                                values = [
                                    x if not x is None else ''
                                    for x in [obj.iLabel, obj.strClassName]
                                ]
                                if channel.NAME == 'Primary':
                                    values += [
                                        obj.oCenterAbs[0], obj.oCenterAbs[1]
                                    ]
                                values += list(features)
                                items.extend(values)

                    if not has_header:
                        has_header = True
                        prefix_str = [''] * len(prefix)
                        line1 = prefix_str + line1
                        line2 = prefix_str + line2
                        line3 = prefix_names + line3
                        f.write('%s\n' % CSVParams.sep.join(line1))
                        f.write('%s\n' % CSVParams.sep.join(line2))
                        f.write('%s\n' % CSVParams.sep.join(line3))

                    f.write(
                        '%s\n' %
                        CSVParams.sep.join([str(i) for i in prefix + items]))
                f.close()
Example #10
0
    def _analyze(self, cellanalyzer):

        thread = QThread.currentThread()

        stopwatch = StopWatch(start=True)
        crd = Coordinate(self.plate_id, self.position, self._frames,
                         list(set(self.ch_mapping.values())))

        for frame, channels in self._imagecontainer( \
            crd, interrupt_channel=True, interrupt_zslice=True):

            self.interruptionPoint()
            txt = '%s, %s, T %d (%d/%d)' \
                  %(self.plate_id, self.position, frame,
                    self._frames.index(frame)+1, len(self._frames))

            self.statusUpdate(text=txt,
                              interval=stopwatch.interim(),
                              increment=True)

            stopwatch.reset(start=True)
            cellanalyzer.initTimepoint(frame)
            self.register_channels(cellanalyzer, channels)

            cellanalyzer.process()

            self.logger.debug(" - Frame %d, cellanalyzer.process (ms): %3d" \
                             %(frame, stopwatch.interval()*1000))

            images = []

            if self.settings('Processing', 'tracking'):
                apc = AppPreferences()
                region = self.settings('Tracking', 'region')
                samples = self.timeholder[frame][
                    PrimaryChannel.NAME].get_region(region)
                self._tracker.track_next_frame(frame, samples)

                if apc.display_tracks:
                    size = cellanalyzer.getImageSize(PrimaryChannel.NAME)
                    img_conn, img_split = self._tracker.render_tracks(
                        frame, size, apc.track_length, apc.cradius)
                    images += [(img_conn, '#FFFF00', 1.0),
                               (img_split, '#00FFFF', 1.0)]

            self.logger.debug(" - Frame %d, Tracking (ms): %3d" \
                             %(frame, stopwatch.interval()*1000))

            # can't cluster on a per frame basis
            if self.settings("EventSelection", "supervised_event_selection"):
                for channel, clf in self.classifiers.iteritems():
                    cellanalyzer.classify_objects(clf, channel)

            self.logger.debug(" - Frame %d, Classification (ms): %3d" \
                             % (frame, stopwatch.interval()*1000))

            self.settings.set_section('General')
            # want emit all images at once

            imgs = {}
            imgs.update(
                self.render_classification_images(cellanalyzer, images, frame))
            imgs.update(self.render_contour_images(cellanalyzer, images,
                                                   frame))
            msg = 'PL %s - P %s - T %05d' % (self.plate_id, self.position,
                                             frame)
            self.setImage(imgs, msg, 50)

            cellanalyzer.purge(features=self.export_features)
            self.logger.debug(" - Frame %d, duration (ms): %3d" \
                              %(frame, stopwatch.interim()*1000))
Example #11
0
    def _data_per_channel(self, timeholder, event_data, filename, channel_name,
                          region_name, feature_names, position):

        eventid = event_data['eventId']
        event_frame, _ = Tracker.split_nodeid(eventid)
        has_split = 'splitId' in event_data

        header_names = ['Frame', 'Timestamp', 'isEvent']
        if has_split:
            header_names.append('isSplit')
            if event_data['splitId'] is not None:
                split_frame, _ = Tracker.split_nodeid(event_data['splitId'])
            else:
                split_frame = None

        table = []
        # zip nodes with same time together
        for nodeids in zip(*event_data['tracks']):
            objids = []
            frame = None
            for nodeid in nodeids:
                node_frame, objid = Tracker.split_nodeid(nodeid)
                if frame is None:
                    frame = node_frame
                else:
                    assert frame == node_frame
                objids.append(objid)

            channel = timeholder[frame][channel_name]
            sample_holder = channel.get_region(region_name)

            if feature_names is None:
                feature_names = sample_holder.feature_names

            if CSVParams.objId not in header_names:
                # setup header line
                header_names.append(CSVParams.objId)
                header_names += [
                    CSVParams.class_ % x
                    for x in ['name', 'label', 'probability']
                ]
                # only feature_names scales according to settings
                header_names += [
                    CSVParams.feature % fn for fn in feature_names
                ]
                header_names += [
                    CSVParams.tracking % tf
                    for tf in CSVParams.tracking_features
                ]

            coordinate = Coordinate(position=position, time=frame)
            data = {
                'Frame': frame,
                'Timestamp': self.meta_data.get_timestamp_relative(coordinate),
                'isEvent': int(frame == event_frame)
            }

            if has_split:
                data['isSplit'] = int(frame == split_frame)

            #for iIdx, iObjId in enumerate(lstObjectIds):
            objid = objids[0]
            if objid in sample_holder:
                sample = sample_holder[objid]
                data[CSVParams.objId] = objid

                # classification data
                if sample.iLabel is not None:
                    data[CSVParams.class_ % 'label'] = sample.iLabel
                    data[CSVParams.class_ % 'name'] = sample.strClassName
                    data[CSVParams.class_ %'probability'] = \
                        ','.join(['%d:%.5f' % (int(x),y) for x,y in
                                  sample.dctProb.iteritems()])

                common_ftr = [
                    f for f in set(sample_holder.feature_names).intersection(
                        feature_names)
                ]
                features = sample_holder.features_by_name(objid, common_ftr)
                for feature, fname in zip(features, common_ftr):
                    data[CSVParams.feature % fname] = feature

                # features not calculated are exported as NAN
                diff_ftr = [
                    f for f in set(feature_names).difference(
                        sample_holder.feature_names)
                ]
                for df in diff_ftr:
                    data[CSVParams.feature % df] = float("NAN")

                # object tracking data (absolute center)
                data[CSVParams.tracking % 'center_x'] = sample.oCenterAbs[0]
                data[CSVParams.tracking % 'center_y'] = sample.oCenterAbs[1]
                data[CSVParams.tracking %
                     'upperleft_x'] = sample.oRoi.upperLeft[0]
                data[CSVParams.tracking %
                     'upperleft_y'] = sample.oRoi.upperLeft[1]
                data[CSVParams.tracking %
                     'lowerright_x'] = sample.oRoi.lowerRight[0]
                data[CSVParams.tracking %
                     'lowerright_y'] = sample.oRoi.lowerRight[1]
            else:
                # we rather skip the entire event in case the object ID is not valid
                return
            table.append(data)

        if len(table) > 0:
            with open(filename, 'wb') as fp:
                writer = csv.DictWriter(fp,
                                        fieldnames=header_names,
                                        delimiter=CSVParams.sep)
                writer.writeheader()
                writer.writerows(table)
Example #12
0
    def __init__(self, settings, imagecontainer):
        super(Browser, self).__init__()

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer
        self._show_objects = False
        self._object_region = None

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")

        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        #splitter.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,
        #                                   QSizePolicy.Expanding))
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        #splitter.setChildrenCollapsible(False)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t - 1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewer = ImageViewer(frame, auto_resize=True)
        layout.addWidget(self.image_viewer, 0, 0)

        #self.image_viewer.image_mouse_dblclk.connect(self._on_dbl_clk)
        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = QSlider(Qt.Horizontal, frame)
        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)
        #        self._t_slider.setMaximum(self.max_frame)

        self._t_slider.setTickPosition(QSlider.TicksBelow)
        self._t_slider.valueChanged.connect(self.on_time_changed_by_slider,
                                            Qt.DirectConnection)
        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action(
            'Next Plate',
            shortcut=QKeySequence('Shift+Alt+Down'),
            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action(
            'Previous Plate',
            shortcut=QKeySequence('Shift+Alt+Up'),
            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                        shortcut=QKeySequence('SHIFT+CTRL+R'),
                                        slot=self.on_act_autoresize,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action('Full Screen',
                                            shortcut=QKeySequence('CTRL+F'),
                                            slot=self.on_act_fullscreen,
                                            signal='triggered(bool)',
                                            checkable=True,
                                            checked=False)
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action(
            'Show Object Contours',
            shortcut=QKeySequence('ALT+C'),
            slot=self.on_act_show_contours,
            signal='triggered(bool)',
            checkable=True,
            checked=self.image_viewer.show_contours)
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(view_menu, (
            act_resize,
            None,
            act_zoom100,
            act_zoomfit,
            act_zoomin,
            act_zoomout,
            None,
            act_prev_t,
            act_next_t,
            act_prev_pos,
            act_next_pos,
            act_prev_plate,
            act_next_plate,
            None,
            act_refresh,
            act_fullscreen,
            None,
            act_show_contours,
            None,
            act_anti,
            act_smooth,
        ))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)

        # tool bar
        toolbar = self.addToolBar('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        region_names = []
        for prefix in ['primary', 'secondary', 'tertiary']:
            region_names.extend(['%s - %s' % (prefix.capitalize(), name) \
                                 for name in REGION_INFO.names[prefix]])

        # FIXME: something went wrong with setting up the current region
        self._object_region = region_names[0].split(' - ')

        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)

        DisplayModule(self._module_manager, self, self._imagecontainer,
                      region_names)

        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        # process and display the first image
        self._process_image()
Example #13
0
File: browser.py Project: jni/cecog
class Browser(QMainWindow):

    ZOOM_STEP = 1.05

    show_objects_toggled = pyqtSignal('bool')
    show_contours_toggled = pyqtSignal('bool')
    #coordinates_changed = pyqtSignal(Coordinate)
    update_regions = pyqtSignal(dict)

    def __init__(self, settings, imagecontainer, parent=None):
        super(Browser, self).__init__(parent)
        self.setWindowTitle('Annotation Browser')

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer

        # These params are used by process_image and contour visualization
        self._detect_objects = False
        self._show_objects_by = 'color'
        self._object_region = None
        self._contour_color = '#000000'
        self._show_objects = True

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")


        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t-1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewers = {
                             'image'   : ImageViewer(frame, auto_resize=True),
                             'gallery' : GalleryViewer(frame)
                             }

        self.image_viewer = self.image_viewers['image']
        layout.addWidget(self.image_viewer , 0, 0)

        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = TSlider(Qt.Horizontal, frame)

        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)

        self._t_slider.setTickPosition(QSlider.NoTicks)
        self._t_slider.newValue.connect(self.on_time_changed_by_slider,
                                        Qt.DirectConnection)
        self._t_slider.valueChanged.connect(self.timeToolTip)
        self._imagecontainer.check_dimensions()

        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus
        act_close = self.create_action('Close',
                                        shortcut=QKeySequence('CTRL+C'),
                                        slot=self.close)

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action(
            'Next Plate', shortcut=QKeySequence('Shift+Alt+Down'),
                                            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action(
            'Previous Plate', shortcut=QKeySequence('Shift+Alt+Up'),
                                            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                         shortcut=QKeySequence('SHIFT+CTRL+R'),
                                         slot=self.on_act_autoresize,
                                         signal='triggered(bool)',
                                         checkable=True,
                                         checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action(
            'Full Screen',
            shortcut=QKeySequence('CTRL+F'),
            slot=self.on_act_fullscreen,
            signal='triggered(bool)',
            checkable=True,
            checked=False
            )
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action(
            'Show Object Contours',
            shortcut=QKeySequence('ALT+C'),
            slot=self.on_act_show_contours,
            signal='triggered(bool)',
            checkable=True,
            checked=self.image_viewer.show_contours
            )
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(view_menu, (act_resize, None,
                                     act_zoom100, act_zoomfit,
                                     act_zoomin, act_zoomout,
                                     None,
                                     act_prev_t, act_next_t,
                                     act_prev_pos, act_next_pos,
                                     act_prev_plate, act_next_plate,
                                     None,
                                     act_refresh,
                                     act_fullscreen, None,
                                     act_show_contours, None,
                                     act_anti, act_smooth,
                                     None, act_close))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)

        toolbar = self.addToolBar('Toolbar')
        toolbar.setObjectName('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        # fallback if no Segmentation plugins have been specified
        rdict = self._region_names()
        if len(rdict) > 0:
            self._object_region = rdict.keys()[0].split(' - ')
        else:
            self._object_region = ('Primary', 'primary')

        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)
        defautl_display_module = DisplayModule(
            self._module_manager, self, self._imagecontainer, rdict)

        self.set_display_module(defautl_display_module)
        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        try:
            CellH5EventModule(self._module_manager,
                              self, self._settings, self._imagecontainer)
        except Exception as e:
            warning(self, str(e))

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        self.layout = layout
        # process and display the first image
        self._restore_geometry()
        self._process_image()

    def closeEvent(self, event):
        self._save_geometry()

    def _save_geometry(self):
        settings = QSettings(version.organisation, version.appname)
        settings.beginGroup('AnnotationBrowser')
        settings.setValue('state', self.saveState())
        settings.setValue('geometry', self.saveGeometry())
        settings.endGroup()

    def _restore_geometry(self):
        settings = QSettings(version.organisation, version.appname)
        settings.beginGroup('AnnotationBrowser')

        if settings.contains('geometry'):
            self.restoreGeometry(settings.value('geometry'))

        if settings.contains('state'):
            self.restoreState(settings.value('state'))
        settings.endGroup()

    def _region_names(self):

        rdict = OrderedDict()
        reginfo = MetaPluginManager().region_info
        for channel, regions in reginfo.names.iteritems():
            for region in regions:
                rdict['%s - %s' % (channel.capitalize(), region)] = \
                    (channel.capitalize(), region)
        return rdict

    def set_image_viewer(self, viewer_type):
        self.image_viewer.hide()
        self.layout.removeWidget(self.image_viewer)
        self.image_viewer = self.image_viewers[viewer_type]
        self.layout.addWidget(self.image_viewer, 0, 0)
        self.image_viewer.show()

    def create_action(self, text, slot=None, shortcut=None, icon=None,
                      tooltip=None, checkable=None, signal='triggered()',
                      checked=False):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(':/%s.png' % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tooltip is not None:
            action.setToolTip(tooltip)
            action.setStatusTip(tooltip)
        if slot is not None:
            if signal == "triggered()":
                action.triggered.connect(slot, Qt.DirectConnection)
            else:
                action.triggered[bool].connect(slot, Qt.DirectConnection)
        if checkable is not None:
            action.setCheckable(True)
        action.setChecked(checked)
        return action

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def set_coords(self, coords):
        self.image_viewer.set_objects_by_crackcoords(coords)
        widget = self._module_manager.get_widget(AnnotationModule.NAME)
        widget.set_coords()

    def set_classified_crack_contours(self, coords):
        self.image_viewer.set_objects_by_crackcoords_with_colors(coords)
        widget = self._module_manager.get_widget(AnnotationModule.NAME)
        widget.set_coords()

    def show_image(self, image_dict):
        widget = self.get_display_module()
        widget.set_image_dict(image_dict)
        self.update_statusbar()

    def set_display_module(self, display_module ):
        self.display_module = display_module

    def get_display_module(self):
        return self.display_module

    def update_statusbar(self):
        meta_data = self._imagecontainer.get_meta_data()
        if meta_data.has_timelapse:
            timestamp = meta_data.get_timestamp_relative(self.coordinate)
            time_info = ' | Frame: %d' % self.coordinate.time

            if not numpy.isnan(timestamp):
                time_info += ' (%.1f min)' % (timestamp / 60)
        else:
            time_info = ''
        msg = 'Plate: %s | Position: %s%s ||  Zoom: %.1f%%' % \
              (self.coordinate.plate, self.coordinate.position, time_info,
               self.image_viewer.scalefactor*100)
        self._statusbar.showMessage(msg)

    def get_coordinate(self):
        return self.coordinate.copy()

    def on_coordinate_changed(self, coordinate):
        """
        All coordinate changes are handled via the Navigator. The change event
        from the Navigator is processed here and further propagated via
        a new Browser event (the Modules are not supposed to know each other).
        """

        self.coordinate = coordinate.copy()
        self._t_slider.blockSignals(True)
        self._imagecontainer.set_plate(coordinate.plate)
        self._t_slider.setValue(coordinate.time)

        self._t_slider.blockSignals(False)
        self._process_image()
        # propagate the signal further to other modules
        #self.coordinates_changed.emit(coordinate)

    def set_coordinate(self, coordinate):
        """
        Changes the Navigator to a fixed coordinate
        """
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_coordinate(coordinate)

    def _process_image(self, ):
        self.image_viewer.remove_objects()
        settings = BaseProcessorFrame.get_special_settings(self._settings)
        settings.set_section('General')
        settings.set2('constrain_positions', True)
        settings.set2('positions', self.coordinate.position)
        settings.set2('redofailedonly', False)
        settings.set2('framerange', True)
        settings.set2('framerange_begin', self.coordinate.time)
        settings.set2('framerange_end', self.coordinate.time)

        settings.set_section('Processing')
        _classify_objects = self._show_objects_by == 'classification'

        settings.set2('primary_classification', _classify_objects )
        settings.set2('secondary_classification', _classify_objects)
        settings.set2('tertiary_classification', _classify_objects)
        settings.set2('merged_classification', _classify_objects)
        settings.set2('primary_featureextraction', _classify_objects)
        settings.set2('secondary_featureextraction', _classify_objects)

        settings.set2('objectdetection', self._detect_objects)
        settings.set2('tracking', False)
        settings.set_section('Output')
        settings.set2('rendering_contours_discwrite', False)
        settings.set2('rendering_class_discwrite', False)
        settings.set2('export_object_counts', False)
        settings.set2('export_object_details', False)
        settings.set2('export_track_data', False)
        settings.set2('hdf5_create_file', False)
        settings.set_section('Classification')
        settings.set2('collectsamples', False)
        settings.set('General', 'rendering', {})
        settings.set('General', 'rendering_class', {})
        settings.set('Output', 'events_export_gallery_images', False)

        # turn of output:
        settings.set('Output', 'export_object_counts', False)
        settings.set('Output', 'export_object_details', False)
        settings.set('Output', 'export_file_names', False)
        settings.set('Output', 'events_export_gallery_images', False)
        settings.set('Output', 'export_track_data', False)
        settings.set('Output', 'export_tracking_as_dot', False)

        nchannels = len(self._imagecontainer.channels)
        # XXX channel mapping unclear
        # processing channel <--> color channel
        # i.e problems if 2 processing channels have the same color
        if nchannels == 2:
            settings.set('General', 'process_secondary', True)
        elif nchannels >= 3:
            settings.set('General', 'process_secondary', True)
            settings.set('General', 'process_tertiary', True)

        settings.set('General', 'rendering', {})
        analyzer = AnalyzerBrowser(self.coordinate.plate,
                                   settings,
                                   self._imagecontainer)

        res = None
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            res = analyzer.processPositions()
            self.render_browser(res)
        except Exception, e:
            import traceback
            from cecog.gui.util import exception
            traceback.print_exc()
            exception(self, str(e))
            raise
        finally:
Example #14
0
class Browser(QMainWindow):

    ZOOM_STEP = 1.05

    show_objects_toggled = pyqtSignal('bool')
    show_contours_toggled = pyqtSignal('bool')
    coordinates_changed = pyqtSignal(Coordinate)

    def __init__(self, settings, imagecontainer):
        super(Browser, self).__init__()

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer
        self._show_objects = False
        self._object_region = None

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")

        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        #splitter.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,
        #                                   QSizePolicy.Expanding))
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        #splitter.setChildrenCollapsible(False)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t - 1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewer = ImageViewer(frame, auto_resize=True)
        layout.addWidget(self.image_viewer, 0, 0)

        #self.image_viewer.image_mouse_dblclk.connect(self._on_dbl_clk)
        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = QSlider(Qt.Horizontal, frame)
        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)
        #        self._t_slider.setMaximum(self.max_frame)

        self._t_slider.setTickPosition(QSlider.TicksBelow)
        self._t_slider.valueChanged.connect(self.on_time_changed_by_slider,
                                            Qt.DirectConnection)
        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action(
            'Next Plate',
            shortcut=QKeySequence('Shift+Alt+Down'),
            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action(
            'Previous Plate',
            shortcut=QKeySequence('Shift+Alt+Up'),
            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                        shortcut=QKeySequence('SHIFT+CTRL+R'),
                                        slot=self.on_act_autoresize,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action('Full Screen',
                                            shortcut=QKeySequence('CTRL+F'),
                                            slot=self.on_act_fullscreen,
                                            signal='triggered(bool)',
                                            checkable=True,
                                            checked=False)
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action(
            'Show Object Contours',
            shortcut=QKeySequence('ALT+C'),
            slot=self.on_act_show_contours,
            signal='triggered(bool)',
            checkable=True,
            checked=self.image_viewer.show_contours)
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(view_menu, (
            act_resize,
            None,
            act_zoom100,
            act_zoomfit,
            act_zoomin,
            act_zoomout,
            None,
            act_prev_t,
            act_next_t,
            act_prev_pos,
            act_next_pos,
            act_prev_plate,
            act_next_plate,
            None,
            act_refresh,
            act_fullscreen,
            None,
            act_show_contours,
            None,
            act_anti,
            act_smooth,
        ))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)

        # tool bar
        toolbar = self.addToolBar('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        region_names = []
        for prefix in ['primary', 'secondary', 'tertiary']:
            region_names.extend(['%s - %s' % (prefix.capitalize(), name) \
                                 for name in REGION_INFO.names[prefix]])

        # FIXME: something went wrong with setting up the current region
        self._object_region = region_names[0].split(' - ')

        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)

        DisplayModule(self._module_manager, self, self._imagecontainer,
                      region_names)

        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        # process and display the first image
        self._process_image()

    def create_action(self,
                      text,
                      slot=None,
                      shortcut=None,
                      icon=None,
                      tooltip=None,
                      checkable=None,
                      signal='triggered()',
                      checked=False):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(':/%s.png' % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tooltip is not None:
            action.setToolTip(tooltip)
            action.setStatusTip(tooltip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot, Qt.DirectConnection)
        if checkable is not None:
            action.setCheckable(True)
        action.setChecked(checked)
        return action

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def set_coords(self, coords):
        self.image_viewer.remove_objects()
        self.image_viewer.set_objects_by_crackcoords(coords)
        widget = self._module_manager.get_widget(AnnotationModule.NAME)
        widget.set_coords()

    def show_image(self, image_dict):
        widget = self._module_manager.get_widget(DisplayModule.NAME)
        widget.set_image_dict(image_dict)
        self.update_statusbar()

    def update_statusbar(self):
        meta_data = self._imagecontainer.get_meta_data()
        if meta_data.has_timelapse:
            timestamp = meta_data.get_timestamp_relative(self.coordinate)
            time_info = ' | Frame: %d' % self.coordinate.time

            if not numpy.isnan(timestamp):
                time_info += ' (%.1f min)' % (timestamp / 60)
        else:
            time_info = ''
        msg = 'Plate: %s | Position: %s%s ||  Zoom: %.1f%%' % \
              (self.coordinate.plate, self.coordinate.position, time_info,
               self.image_viewer.scale_factor*100)
        self._statusbar.showMessage(msg)

    def get_coordinate(self):
        return self.coordinate.copy()

    def on_coordinate_changed(self, coordinate):
        """
        All coordinate changes are handled via the Navigator. The change event
        from the Navigator is processed here and further propagated via
        a new Browser event (the Modules are not supposed to know each other).
        """

        self.coordinate = coordinate.copy()
        self._t_slider.blockSignals(True)
        self._imagecontainer.set_plate(coordinate.plate)

        # the slider is always working with frames.
        # reason: it is difficult to forbid slider values between allowed values.

        frame = int(
            round(self.max_frame * (coordinate.time - self.min_time) /
                  max(float(self.max_time - self.min_time), 1)))

        self._t_slider.setValue(frame)

        self._t_slider.blockSignals(False)
        self._process_image()
        # propagate the signal further to other modules
        self.coordinates_changed.emit(coordinate)

    def set_coordinate(self, coordinate):
        """
        Changes the Navigator to a fixed coordinate
        """
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_coordinate(coordinate)

    def _process_image(self):
        settings = _ProcessorMixin.get_special_settings(self._settings)
        settings.set_section('General')
        settings.set2('constrain_positions', True)
        settings.set2('positions', self.coordinate.position)
        settings.set2('redofailedonly', False)
        settings.set2('framerange', True)
        settings.set2('framerange_begin', self.coordinate.time)
        settings.set2('framerange_end', self.coordinate.time)

        settings.set_section('ObjectDetection')
        prim_id = PrimaryChannel.NAME
        #sec_id = SecondaryChannel.NAME
        #sec_regions = settings.get2('secondary_regions')
        settings.set_section('Processing')
        settings.set2('primary_classification', False)
        settings.set2('secondary_classification', False)
        settings.set2('tertiary_classification', False)
        settings.set2('merged_classification', False)
        settings.set2('primary_featureextraction', False)
        settings.set2('secondary_featureextraction', False)

        settings.set2('objectdetection', self._show_objects)
        settings.set2('tracking', False)
        settings.set_section('Output')
        settings.set2('rendering_contours_discwrite', False)
        settings.set2('rendering_class_discwrite', False)
        settings.set2('export_object_counts', False)
        settings.set2('export_object_details', False)
        settings.set2('export_track_data', False)
        settings.set2('hdf5_create_file', False)
        settings.set_section('Classification')
        settings.set2('collectsamples', False)
        settings.set('General', 'rendering', {})
        settings.set('General', 'rendering_class', {})
        settings.set('Output', 'events_export_gallery_images', False)

        # turn of output:
        settings.set('Output', 'export_object_counts', False)
        settings.set('Output', 'export_object_details', False)
        settings.set('Output', 'export_file_names', False)
        settings.set('Output', 'events_export_gallery_images', False)
        settings.set('Output', 'export_track_data', False)
        settings.set('Output', 'export_tracking_as_dot', False)

        nchannels = len(self._imagecontainer.channels)

        # XXX channel mapping unclear
        # processing channel <--> color channel
        # i.e problems if 2 processing channels have the
        # same color
        if nchannels == 2:
            settings.set('Processing', 'secondary_processChannel', True)
        elif nchannels == 3:
            settings.set('Processing', 'secondary_processChannel', True)
            settings.set('Processing', 'tertiary_processChannel', True)
        # need turn of virtual channels
        settings.set('Processing', 'merged_processChannel', False)

        settings.set('General', 'rendering', {})
        analyzer = AnalyzerCore(self.coordinate.plate, settings,
                                self._imagecontainer)

        # as long the GIL is not released, if GIL is released
        # just use self.setCursor

        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            analyzer.processPositions(myhack=self)
        except Exception, e:
            import traceback
            traceback.print_exc()
            raise (e)
        finally:
Example #15
0
    def __init__(self, settings, imagecontainer, parent=None):
        super(Browser, self).__init__(parent)
        self.setWindowTitle('Annotation Browser')

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer

        # These params are used by process_image and contour visualization
        self._detect_objects = False
        self._show_objects_by = 'color'
        self._object_region = None
        self._contour_color = '#000000'
        self._show_objects = True

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")

        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t - 1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewers = {
            'image': ImageViewer(frame, auto_resize=True),
            'gallery': GalleryViewer(frame)
        }

        self.image_viewer = self.image_viewers['image']
        layout.addWidget(self.image_viewer, 0, 0)

        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = TSlider(Qt.Horizontal, frame)

        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)

        self._t_slider.setTickPosition(QSlider.NoTicks)
        self._t_slider.newValue.connect(self.on_time_changed_by_slider,
                                        Qt.DirectConnection)
        self._t_slider.valueChanged.connect(self.timeToolTip)
        self._imagecontainer.check_dimensions()

        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus
        act_close = self.create_action('Close',
                                       shortcut=QKeySequence('CTRL+C'),
                                       slot=self.close)

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action(
            'Next Plate',
            shortcut=QKeySequence('Shift+Alt+Down'),
            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action(
            'Previous Plate',
            shortcut=QKeySequence('Shift+Alt+Up'),
            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                        shortcut=QKeySequence('SHIFT+CTRL+R'),
                                        slot=self.on_act_autoresize,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action('Full Screen',
                                            shortcut=QKeySequence('CTRL+F'),
                                            slot=self.on_act_fullscreen,
                                            signal='triggered(bool)',
                                            checkable=True,
                                            checked=False)
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action(
            'Show Object Contours',
            shortcut=QKeySequence('ALT+C'),
            slot=self.on_act_show_contours,
            signal='triggered(bool)',
            checkable=True,
            checked=self.image_viewer.show_contours)
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(
            view_menu,
            (act_resize, None, act_zoom100, act_zoomfit, act_zoomin,
             act_zoomout, None, act_prev_t, act_next_t, act_prev_pos,
             act_next_pos, act_prev_plate, act_next_plate, None, act_refresh,
             act_fullscreen, None, act_show_contours, None, act_anti,
             act_smooth, None, act_close))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)

        toolbar = self.addToolBar('Toolbar')
        toolbar.setObjectName('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        # fallback if no Segmentation plugins have been specified
        rdict = self._region_names()
        if len(rdict) > 0:
            self._object_region = rdict.keys()[0].split(' - ')
        else:
            self._object_region = ('Primary', 'primary')

        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)
        defautl_display_module = DisplayModule(self._module_manager, self,
                                               self._imagecontainer, rdict)

        self.set_display_module(defautl_display_module)
        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        try:
            CellH5EventModule(self._module_manager, self, self._settings,
                              self._imagecontainer)
        except Exception as e:
            QMessageBox.warning(self, "Warning", str(e))

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        self.layout = layout
        # process and display the first image
        self._restore_geometry()
        self._process_image()
Example #16
0
class Browser(QMainWindow):

    ZOOM_STEP = 1.05

    show_objects_toggled = pyqtSignal('bool')
    show_contours_toggled = pyqtSignal('bool')
    update_regions = pyqtSignal(dict)

    def __init__(self, settings, imagecontainer, parent=None):
        super(Browser, self).__init__(parent)
        self.setWindowTitle('Annotation Browser')

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._settings = settings
        self._imagecontainer = imagecontainer

        # These params are used by process_image and contour visualization
        self._detect_objects = False
        self._show_objects_by = 'color'
        self._object_region = None
        self._contour_color = '#000000'
        self._show_objects = True

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet("QStatusBar { border-top: 1px solid gray; }")

        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()
        self.max_time = meta_data.times[-1]
        self.min_time = meta_data.times[0]
        self.max_frame = meta_data.dim_t - 1

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewers = {
            'image': ImageViewer(frame, auto_resize=True),
            'gallery': GalleryViewer(frame)
        }

        self.image_viewer = self.image_viewers['image']
        layout.addWidget(self.image_viewer, 0, 0)

        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = TSlider(Qt.Horizontal, frame)

        self._t_slider.setMinimum(self.min_time)
        self._t_slider.setMaximum(self.max_time)

        self._t_slider.setTickPosition(QSlider.NoTicks)
        self._t_slider.newValue.connect(self.on_time_changed_by_slider,
                                        Qt.DirectConnection)
        self._t_slider.valueChanged.connect(self.timeToolTip)
        self._imagecontainer.check_dimensions()

        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus
        act_close = self.create_action('Close',
                                       shortcut=QKeySequence('CTRL+C'),
                                       slot=self.close)

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action(
            'Next Plate',
            shortcut=QKeySequence('Shift+Alt+Down'),
            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action(
            'Previous Plate',
            shortcut=QKeySequence('Shift+Alt+Up'),
            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                        shortcut=QKeySequence('SHIFT+CTRL+R'),
                                        slot=self.on_act_autoresize,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_refresh = self.create_action('Refresh',
                                         shortcut=QKeySequence('F5'),
                                         slot=self.on_refresh)

        act_fullscreen = self.create_action('Full Screen',
                                            shortcut=QKeySequence('CTRL+F'),
                                            slot=self.on_act_fullscreen,
                                            signal='triggered(bool)',
                                            checkable=True,
                                            checked=False)
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action(
            'Show Object Contours',
            shortcut=QKeySequence('ALT+C'),
            slot=self.on_act_show_contours,
            signal='triggered(bool)',
            checkable=True,
            checked=self.image_viewer.show_contours)
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')

        self.add_actions(
            view_menu,
            (act_resize, None, act_zoom100, act_zoomfit, act_zoomin,
             act_zoomout, None, act_prev_t, act_next_t, act_prev_pos,
             act_next_pos, act_prev_plate, act_next_plate, None, act_refresh,
             act_fullscreen, None, act_show_contours, None, act_anti,
             act_smooth, None, act_close))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)

        toolbar = self.addToolBar('Toolbar')
        toolbar.setObjectName('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        # fallback if no Segmentation plugins have been specified
        rdict = self._region_names()
        if len(rdict) > 0:
            self._object_region = rdict.keys()[0].split(' - ')
        else:
            self._object_region = ('Primary', 'primary')

        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)
        defautl_display_module = DisplayModule(self._module_manager, self,
                                               self._imagecontainer, rdict)

        self.set_display_module(defautl_display_module)
        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        try:
            CellH5EventModule(self._module_manager, self, self._settings,
                              self._imagecontainer)
        except Exception as e:
            QMessageBox.warning(self, "Warning", str(e))

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        self.layout = layout
        # process and display the first image
        self._restore_geometry()
        self._process_image()

    def closeEvent(self, event):
        self._save_geometry()

    def _save_geometry(self):
        settings = QSettings(version.organisation, version.appname)
        settings.beginGroup('AnnotationBrowser')
        settings.setValue('state', self.saveState())
        settings.setValue('geometry', self.saveGeometry())
        settings.endGroup()

    def _restore_geometry(self):
        settings = QSettings(version.organisation, version.appname)
        settings.beginGroup('AnnotationBrowser')

        if settings.contains('geometry'):
            self.restoreGeometry(settings.value('geometry'))

        if settings.contains('state'):
            self.restoreState(settings.value('state'))
        settings.endGroup()

    def _region_names(self):

        rdict = OrderedDict()
        reginfo = MetaPluginManager().region_info
        for channel, regions in reginfo.names.iteritems():
            for region in regions:
                rdict['%s - %s' % (channel.capitalize(), region)] = \
                    (channel.capitalize(), region)
        return rdict

    def set_image_viewer(self, viewer_type):
        self.image_viewer.hide()
        self.layout.removeWidget(self.image_viewer)
        self.image_viewer = self.image_viewers[viewer_type]
        self.layout.addWidget(self.image_viewer, 0, 0)
        self.image_viewer.show()

    def create_action(self,
                      text,
                      slot=None,
                      shortcut=None,
                      icon=None,
                      tooltip=None,
                      checkable=None,
                      signal='triggered()',
                      checked=False):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(':/%s.png' % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tooltip is not None:
            action.setToolTip(tooltip)
            action.setStatusTip(tooltip)
        if slot is not None:
            if signal == "triggered()":
                action.triggered.connect(slot, Qt.DirectConnection)
            else:
                action.triggered[bool].connect(slot, Qt.DirectConnection)
        if checkable is not None:
            action.setCheckable(True)
        action.setChecked(checked)
        return action

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def set_coords(self, coords):
        self.image_viewer.set_objects_by_crackcoords(coords)
        widget = self._module_manager.get_widget(AnnotationModule.NAME)
        widget.set_coords()

    def set_classified_crack_contours(self, coords):
        self.image_viewer.set_objects_by_crackcoords_with_colors(coords)
        widget = self._module_manager.get_widget(AnnotationModule.NAME)
        widget.set_coords()

    def show_image(self, image_dict):
        widget = self.get_display_module()
        widget.set_image_dict(image_dict)
        self.update_statusbar()

    def set_display_module(self, display_module):
        self.display_module = display_module

    def get_display_module(self):
        return self.display_module

    def update_statusbar(self):
        meta_data = self._imagecontainer.get_meta_data()
        if meta_data.has_timelapse:
            timestamp = meta_data.get_timestamp_relative(self.coordinate)
            time_info = ' | Frame: %d' % self.coordinate.time

            if not numpy.isnan(timestamp):
                time_info += ' (%.1f min)' % (timestamp / 60)
        else:
            time_info = ''
        msg = 'Plate: %s | Position: %s%s ||  Zoom: %.1f%%' % \
              (self.coordinate.plate, self.coordinate.position, time_info,
               self.image_viewer.scalefactor*100)
        self._statusbar.showMessage(msg)

    def get_coordinate(self):
        return self.coordinate.copy()

    def on_coordinate_changed(self, coordinate):
        """
        All coordinate changes are handled via the Navigator. The change event
        from the Navigator is processed here and further propagated via
        a new Browser event (the Modules are not supposed to know each other).
        """

        self.coordinate = coordinate.copy()
        self._t_slider.blockSignals(True)
        self._imagecontainer.set_plate(coordinate.plate)
        self._t_slider.setValue(coordinate.time)

        self._t_slider.blockSignals(False)
        self._process_image()
        # propagate the signal further to other modules
        #self.coordinates_changed.emit(coordinate)

    def set_coordinate(self, coordinate):
        """
        Changes the Navigator to a fixed coordinate
        """
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_coordinate(coordinate)

    def _process_image(self, ):
        self.image_viewer.remove_objects()
        settings = BaseProcessorFrame.get_special_settings(self._settings)
        settings.set_section('General')
        settings.set2('constrain_positions', True)
        settings.set2('positions', self.coordinate.position)
        settings.set2('skip_finished', False)
        settings.set2('framerange', True)
        settings.set2('framerange_begin', self.coordinate.time)
        settings.set2('framerange_end', self.coordinate.time)

        settings.set_section('Processing')
        _classify_objects = self._show_objects_by == 'classification'

        settings.set2('primary_classification', _classify_objects)
        settings.set2('secondary_classification', _classify_objects)
        settings.set2('tertiary_classification', _classify_objects)
        settings.set2('merged_classification', _classify_objects)
        settings.set2('primary_featureextraction', _classify_objects)
        settings.set2('secondary_featureextraction', _classify_objects)
        settings.set2('objectdetection', self._detect_objects)
        settings.set2('tracking', False)

        settings.set('Output', 'hdf5_create_file', False)
        settings.set('General', 'rendering', {})
        settings.set('General', 'rendering_class', {})

        nchannels = len(self._imagecontainer.channels)
        # XXX channel mapping unclear
        # processing channel <--> color channel
        # i.e problems if 2 processing channels have the same color
        if nchannels == 2:
            settings.set('General', 'process_secondary', True)
        elif nchannels >= 3:
            settings.set('General', 'process_secondary', True)
            settings.set('General', 'process_tertiary', True)

        settings.set('General', 'rendering', {})

        analyzer = AnalyzerBrowser(self.coordinate.plate, settings,
                                   self._imagecontainer)

        res = None
        try:
            QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
            res = analyzer()
            self.render_browser(res)
        except Exception, e:
            import traceback
            traceback.print_exc()
            QMessageBox.critical(self, "Error", str(e))
            raise
        finally:
Example #17
0
class Browser(QMainWindow):

    ZOOM_STEP = 1.05

    show_objects_toggled = pyqtSignal('bool')
    show_contours_toggled = pyqtSignal('bool')
    coordinates_changed = pyqtSignal(Coordinate)

    def __init__(self, settings, imagecontainer):
        QMainWindow.__init__(self)

        frame = QFrame(self)
        self.setCentralWidget(frame)

        self._stopwatch = StopWatch()

        self._settings = settings
        self._imagecontainer = imagecontainer
        self._show_objects = False
        self._object_region = None

        self.coordinate = Coordinate()

        self.grabGesture(Qt.SwipeGesture)

        self.setStyleSheet(
"""
  QStatusBar { border-top: 1px solid gray; }
""")


        layout = QVBoxLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)

        splitter = QSplitter(Qt.Horizontal, frame)
        #splitter.setSizePolicy(QSizePolicy(QSizePolicy.Minimum,
        #                                   QSizePolicy.Expanding))
        layout.addWidget(splitter)

        frame = QFrame(self)
        frame_side = QStackedWidget(splitter)
        #splitter.setChildrenCollapsible(False)
        splitter.addWidget(frame)
        splitter.addWidget(frame_side)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 0)
        splitter.setSizes([-1, 80])

        self.coordinate.plate = self._imagecontainer.plates[0]
        self._imagecontainer.set_plate(self.coordinate.plate)

        self.coordinate.channel = self._imagecontainer.channels[0]

        meta_data = self._imagecontainer.get_meta_data()

        layout = QGridLayout(frame)
        layout.setContentsMargins(0, 0, 0, 0)
        self.image_viewer = ImageViewer(frame, auto_resize=True)
        layout.addWidget(self.image_viewer, 0, 0)

        #self.image_viewer.image_mouse_dblclk.connect(self._on_dbl_clk)
        self.image_viewer.zoom_info_updated.connect(self.on_zoom_info_updated)

        self._t_slider = QSlider(Qt.Horizontal, frame)
        self._t_slider.setMinimum(meta_data.times[0])
        self._t_slider.setMaximum(meta_data.times[-1])
        self._t_slider.setTickPosition(QSlider.TicksBelow)
        self._t_slider.valueChanged.connect(self.on_time_changed_by_slider,
                                            Qt.DirectConnection)
        if self._imagecontainer.has_timelapse:
            self._t_slider.show()
        else:
            self._t_slider.hide()
        layout.addWidget(self._t_slider, 1, 0)

        self.coordinate.position = meta_data.positions[0]
        self.coordinate.time = self._t_slider.minimum()

        # menus

        act_next_t = self.create_action('Next Time-point',
                                        shortcut=QKeySequence('Right'),
                                        slot=self.on_act_next_t)
        act_prev_t = self.create_action('Previous Time-point',
                                        shortcut=QKeySequence('Left'),
                                        slot=self.on_act_prev_t)
        act_next_pos = self.create_action('Next Position',
                                          shortcut=QKeySequence('Shift+Down'),
                                          slot=self.on_act_next_pos)
        act_prev_pos = self.create_action('Previous Position',
                                          shortcut=QKeySequence('Shift+Up'),
                                          slot=self.on_act_prev_pos)
        act_next_plate = self.create_action('Next Plate',
                                            shortcut=QKeySequence('Shift+Alt+Down'),
                                            slot=self.on_act_next_plate)
        act_prev_plate = self.create_action('Previous Plate',
                                            shortcut=QKeySequence('Shift+Alt+Up'),
                                            slot=self.on_act_prev_plate)
        act_resize = self.create_action('Automatically Resize',
                                         shortcut=QKeySequence('SHIFT+CTRL+R'),
                                         slot=self.on_act_autoresize,
                                         signal='triggered(bool)',
                                         checkable=True,
                                         checked=True)
        self._act_resize = act_resize
        act_zoomfit = self.create_action('Zoom to Fit',
                                         shortcut=QKeySequence('CTRL+0'),
                                         slot=self.on_act_zoomfit)
        act_zoom100 = self.create_action('Actual Size',
                                         shortcut=QKeySequence('CTRL+1'),
                                         slot=self.on_act_zoom100)
        act_zoomin = self.create_action('Zoom In',
                                        shortcut=QKeySequence('CTRL++'),
                                        slot=self.on_act_zoomin)
        act_zoomout = self.create_action('Zoom Out',
                                         shortcut=QKeySequence('CTRL+-'),
                                         slot=self.on_act_zoomout)
        act_fullscreen = self.create_action('Full Screen',
                                            shortcut=QKeySequence('CTRL+F'),
                                            slot=self.on_act_fullscreen,
                                            signal='triggered(bool)',
                                            checkable=True,
                                            checked=False)
        self._act_fullscreen = act_fullscreen

        act_show_contours = self.create_action('Show Object Contours',
                                               shortcut=QKeySequence('ALT+C'),
                                               slot=self.on_act_show_contours,
                                               signal='triggered(bool)',
                                               checkable=True,
                                               checked=self.image_viewer.show_contours)
        self._act_show_contours = act_show_contours

        act_anti = self.create_action('Antialiasing',
                                      shortcut=QKeySequence('CTRL+ALT+A'),
                                      slot=self.on_act_antialiasing,
                                      signal='triggered(bool)',
                                      checkable=True,
                                      checked=True)
        act_smooth = self.create_action('Smooth Transform',
                                        shortcut=QKeySequence('CTRL+ALT+S'),
                                        slot=self.on_act_smoothtransform,
                                        signal='triggered(bool)',
                                        checkable=True,
                                        checked=True)
        view_menu = self.menuBar().addMenu('&View')
        self.add_actions(view_menu, (act_resize, None,
                                     act_zoom100, act_zoomfit,
                                     act_zoomin, act_zoomout,
                                     None,
                                     act_prev_t, act_next_t,
                                     act_prev_pos, act_next_pos,
                                     act_prev_plate, act_next_plate,
                                     None,
                                     act_fullscreen, None,
                                     act_show_contours, None,
                                     act_anti, act_smooth,
                                     ))

        self._statusbar = QStatusBar(self)
        self.setStatusBar(self._statusbar)


        # tool bar

        toolbar = self.addToolBar('Toolbar')
        toolbar.setMovable(False)
        toolbar.setFloatable(False)

        region_names = ['Primary - primary']
        self._settings.set_section('ObjectDetection')
        for prefix in ['secondary', 'tertiary']:
            if self._settings.get('Processing', '%s_processchannel' % prefix):
                for name in REGION_NAMES_SECONDARY:
                    if self._settings.get2('%s_regions_%s' % (prefix, name)):
                        region_names.append('%s - %s' % (prefix.capitalize(), name))

        # FIXME: something went wrong with setting up the current region
        self._object_region = region_names[0].split(' - ')


        # create a new ModuleManager with a QToolbar and QStackedFrame
        self._module_manager = ModuleManager(toolbar, frame_side)

        NavigationModule(self._module_manager, self, self._imagecontainer)

        DisplayModule(self._module_manager, self, self._imagecontainer,
                      region_names)

        AnnotationModule(self._module_manager, self, self._settings,
                         self._imagecontainer)

        # set the Navigation module activated
        self._module_manager.activate_tab(NavigationModule.NAME)

        # process and display the first image
        self._process_image()

    def create_action(self, text, slot=None, shortcut=None, icon=None,
                      tooltip=None, checkable=None, signal='triggered()',
                      checked=False):
        action = QAction(text, self)
        if icon is not None:
            action.setIcon(QIcon(':/%s.png' % icon))
        if shortcut is not None:
            action.setShortcut(shortcut)
        if tooltip is not None:
            action.setToolTip(tooltip)
            action.setStatusTip(tooltip)
        if slot is not None:
            self.connect(action, SIGNAL(signal), slot, Qt.DirectConnection)
        if checkable is not None:
            action.setCheckable(True)
        action.setChecked(checked)
        return action

    def add_actions(self, target, actions):
        for action in actions:
            if action is None:
                target.addSeparator()
            else:
                target.addAction(action)

    def set_coords(self, coords):
        self.image_viewer.remove_objects()
        self.image_viewer.set_objects_by_crackcoords(coords)
        widget = self._module_manager.get_widget(AnnotationModule.NAME)
        widget.set_coords()

    def set_image(self, image_dict):
        widget = self._module_manager.get_widget(DisplayModule.NAME)
        widget.set_image_dict(image_dict)
        self.update_statusbar()

    def update_statusbar(self):
        meta_data = self._imagecontainer.get_meta_data()
        if meta_data.has_timelapse:
            timestamp = meta_data.get_timestamp_relative(self.coordinate)
            time_info = ' | Frame: %d' % self.coordinate.time
            if not numpy.isnan(timestamp):
                time_info += ' (%.1f min)' % (timestamp / 60)
        else:
            time_info = ''
        msg = 'Plate: %s | Position: %s%s ||  Zoom: %.1f%%' % \
              (self.coordinate.plate, self.coordinate.position, time_info,
               self.image_viewer.scale_factor*100)
        self._statusbar.showMessage(msg)

    def get_coordinate(self):
        return self.coordinate.copy()

    def on_coordinate_changed(self, coordinate):
        """
        All coordinate changes are handled via the Navigator. The change event
        from the Navigator is processed here and further propagated via
        a new Browser event (the Modules are not supposed to know each other).
        """
        self.coordinate = coordinate.copy()
        self._t_slider.blockSignals(True)
        self._imagecontainer.set_plate(coordinate.plate)
        meta_data = self._imagecontainer.get_meta_data()
        self._t_slider.setMaximum(meta_data.dim_t)
        self._t_slider.setValue(coordinate.time)
        self._t_slider.blockSignals(False)
        self._process_image()
        # propagate the signal further to other modules
        self.coordinates_changed.emit(coordinate)

    def set_coordinate(self, coordinate):
        """
        Changes the Navigator to a fixed coordinate
        """
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_coordinate(coordinate)

    def _process_image(self):
        print 'process image'
        self._stopwatch.reset()
        s = StopWatch()
        settings = _ProcessorMixin.get_special_settings(self._settings)
        settings.set_section('General')
        settings.set2('constrain_positions', True)
        settings.set2('positions', self.coordinate.position)
        settings.set2('redofailedonly', False)
        settings.set2('framerange', True)
        settings.set2('framerange_begin', self.coordinate.time)
        settings.set2('framerange_end', self.coordinate.time)

        settings.set_section('ObjectDetection')
        prim_id = PrimaryChannel.NAME
        #sec_id = SecondaryChannel.NAME
        #sec_regions = settings.get2('secondary_regions')
        settings.set_section('Processing')
        settings.set2('primary_classification', False)
        settings.set2('secondary_classification', False)
        settings.set2('primary_featureextraction', False)
        settings.set2('secondary_featureextraction', False)

        settings.set2('objectdetection', self._show_objects)
        settings.set2('tracking', False)
        settings.set_section('Output')
        settings.set2('rendering_contours_discwrite', False)
        settings.set2('rendering_class_discwrite', False)
        settings.set2('export_object_counts', False)
        settings.set2('export_object_details', False)
        settings.set2('export_track_data', False)
        settings.set_section('Classification')
        settings.set2('collectsamples', False)
        settings.set('General', 'rendering', {})
        settings.set('General', 'rendering_class', {})

        if len(self._imagecontainer.channels) > 1:
            settings.set('Processing', 'secondary_processChannel', True)
        settings.set('General', 'rendering', {})

        print settings
        analyzer = AnalyzerCore(self.coordinate.plate, settings,
                                self._imagecontainer)
        analyzer.processPositions(myhack=self)
        print('PROCESS IMAGE: %s' % s)

    # slots

    def on_zoom_info_updated(self, info):
        self.update_statusbar()

    def on_time_changed_by_slider(self, time):
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_time(time)

    def on_object_region_changed(self, channel, region):
        self._object_region = channel, region
        self._process_image()

    def on_act_prev_t(self):
        self._t_slider.setValue(self._t_slider.value()-1)

    def on_act_next_t(self):
        self._t_slider.setValue(self._t_slider.value()+1)

    def on_act_prev_pos(self):
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_prev_position()

    def on_act_next_pos(self):
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_next_position()

    def on_act_prev_plate(self):
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_prev_plate()

    def on_act_next_plate(self):
        nav = self._module_manager.get_widget(NavigationModule.NAME)
        nav.nav_to_next_plate()

    def on_act_fullscreen(self, checked):
        if checked:
            self.showFullScreen()
        else:
            self.showNormal()
        self.raise_()

    def on_act_show_contours(self, checked):
        self._act_show_contours.blockSignals(True)
        self._act_show_contours.setChecked(checked)
        self._act_show_contours.blockSignals(False)
        self.image_viewer.set_show_contours(checked)
        self.show_contours_toggled.emit(checked)

    def on_act_antialiasing(self, checked):
        self.image_viewer.setRenderHint(QPainter.Antialiasing, checked)
        self.image_viewer.update()

    def on_act_smoothtransform(self, checked):
        self.image_viewer.setRenderHint(QPainter.SmoothPixmapTransform,
                                         checked)
        self.image_viewer.update()

    def on_act_autoresize(self, state):
        self.image_viewer.set_auto_resize(state)
        if state:
            self.image_viewer.scale_to_fit()

    def on_act_zoom100(self):
        self.image_viewer.set_auto_resize(False)
        self._act_resize.setChecked(False)
        self.image_viewer.scale_reset()

    def on_act_zoomfit(self):
        self.image_viewer.set_auto_resize(False)
        self._act_resize.setChecked(False)
        self.image_viewer.scale_to_fit()

    def on_act_zoomin(self):
        self.image_viewer.set_auto_resize(False)
        self._act_resize.setChecked(False)
        self.image_viewer.scale_relative(self.ZOOM_STEP, ensure_fit=False)

    def on_act_zoomout(self):
        self.image_viewer.set_auto_resize(False)
        self._act_resize.setChecked(False)
        self.image_viewer.scale_relative(1/self.ZOOM_STEP, ensure_fit=True)

    def on_act_transform(self, checked):
        if checked:
            self.image_viewer.set_scale_transform(Qt.FastTransformation)
        else:
            self.image_viewer.set_scale_transform(Qt.SmoothTransformation)
        self._process_image()

    def on_act_class_selected(self, class_label):
        items = self._find_items_in_class_table(str(class_label),
                                                self.COLUMN_CLASS_LABEL)
        if len(items) == 1:
            self._class_table.setCurrentItem(items[0])

    def on_show_objects(self, state):
        self._show_objects = state
        self.image_viewer.remove_objects()
        self._process_image()
        self.show_objects_toggled.emit(state)

    # Qt method overwrites

    def keyPressEvent(self, ev):
        QMainWindow.keyPressEvent(self, ev)
        # allow to return from fullscreen via the Escape key
        if self.isFullScreen() and ev.key() == Qt.Key_Escape:
            self.showNormal()
            self._act_fullscreen.setChecked(False)
            self.raise_()

    def gestureEvent(self, ev):
        # determine whether a swipe gesture was detected
        if not ev.gesture(Qt.SwipeGesture) is None:
            gesture = ev.gesture(Qt.SwipeGesture)
            if gesture.state() == Qt.GestureFinished:
                if gesture.horizontalDirection() == QSwipeGesture.Left:
                    self._on_act_left()
                elif gesture.horizontalDirection() == QSwipeGesture.Right:
                    self._on_act_right()
                elif gesture.horizontalDirection() == QSwipeGesture.Up:
                    self._on_act_up()
                elif gesture.horizontalDirection() == QSwipeGesture.Down:
                    self._on_act_down()
        return True

    def event(self, ev):
        if ev.type() == QEvent.Gesture:
            return self.gestureEvent(ev)
        return QWidget.event(self, ev)
Example #18
0
    def _analyze(self, cellanalyzer):
        super(PositionAnalyzer, self)._analyze()
        n_images = 0
        stopwatch = StopWatch(start=True)
        crd = Coordinate(self.plate_id, self.position, self._frames,
                         list(set(self.ch_mapping.values())))

        for frame, channels in self._imagecontainer( \
            crd, interrupt_channel=True, interrupt_zslice=True):

            if self.is_aborted():
                self.clear()
                return 0
            else:
                txt = 'T %d (%d/%d)' % (frame, self._frames.index(frame) + 1,
                                        len(self._frames))
                self.update_status({
                    'progress': self._frames.index(frame) + 1,
                    'text': txt,
                    'interval': stopwatch.interim()
                })

            stopwatch.reset(start=True)
            cellanalyzer.initTimepoint(frame)
            self.register_channels(cellanalyzer, channels)

            cellanalyzer.process()
            n_images += 1
            images = []

            if self.settings.get('Processing', 'tracking'):
                region = self.settings.get('Tracking', 'tracking_regionname')
                samples = self.timeholder[frame][
                    PrimaryChannel.NAME].get_region(region)
                self._tracker.track_next_frame(frame, samples)

                if self.settings.get('Tracking', 'tracking_visualization'):
                    size = cellanalyzer.getImageSize(PrimaryChannel.NAME)
                    nframes = self.settings.get(
                        'Tracking', 'tracking_visualize_track_length')
                    radius = self.settings.get('Tracking',
                                               'tracking_centroid_radius')
                    img_conn, img_split = self._tracker.render_tracks(
                        frame, size, nframes, radius)
                    images += [(img_conn, '#FFFF00', 1.0),
                               (img_split, '#00FFFF', 1.0)]

            for clf in self.classifiers.itervalues():
                cellanalyzer.classify_objects(clf)

            ##############################################################
            # FIXME - part for browser
            if not self._myhack is None:
                self.render_browser(cellanalyzer)
            ##############################################################

            self.settings.set_section('General')
            self.render_classification_images(cellanalyzer, images, frame)
            self.render_contour_images(cellanalyzer, images, frame)

            if self.settings.get('Output', 'rendering_channel_gallery'):
                self.render_channel_gallery(cellanalyzer, frame)

            if self.settings.get('Output', 'rendering_labels_discwrite'):
                cellanalyzer.exportLabelImages(self._labels_dir)

            self.logger.info(" - Frame %d, duration (ms): %3d" \
                                 %(frame, stopwatch.interim()*1000))
            cellanalyzer.purge(features=self.export_features)

        return n_images