def iter_check_plates(cls, settings): settings.set_section(SECTION_NAME_GENERAL) path_in = CecogEnvironment.convert_package_path( settings.get2('pathin')) path_out = CecogEnvironment.convert_package_path( settings.get2('pathout')) has_multiple_plates = settings.get2('has_multiple_plates') if has_multiple_plates: plate_folders = [x for x in os.listdir(path_in) if os.path.isdir(os.path.join(path_in, x))] else: plate_folders = [os.path.split(path_in)[1]] for plate_id in plate_folders: if has_multiple_plates: path_plate_in = os.path.join(path_in, plate_id) path_plate_out = os.path.join(path_out, plate_id) else: path_plate_in = path_in path_plate_out = path_out # check if structure file exists filename = cls._get_structure_filename(settings, plate_id, path_plate_in, path_plate_out) if not os.path.isfile(filename): # check old (hidden) filename for compatibility reasons filename = cls._get_structure_filename(settings, plate_id, path_plate_in, path_plate_out, use_old=True) if not os.path.isfile(filename): filename = None yield plate_id, path_plate_in, path_plate_out, filename
def load_classifier(self, check=True): _resolve = lambda x,y: self._settings.get(x, '%s_%s' % (self._channel, y)) clfdir = CecogEnvironment.convert_package_path(_resolve('Classification', 'classification_envpath')) # XXX - where does the "." come if not isdir(clfdir) or clfdir == ".": return else: self._learner = CommonClassPredictor( \ clf_dir=clfdir, name=self._channel, channels={self._channel.title(): _resolve('Classification', 'classification_regionname')}, color_channel=_resolve('ObjectDetection', 'channelid')) result = self._learner.check() if check: b = lambda x: 'Yes' if x else 'No' msg = 'Classifier path: %s\n' % result['path_env'] msg += 'Found class definition: %s\n' % b(result['has_definition']) msg += 'Found annotations: %s\n' % b(result['has_path_annotations']) msg += 'Can you pick new samples? %s\n\n' % b(self.is_pick_samples()) msg += 'Found ARFF file: %s\n' % b(result['has_arff']) msg += 'Can you train a classifier? %s\n\n' % b(self.is_train_classifier()) msg += 'Found SVM model: %s\n' % b(result['has_model']) msg += 'Found SVM range: %s\n' % b(result['has_range']) msg += 'Can you apply the classifier to images? %s\n\n' % b(self.is_apply_classifier()) msg += 'Found samples: %s\n' % b(result['has_path_samples']) msg += 'Sample images are only used for visualization and annotation control at the moment.' txt = '%s classifier inspection results' % self._channel information(self, txt, info=msg) if result['has_arff']: self._learner.importFromArff() nr_features_prev = len(self._learner.feature_names) removed_features = self._learner.filter_nans(apply=True) nr_features = nr_features_prev - len(removed_features) self._label_features.setText(self.LABEL_FEATURES %(nr_features, nr_features_prev)) self._label_features.setToolTip("removed %d features containing NA values:\n%s" % (len(removed_features), "\n".join(removed_features))) if result['has_definition']: self._learner.loadDefinition() if result['has_conf']: c, g, conf = self._learner.importConfusion() self._set_info(c, g, conf) self._init_conf_table(conf) self._update_conf_table(conf) else: conf = None self._init_conf_table(conf) self._set_info_table(conf)
def _on_browse_name(self, name, mode): # FIXME: signals are send during init were registry is not set yet if name in self._registry: input = CecogEnvironment.convert_package_path(str(self._registry[name].text())) dir = os.path.abspath(input) if mode == StringTrait.STRING_FILE: result = QFileDialog.getOpenFileName(self, 'Select a file', dir) else: result = QFileDialog.getExistingDirectory(self, \ 'Select a directory', dir) if result: self._registry[name].setText(result) self._set_value(name, result) # call final handler if name in self._final_handlers: self._final_handlers[name]()
def get_special_settings(cls, settings, has_timelapse=True): settings = settings.copy() # try to resolve the paths relative to the package dir # (only in case of an relative path given) converts = [('General', 'pathin'), ('General', 'pathout'), ('Classification', 'primary_classification_envpath'), ('Classification', 'secondary_classification_envpath'), ('ErrorCorrection', 'primary_graph'), ('ErrorCorrection', 'secondary_graph'), ('ErrorCorrection', 'mappingfile_path'), ] for section, option in converts: value = settings.get(section, option) settings.set(section, option, CecogEnvironment.convert_package_path(value)) return settings
def _on_browse_name(self, name, mode): # FIXME: signals are send during init were registry is not set yet if name in self._registry: input = CecogEnvironment.convert_package_path( str(self._registry[name].text())) dir = os.path.abspath(input) if mode == StringTrait.STRING_FILE: result = QFileDialog.getOpenFileName(self, 'Select a file', dir) else: result = QFileDialog.getExistingDirectory(self, \ 'Select a directory', dir) if result: self._registry[name].setText(result) self._set_value(name, result) # call final handler if name in self._final_handlers: self._final_handlers[name]()
def get_special_settings(cls, settings, has_timelapse=True): settings = settings.copy() # try to resolve the paths relative to the package dir # (only in case of an relative path given) converts = [ ('General', 'pathin'), ('General', 'pathout'), ('Classification', 'primary_classification_envpath'), ('Classification', 'secondary_classification_envpath'), ('ErrorCorrection', 'primary_graph'), ('ErrorCorrection', 'secondary_graph'), ('ErrorCorrection', 'mappingfile_path'), ] for section, option in converts: value = settings.get(section, option) settings.set(section, option, CecogEnvironment.convert_package_path(value)) return settings
class CecogAnalyzer(QtGui.QMainWindow): NAME_FILTERS = ['Settings files (*.conf)', 'All files (*.*)'] modified = QtCore.pyqtSignal('bool') def __init__(self, appname, version, redirect, debug=False, *args, **kw): super(CecogAnalyzer, self).__init__(*args, **kw) self.setWindowTitle("%s-%s" %(appname, version) + '[*]') self.setCentralWidget(QtGui.QFrame(self)) self.setObjectName(appname) self.version = version self.appname = appname self.debug = debug self.environ = CecogEnvironment(version, redirect=redirect, debug=debug) if debug: self.environ.pprint() self._is_initialized = False self._imagecontainer = None self._meta_data = None self._browser = None action_quit = self.create_action('&Quit', slot=self.close) action_pref = self.create_action('&Preferences', slot=self.open_preferences) action_open = self.create_action('&Open Settings...', shortcut=QtGui.QKeySequence.Open, slot=self._on_file_open) action_save = self.create_action('&Save Settings', shortcut=QtGui.QKeySequence.Save, slot=self._on_file_save) self.action_save = action_save action_save_as = self.create_action('&Save Settings As...', shortcut=QtGui.QKeySequence.SaveAs, slot=self._on_file_save_as) menu_file = self.menuBar().addMenu('&File') self.add_actions(menu_file, (action_pref, None, action_open, None, action_save, action_save_as, None, action_quit)) action_open = self.create_action('&Open Browser...', shortcut=QtGui.QKeySequence('CTRL+B'), slot=self._on_browser_open) menu_browser = self.menuBar().addMenu('&Browser') self.add_actions(menu_browser, (action_open, )) action_log = self.create_action('&Show Log Window...', shortcut=QtGui.QKeySequence(Qt.CTRL + Qt.Key_L), slot=self._on_show_log_window) menu_window = self.menuBar().addMenu('&Window') self.add_actions(menu_window, (action_log,)) action_help_startup = self.create_action('&Startup Help...', shortcut=QtGui.QKeySequence.HelpContents, slot=self._on_help_startup) action_about = self.create_action('&About', slot=self.on_about) menu_help = self.menuBar().addMenu('&Help') self.add_actions(menu_help, (action_help_startup, action_about)) qApp._main_window = self qApp._statusbar = QtGui.QStatusBar(self) self.setStatusBar(qApp._statusbar) self._selection = QtGui.QListWidget(self.centralWidget()) self._selection.setViewMode(QtGui.QListView.IconMode) self._selection.setIconSize(QtCore.QSize(35, 35)) self._selection.setGridSize(QtCore.QSize(140, 60)) self._selection.setMovement(QtGui.QListView.Static) self._selection.setMaximumWidth(self._selection.gridSize().width() + 5) self._selection.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._selection.setSizePolicy( QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Expanding)) self._pages = QtGui.QStackedWidget(self.centralWidget()) self._pages.main_window = self self._settings_filename = None self._settings = GuiConfigSettings(self, SECTION_REGISTRY) self._tab_lookup = OrderedDict() self._tabs = [GeneralFrame(self._settings, self._pages), ObjectDetectionFrame(self._settings, self._pages), FeatureExtractionFrame(self._settings, self._pages), ClassificationFrame(self._settings, self._pages), TrackingFrame(self._settings, self._pages), ErrorCorrectionFrame(self._settings, self._pages), PostProcessingFrame(self._settings, self._pages), OutputFrame(self._settings, self._pages), ProcessingFrame(self._settings, self._pages)] if self.environ.analyzer_config.get('Analyzer', 'cluster_support'): self._tabs.append(ClusterFrame(self._settings, self._pages, self._imagecontainer)) widths = [] for tab in self._tabs: size = self._add_page(tab) widths.append(size.width()) self.set_modules_active(state=False) self._pages.setMinimumWidth(max(widths) + 45) self._selection.currentItemChanged.connect(self._on_change_page) self._selection.setCurrentRow(0) w_logo = QtGui.QLabel(self.centralWidget()) w_logo.setPixmap(QtGui.QPixmap(':cecog_logo_w145')) layout = QtGui.QGridLayout(self.centralWidget()) layout.addWidget(self._selection, 0, 0) layout.addWidget(w_logo, 1, 0, Qt.AlignBottom | Qt.AlignHCenter) layout.addWidget(self._pages, 0, 1, 2, 1) layout.setContentsMargins(1, 1, 1, 1) handler = GuiLogHandler(self) handler.setLevel(logging.INFO) formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') handler.setFormatter(formatter) self.log_window = LogWindow(self, handler) self.log_window.setGeometry(50, 50, 600, 300) logger = logging.getLogger() logger.setLevel(logging.INFO) qApp._image_dialog = None qApp._graphics = None self.setGeometry(0, 0, 1200, 700) self.setMinimumSize(QtCore.QSize(700, 600)) self._is_initialized = True def show(self): super(CecogAnalyzer, self).show() self.center() def closeEvent(self, event): # Quit dialog only if not debuging flag is not set if self.debug: return ret = QMessageBox.question(self, "Quit %s" %self.appname, "Do you really want to quit?", QMessageBox.Yes|QMessageBox.No) if self._check_settings_saved() and ret == QMessageBox.No: event.ignore() else: # FIXME - some dialogs are attributs of qApp # --> QApplication does not exit automatically QtGui.QApplication.exit() def settings_changed(self, changed): if self._is_initialized: self.setWindowModified(changed) self.action_save.setEnabled(changed) self.modified.emit(changed) def _add_page(self, widget): button = QtGui.QListWidgetItem(self._selection) button.setIcon(QtGui.QIcon(widget.ICON)) button.setText(widget.get_name()) button.setTextAlignment(Qt.AlignHCenter) self._pages.addWidget(widget) widget.toggle_tabs.connect(self._on_toggle_tabs) self._tab_lookup[widget.get_name()] = (button, widget) return widget.size() def _on_toggle_tabs(self, name): """Toggle ItemIsEnabled flag for all list items but name.""" for name2 in self._tab_lookup: if name2 != name: item, widget = self._tab_lookup[name2] flags = item.flags() # check flag (and) if flags & Qt.ItemIsEnabled: # remove flag (nand) item.setFlags(flags & ~Qt.ItemIsEnabled) else: # set flag (or) item.setFlags(flags | Qt.ItemIsEnabled) def _on_change_page(self, current, previous): if not current: current = previous index = self._selection.row(current) self._pages.setCurrentIndex(index); widget = self._pages.widget(index) widget.page_changed() def _check_settings_saved(self): if self.isWindowModified(): result = question(self, 'Settings have been modified.', info='Do you want to save settings?', modal=True, show_cancel=True, default=QMessageBox.Yes, escape=QMessageBox.Cancel) if result == QMessageBox.Yes: self.save_settings() else: result = QMessageBox.No return result def center(self): screen = QtGui.QDesktopWidget().screenGeometry() size = self.geometry() self.move((screen.width() - size.width()) / 2, (screen.height() - size.height()) / 2) def add_actions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def create_action(self, text, slot=None, shortcut=None, icon=None, tooltip=None, checkable=None, signal='triggered()', checked=False): action = QtGui.QAction(text, self) if icon is not None: action.setIcon(QtGui.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, QtCore.SIGNAL(signal), slot) if checkable is not None: action.setCheckable(True) action.setChecked(checked) return action def save_settings(self, save_as=False): filename = self._settings_filename if filename is None or save_as: filename = self._get_save_as_filename() if not filename is None: self._write_settings(filename) def _read_settings(self, filename): try: self._settings.read(filename) except: critical(self, "Error loading settings file", info="Could not load settings file '%s'." % filename, detail_tb=True) status('Settings not successfully loaded.') else: self._settings_filename = filename title = self.windowTitle().split(' - ')[0] self.setWindowTitle('%s - %s[*]' % (title, filename)) try: for widget in self._tabs: widget.update_input() except: critical(self, "Problem loading settings file.", info="Fix the problem in file '%s' and load the "\ "settings file again." % filename, detail_tb=True) else: # convert settings if self.version > self._settings.get('General', 'version'): print 'print new version' # set settings to not-changed (assume no changed since loaded from file) self.settings_changed(False) # notify tabs about new settings loaded for tab in self._tabs: tab.settings_loaded() status('Settings successfully loaded.') def _write_settings(self, filename): try: f = file(filename, 'w') # create a new version (copy) of the current # settings which add the needed rendering information settings_dummy = ProcessingFrame.get_export_settings(self._settings) settings_dummy.write(f) f.close() except: critical(self, "Error saving settings file", info="Could not save settings file as '%s'." % filename, detail_tb=True) status('Settings not successfully saved.') else: self._settings_filename = filename self.setWindowTitle('%s - %s[*]' % (self.appname, filename)) self.settings_changed(False) status('Settings successfully saved.') def on_about(self): dialog = CecogAboutDialog(self) dialog.show() def open_preferences(self): print "pref" def _on_browser_open(self): if self._imagecontainer is None: warning(self, 'Data structure not loaded', 'The input data structure was not loaded.\n' 'Please click "Load image data" in General.') elif self._browser is None: try: browser = Browser(self._settings, self._imagecontainer) browser.show() browser.raise_() browser.setFocus() self._browser = browser except: exception(self, 'Problem opening the browser') else: self._browser.show() self._browser.raise_() def _on_load_input(self): txt = "Error scanning image structure" path_in = self._settings.get(SECTION_NAME_GENERAL, 'pathin') if path_in == '': critical(self, txt, "Image path must be defined.") elif not os.path.isdir(path_in) and \ not os.path.isdir(os.path.join(self.environ.package_dir, path_in)): critical(self, txt, "Image path '%s' not found." % path_in) else: try: infos = list(ImageContainer.iter_check_plates(self._settings)) except: exception(self, txt) else: found_any = numpy.any([not info[3] is None for info in infos]) cancel = False if found_any: found_plates = [info[0] for info in infos if not info[3] is None] missing_plates = [info[0] for info in infos if info[3] is None] has_missing = len(missing_plates) > 0 txt = '%s plates were already scanned.\nDo you want ' \ 'to rescan the file structure(s)? ' \ 'This can take several minutes.' % \ ('Some' if has_missing else 'All') title = 'Rescan input structure?' box = QMessageBox(QMessageBox.Question, title, title, QMessageBox.Cancel, self, Qt.Sheet) box.setWindowModality(Qt.WindowModal) box.setInformativeText(txt) box.setDetailedText('Plates with scanned structure: \n%s\n' '\nPlates without scanned structure: ' '\n%s' % ('\n'.join(found_plates), '\n'.join(missing_plates))) if not has_missing: btn1 = QtGui.QPushButton('No', box) box.addButton(btn1, QMessageBox.NoRole) box.setDefaultButton(btn1) elif len(found_plates) > 0: btn1 = QtGui.QPushButton('Rescan missing', box) box.addButton(btn1, QMessageBox.YesRole) box.setDefaultButton(btn1) else: btn1 = None btn2 = QtGui.QPushButton('Rescan all', box) box.addButton(btn2, QMessageBox.YesRole) if box.exec_() == QMessageBox.Cancel: cancel = True else: btn = box.clickedButton() if btn == btn1: if has_missing: scan_plates = dict([(info[0], info[0] in missing_plates) for info in infos]) else: scan_plates = dict((info[0], False) for info in infos) else: scan_plates = dict((info[0], True) for info in infos) else: has_multiple = self._settings.get(SECTION_NAME_GENERAL, "has_multiple_plates") if not question(self, "No structure data found", "Are you sure to scan %s?\n\nThis can take " "several minutes depending on the number of" " images." % ("%d plates" % len(infos) if has_multiple else "one plate")): cancel = True scan_plates = dict((info[0], True) for info in infos) if not cancel: self._load_image_container(infos, scan_plates) def _load_image_container(self, plate_infos, scan_plates=None, show_dlg=True): self._clear_browser() imagecontainer = ImageContainer() self._imagecontainer = imagecontainer if scan_plates is None: scan_plates = dict((info[0], False) for info in plate_infos) def load(dlg): iter = imagecontainer.iter_import_from_settings(self._settings, scan_plates) for idx, info in enumerate(iter): dlg.targetSetValue.emit(idx + 1) if len(imagecontainer.plates) > 0: plate = imagecontainer.plates[0] imagecontainer.set_plate(plate) self.dlg = waitingProgressDialog('Please wait until the input structure is scanned\n' 'or the structure data loaded...', self, load, (0, len(scan_plates))) self.dlg.exec_(passDialog=True) if len(imagecontainer.plates) > 0: imagecontainer.check_dimensions() channels = imagecontainer.channels # do not report value changes to the main window self._settings.set_notify_change(False) self.set_image_crop_size() problems = [] for prefix in ['primary', 'secondary', 'tertiary']: trait = self._settings.get_trait(SECTION_NAME_OBJECTDETECTION, '%s_channelid' % prefix) if trait.set_list_data(channels) is None: problems.append(prefix) self._tabs[1].get_widget('%s_channelid' % prefix).update() # report problems about a mismatch between channel IDs found in the data and specified by the user if len(problems) > 0: critical(self, "Selected channel IDs not valid", "The selected channel IDs for %s are not valid.\nValid IDs are %s." % (", ".join(["'%s Channel'" % s.capitalize() for s in problems]), ", ".join(["'%s'" % s for s in channels]))) # a mismatch between settings and data will cause changed settings self.settings_changed(True) trait = self._settings.get_trait(SECTION_NAME_TRACKING, 'tracking_duration_unit') # allow time-base tracking durations only if time-stamp # information is present meta_data = imagecontainer.get_meta_data() if meta_data.has_timestamp_info: result = trait.set_list_data(TRACKING_DURATION_UNITS_TIMELAPSE) else: result = trait.set_list_data(TRACKING_DURATION_UNITS_DEFAULT) if result is None: critical(self, "Could not set tracking duration units", "The tracking duration units selected to match the load data. Please check your settings.") # a mismatch between settings and data will cause changed settings self.settings_changed(True) # activate change notification again self._settings.set_notify_change(True) self.set_modules_active(state=True) if show_dlg: information(self, "Plate(s) successfully loaded", "%d plates loaded successfully." % len(imagecontainer.plates)) else: critical(self, "No valid image data found", "The naming schema provided might not fit your image data" "or the coordinate file is not correct.\n\nPlease modify " "the values and scan the structure again.") def set_image_crop_size(self): x0, y0, x1, y1 = self._settings.get('General', 'crop_image_x0'), \ self._settings.get('General', 'crop_image_y0'), \ self._settings.get('General', 'crop_image_x1'), \ self._settings.get('General', 'crop_image_y1') x0_, y0_, x1_, y1_ = 0, \ 0, \ self._imagecontainer.get_meta_data().dim_x, \ self._imagecontainer.get_meta_data().dim_y tr_x0 = self._settings.get_trait(SECTION_NAME_GENERAL, 'crop_image_x0') tr_y0 = self._settings.get_trait(SECTION_NAME_GENERAL, 'crop_image_y0') tr_x1 = self._settings.get_trait(SECTION_NAME_GENERAL, 'crop_image_x1') tr_y1 = self._settings.get_trait(SECTION_NAME_GENERAL, 'crop_image_y1') # Check if the crop values are valid if x0 > 0 and y0 > 0 and x1 <= x1_ and y1 <= y1_ and \ x0 != x1 and y0 != y1: # Set to default values tr_x0.set_value(tr_x0.get_widget(), x0) tr_y0.set_value(tr_y0.get_widget(), y0) tr_x1.set_value(tr_x1.get_widget(), x1) tr_y0.set_value(tr_y1.get_widget(), y1) else: tr_x0.set_value(tr_x0.get_widget(), x0_) tr_y0.set_value(tr_y0.get_widget(), y0_) tr_x1.set_value(tr_x1.get_widget(), x1_) tr_y0.set_value(tr_y1.get_widget(), y1_) # Set GUI widget valid ranges tr_x0.set_min_value(x0_) tr_x0.set_max_value(x1_) tr_y0.set_min_value(y0_) tr_y0.set_max_value(y1_) tr_x1.set_min_value(x0_) tr_x1.set_max_value(x1_) tr_y1.set_min_value(y0_) tr_y1.set_max_value(y1_) def set_modules_active(self, state=True): for name, (button, widget) in self._tab_lookup.iteritems(): widget.set_active(state) @QtCore.pyqtSlot() def _on_file_open(self): if self._check_settings_saved() != QMessageBox.Cancel: dir = "" if not self._settings_filename is None: settings_filename = self.environ.convert_package_path( self._settings_filename) if os.path.isfile(settings_filename): dir = settings_filename filename = QtGui.QFileDialog.getOpenFileName(self, 'Open config file', dir, ';;'.join(self.NAME_FILTERS)) if filename: self._read_settings(filename) if self._settings.was_old_file_format(): information(self, ('Selected config file had an old ' 'version <= 1.3.0. The current version is %s. ' 'The config file was be updated...' %self.version)) else: information(self, "Config file version %s found" \ %self._settings.get('General', 'version')) self._clear_browser() self.set_modules_active(state=False) @QtCore.pyqtSlot() def _on_file_save(self): self.save_settings(False) @QtCore.pyqtSlot() def _on_file_save_as(self): self.save_settings(True) def _clear_browser(self): # close and delete the current browser instance if not self._browser is None: self._browser.close() self._browser = None def _on_show_log_window(self): logger = logging.getLogger() logger.addHandler(self.log_window.handler) self.log_window.show() #self.log_window.raise_() def _get_save_as_filename(self): dir = "" if not self._settings_filename is None: settings_filename = self.environ.convert_package_path( self._settings_filename) if os.path.isfile(settings_filename): dir = settings_filename filename = QtGui.QFileDialog.getSaveFileName( self, 'Save config file as', dir, ';;'.join(self.NAME_FILTERS)) return filename or None def _on_help_startup(self): show_html('_startup')
def load_classifier(self, check=True): _resolve = lambda x, y: self._settings.get( x, '%s_%s' % (self._channel, y)) clfdir = CecogEnvironment.convert_package_path( _resolve('Classification', 'classification_envpath')) # XXX - where does the "." come if not isdir(clfdir) or clfdir == ".": return else: self._learner = CommonClassPredictor( \ clf_dir=clfdir, name=self._channel, channels={self._channel.title(): _resolve('Classification', 'classification_regionname')}, color_channel=_resolve('ObjectDetection', 'channelid')) result = self._learner.check() if check: b = lambda x: 'Yes' if x else 'No' msg = 'Classifier path: %s\n' % result['path_env'] msg += 'Found class definition: %s\n' % b( result['has_definition']) msg += 'Found annotations: %s\n' % b( result['has_path_annotations']) msg += 'Can you pick new samples? %s\n\n' % b( self.is_pick_samples()) msg += 'Found ARFF file: %s\n' % b(result['has_arff']) msg += 'Can you train a classifier? %s\n\n' % b( self.is_train_classifier()) msg += 'Found SVM model: %s\n' % b(result['has_model']) msg += 'Found SVM range: %s\n' % b(result['has_range']) msg += 'Can you apply the classifier to images? %s\n\n' % b( self.is_apply_classifier()) msg += 'Found samples: %s\n' % b(result['has_path_samples']) msg += 'Sample images are only used for visualization and annotation control at the moment.' txt = '%s classifier inspection results' % self._channel information(self, txt, info=msg) if result['has_arff']: self._learner.importFromArff() nr_features_prev = len(self._learner.feature_names) removed_features = self._learner.filter_nans(apply=True) nr_features = nr_features_prev - len(removed_features) self._label_features.setText(self.LABEL_FEATURES % (nr_features, nr_features_prev)) self._label_features.setToolTip( "removed %d features containing NA values:\n%s" % (len(removed_features), "\n".join(removed_features))) if result['has_definition']: self._learner.loadDefinition() if result['has_conf']: c, g, conf = self._learner.importConfusion() self._set_info(c, g, conf) self._init_conf_table(conf) self._update_conf_table(conf) else: conf = None self._init_conf_table(conf) self._set_info_table(conf)
def _on_process_start(self, name, start_again=False): if not self._is_running or start_again: is_valid = True self._is_abort = False self._has_error = False if self._process_items is None: cls = self._control_buttons[name]['cls'] if type(cls) == types.ListType: self._process_items = cls self._current_process_item = 0 cls = cls[self._current_process_item] # remove HmmThread if process is not first in list and # not valid error correction was activated if (HmmThread in self._process_items and self._process_items.index(HmmThread) > 0 and not (self._settings.get( 'Processing', 'primary_errorcorrection') or (self._settings.get( 'Processing', 'secondary_errorcorrection') and self._settings.get( 'Processing', 'secondary_processchannel')))): self._process_items.remove(HmmThread) else: self._process_items = None self._current_process_item = 0 else: cls = self._process_items[self._current_process_item] if self.SECTION_NAME == 'Classification': result_frame = self._get_result_frame(self._tab_name) result_frame.load_classifier(check=False) learner = result_frame._learner if name == self.PROCESS_PICKING: if not result_frame.is_pick_samples(): is_valid = False result_frame.msg_pick_samples(self) elif result_frame.is_train_classifier(): if not question( self, 'Samples already picked', 'Do you want to pick samples again and ' 'overwrite previous ' 'results?'): is_valid = False elif name == self.PROCESS_TRAINING: if not result_frame.is_train_classifier(): is_valid = False result_frame.msg_train_classifier(self) elif result_frame.is_apply_classifier(): if not question( self, 'Classifier already trained', 'Do you want to train the classifier ' 'again?'): is_valid = False elif name == self.PROCESS_TESTING and not result_frame.is_apply_classifier( ): is_valid = False result_frame.msg_apply_classifier(self) elif cls is HmmThread: success, cmd = HmmThread.test_executable( self._settings.get('ErrorCorrection', 'filename_to_R')) if not success: critical(self, 'Error running R', "The R command line program '%s' could not be executed.\n\n"\ "Make sure that the R-project is installed.\n\n"\ "See README.txt for details." % cmd) is_valid = False elif cls is MultiAnalyzerThread: ncpu = cpu_count() (ncpu, ok) = QInputDialog.getInt(None, "On your machine are %d processers available." % ncpu, \ "Select the number of processors", \ ncpu, 1, ncpu*2) if not ok: self._process_items = None is_valid = False if is_valid: self._current_process = name if not start_again: self.parent().main_window.log_window.clear() self._is_running = True self._stage_infos = {} self._toggle_tabs(False) # disable all section button of the main widget self.toggle_tabs.emit(self.get_name()) self._set_control_button_text(idx=1) self._toggle_control_buttons() imagecontainer = self.parent().main_window._imagecontainer if cls is PickerThread: self._current_settings = self._get_modified_settings( name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, imagecontainer) self._set_display_renderer_info() self._clear_image() elif cls is AnalyzerThread: self._current_settings = self._get_modified_settings( name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, imagecontainer) self._set_display_renderer_info() self._clear_image() elif cls is TrainingThread: self._current_settings = self._settings.copy() self._analyzer = cls(self, self._current_settings, result_frame._learner) self._analyzer.setTerminationEnabled(True) self._analyzer.conf_result.connect( result_frame.on_conf_result, Qt.QueuedConnection) result_frame.reset() elif cls is MultiAnalyzerThread: self._current_settings = self._get_modified_settings( name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, imagecontainer, ncpu) self._set_display_renderer_info() elif cls is HmmThread: self._current_settings = self._get_modified_settings( name, imagecontainer.has_timelapse) # FIXME: classifier handling needs revision!!! learner_dict = {} for kind in ['primary', 'secondary']: _resolve = lambda x, y: self._settings.get( x, '%s_%s' % (kind, y)) env_path = CecogEnvironment.convert_package_path( _resolve('Classification', 'classification_envpath')) if (os.path.exists(env_path) and (kind == 'primary' or self._settings.get( 'Processing', 'secondary_processchannel'))): learner = CommonClassPredictor( \ env_path, _resolve('ObjectDetection', 'channelid'), _resolve('Classification', 'classification_regionname')) learner.importFromArff() learner_dict[kind] = learner ### Whee, I like it... "self.parent().main_window._imagecontainer" crazy, crazy, michael... :-) self._analyzer = cls( self, self._current_settings, learner_dict, self.parent().main_window._imagecontainer) self._analyzer.setTerminationEnabled(True) lw = self.parent().main_window.log_window lw.show() elif cls is PostProcessingThread: learner_dict = {} for kind in ['primary', 'secondary']: _resolve = lambda x, y: self._settings.get( x, '%s_%s' % (kind, y)) env_path = CecogEnvironment.convert_package_path( _resolve('Classification', 'classification_envpath')) if (_resolve('Processing', 'classification') and (kind == 'primary' or self._settings.get( 'Processing', 'secondary_processchannel'))): learner = CommonClassPredictor( \ env_path, _resolve('ObjectDetection', 'channelid'), _resolve('Classification', 'classification_regionname')) learner.importFromArff() learner_dict[kind] = learner self._current_settings = self._get_modified_settings( name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, learner_dict, imagecontainer) self._analyzer.setTerminationEnabled(True) self._analyzer.finished.connect(self._on_process_finished) self._analyzer.stage_info.connect(self._on_update_stage_info, Qt.QueuedConnection) self._analyzer.analyzer_error.connect(self._on_error, Qt.QueuedConnection) self._analyzer.start(QThread.LowestPriority) if self._current_process_item == 0: status('Process started...') else: self._abort_processing()
def _on_process_start(self, name, start_again=False): if not self._is_running or start_again: is_valid = True self._is_abort = False self._has_error = False if self._process_items is None: cls = self._control_buttons[name]['cls'] if type(cls) == types.ListType: self._process_items = cls self._current_process_item = 0 cls = cls[self._current_process_item] # remove HmmThread if process is not first in list and # not valid error correction was activated if (HmmThread in self._process_items and self._process_items.index(HmmThread) > 0 and not (self._settings.get('Processing', 'primary_errorcorrection') or (self._settings.get('Processing', 'secondary_errorcorrection') and self._settings.get('Processing', 'secondary_processchannel')))): self._process_items.remove(HmmThread) else: self._process_items = None self._current_process_item = 0 else: cls = self._process_items[self._current_process_item] if self.SECTION_NAME == 'Classification': result_frame = self._get_result_frame(self._tab_name) result_frame.load_classifier(check=False) learner = result_frame._learner if name == self.PROCESS_PICKING: if not result_frame.is_pick_samples(): is_valid = False result_frame.msg_pick_samples(self) elif result_frame.is_train_classifier(): if not question(self, 'Samples already picked', 'Do you want to pick samples again and ' 'overwrite previous ' 'results?'): is_valid = False elif name == self.PROCESS_TRAINING: if not result_frame.is_train_classifier(): is_valid = False result_frame.msg_train_classifier(self) elif result_frame.is_apply_classifier(): if not question(self, 'Classifier already trained', 'Do you want to train the classifier ' 'again?'): is_valid = False elif name == self.PROCESS_TESTING and not result_frame.is_apply_classifier(): is_valid = False result_frame.msg_apply_classifier(self) elif cls is HmmThread: success, cmd = HmmThread.test_executable(self._settings.get('ErrorCorrection', 'filename_to_R')) if not success: critical(self, 'Error running R', "The R command line program '%s' could not be executed.\n\n"\ "Make sure that the R-project is installed.\n\n"\ "See README.txt for details." % cmd) is_valid = False elif cls is MultiAnalyzerThread: ncpu = cpu_count() (ncpu, ok) = QInputDialog.getInt(None, "On your machine are %d processers available." % ncpu, \ "Select the number of processors", \ ncpu, 1, ncpu*2) if not ok: self._process_items = None is_valid = False if is_valid: self._current_process = name if not start_again: self.parent().main_window.log_window.clear() self._is_running = True self._stage_infos = {} self._toggle_tabs(False) # disable all section button of the main widget self.toggle_tabs.emit(self.get_name()) self._set_control_button_text(idx=1) self._toggle_control_buttons() imagecontainer = self.parent().main_window._imagecontainer if cls is PickerThread: self._current_settings = self._get_modified_settings(name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, imagecontainer) self._set_display_renderer_info() self._clear_image() elif cls is AnalyzerThread: self._current_settings = self._get_modified_settings(name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, imagecontainer) self._set_display_renderer_info() self._clear_image() elif cls is TrainingThread: self._current_settings = self._settings.copy() self._analyzer = cls(self, self._current_settings, result_frame._learner) self._analyzer.setTerminationEnabled(True) self._analyzer.conf_result.connect(result_frame.on_conf_result, Qt.QueuedConnection) result_frame.reset() elif cls is MultiAnalyzerThread: self._current_settings = self._get_modified_settings(name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, imagecontainer, ncpu) self._set_display_renderer_info() elif cls is HmmThread: self._current_settings = self._get_modified_settings(name, imagecontainer.has_timelapse) # FIXME: classifier handling needs revision!!! learner_dict = {} for kind in ['primary', 'secondary']: _resolve = lambda x,y: self._settings.get(x, '%s_%s' % (kind, y)) env_path = CecogEnvironment.convert_package_path(_resolve('Classification', 'classification_envpath')) if (os.path.exists(env_path) and (kind == 'primary' or self._settings.get('Processing', 'secondary_processchannel')) ): learner = CommonClassPredictor( \ env_path, _resolve('ObjectDetection', 'channelid'), _resolve('Classification', 'classification_regionname')) learner.importFromArff() learner_dict[kind] = learner ### Whee, I like it... "self.parent().main_window._imagecontainer" crazy, crazy, michael... :-) self._analyzer = cls(self, self._current_settings, learner_dict, self.parent().main_window._imagecontainer) self._analyzer.setTerminationEnabled(True) lw = self.parent().main_window.log_window lw.show() elif cls is PostProcessingThread: learner_dict = {} for kind in ['primary', 'secondary']: _resolve = lambda x,y: self._settings.get(x, '%s_%s' % (kind, y)) env_path = CecogEnvironment.convert_package_path(_resolve('Classification', 'classification_envpath')) if (_resolve('Processing', 'classification') and (kind == 'primary' or self._settings.get('Processing', 'secondary_processchannel'))): learner = CommonClassPredictor( \ env_path, _resolve('ObjectDetection', 'channelid'), _resolve('Classification', 'classification_regionname')) learner.importFromArff() learner_dict[kind] = learner self._current_settings = self._get_modified_settings(name, imagecontainer.has_timelapse) self._analyzer = cls(self, self._current_settings, learner_dict, imagecontainer) self._analyzer.setTerminationEnabled(True) self._analyzer.finished.connect(self._on_process_finished) self._analyzer.stage_info.connect(self._on_update_stage_info, Qt.QueuedConnection) self._analyzer.analyzer_error.connect(self._on_error, Qt.QueuedConnection) self._analyzer.start(QThread.LowestPriority) if self._current_process_item == 0: status('Process started...') else: self._abort_processing()