def __init__(self, parent, plugin_manager, settings): super(QFrame, self).__init__(parent) self.plugin_manager = plugin_manager self.plugin_manager.register_observer(self) self.settings = settings self._plugins = OrderedDict() self.setStyleSheet( "PluginItem { border: 1px solid black; background: white; }") layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) frame1 = QFrame(self) self._frame2 = QFrame(self) layout.addWidget(frame1) layout.addSpacing(10) layout.addWidget(self._frame2) label = QLabel('%s plugins' % plugin_manager.display_name, frame1) label.setStyleSheet("font-weight: bold;") btn = QPushButton('Add', frame1) btn.clicked.connect(self._on_add_plugin) self._cb = QComboBox(frame1) self._set_plugin_labels() layout = QHBoxLayout(frame1) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(label) layout.addWidget(self._cb, 1) layout.addWidget(btn) layout = QVBoxLayout(self._frame2) layout.setContentsMargins(0, 0, 0, 0)
class SectionRegistry(object): def __init__(self): self._registry = OrderedDict() def register_section(self, section): self._registry[section.SECTION_NAME] = section def unregister_section(self, name): del self._registry[name] def get_section(self, name): return self._registry[name] def get_section_names(self): return self._registry.keys() def get_path_settings(self): result = [] for section_name, section in self._registry.iteritems(): for trait_name in section.get_trait_names(): trait = section.get_trait(trait_name) if (isinstance(trait, StringTrait) and trait.widget_info in [StringTrait.STRING_FILE, StringTrait.STRING_PATH]): result.append((section_name, trait_name, trait)) return result
def getSamples(self, className): self._loadInfos() strPathSamples = os.path.join(self._oLearner.dctEnvPaths['samples'], className) lstResults = [] if os.path.isdir(strPathSamples): #print len(self._oLearner.lstFeatureNames), len() dctImagePairs = OrderedDict() for strName, oMatch in collect_files_by_regex(strPathSamples, '(?P<prefix>.+?)__(?P<type>(img)|(msk)).+?', ['.png', '.jpg']): strPrefix = oMatch.group('prefix') strType = oMatch.group('type') if not strPrefix in dctImagePairs: dctImagePairs[strPrefix] = {} dctImagePairs[strPrefix][strType] = strName iIdx = 0 for dctPair in dctImagePairs.values(): #oContainer = ccore.SingleObjectContainer(dctPair['img'], dctPair['msk']) #strCoords = ",".join(map(str,flatten(oContainer.getCrackCoordinates(1)))) #print dctPair['img'], dctPair['msk'] #dctFeatures = {} #for iF, strFeatureName in enumerate(self._oLearner.lstFeatureNames): # dctFeatures[strFeatureName] = self._oLearner.dctFeatureData[className][iIdx][iF] oSample = Sample(dctPair['img']) lstResults.append(oSample) iIdx += 1 #break return lstResults
def __init__(self, name=None, path=None): #super(Classifier, self).__init__() self.name = name self.path = path self.dctClassInfos = OrderedDict() self.dctFeatureInfos = OrderedDict() self.isInitialized = False
def __init__(self, display_name, name, section): super(PluginManager, self).__init__() self.display_name = display_name self.name = name self.section = section self._plugins = OrderedDict() self._instances = OrderedDict() self._observer = []
def __init__(self, **options): self.dctFeatureData = OrderedDict() self.dctClassNames = {} self.dctClassLabels = {} self.lstFeatureNames = None self.dctHexColors = {} self.dctSampleNames = {} self.dctEnvPaths = {} self.hasZeroInsert = False self.dctImageObjects = OrderedDict() super(BaseLearner, self).__init__(**options)
def _updateClassifiers(self): self._dctClassifiers = OrderedDict() for strName in os.listdir(self.strPath): strPathClassifier = os.path.join(self.strPath, strName) if os.path.isdir(strPathClassifier) and strName[0] not in ['.', '_']: oClassifier = Classifier(strName, strPathClassifier) self._dctClassifiers[strName] = oClassifier
def get_pheno_type_phenes(cls): """ Returns a map containing all phenes of the given (L{PhenoType}) class. @param cls: class to query @type cls: L{PhenoType} @return: phene name (L{str}) to L{Phene} instance map @rtype: L{dict} """ phene_map = OrderedDict() for base in get_bases(cls) + [cls]: for name, value in base.__dict__.iteritems(): if isinstance(value, Phene): phene_map[name] = value phene_map.sort(key = lambda name: phene_map[name].rank, reverse=True) return phene_map
def __init__(self, parent, plugin_manager, settings): super(QFrame, self).__init__(parent) self.plugin_manager = plugin_manager self.plugin_manager.register_observer(self) self.settings = settings self._plugins = OrderedDict() self.setStyleSheet("PluginItem { border: 1px solid black; background: white; }") layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) frame1 = QFrame(self) self._frame2 = QFrame(self) layout.addWidget(frame1) layout.addSpacing(10) layout.addWidget(self._frame2) label = QLabel('%s plugins' % plugin_manager.display_name, frame1) label.setStyleSheet("font-weight: bold;") btn = QPushButton('Add', frame1) btn.clicked.connect(self._on_add_plugin) self._cb = QComboBox(frame1) self._set_plugin_labels() layout = QHBoxLayout(frame1) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(label) layout.addWidget(self._cb, 1) layout.addWidget(btn) layout = QVBoxLayout(self._frame2) layout.setContentsMargins(0, 0, 0, 0)
def get_pheno_type_phenes(cls): """ Returns a map containing all phenes of the given (L{PhenoType}) class. @param cls: class to query @type cls: L{PhenoType} @return: phene name (L{str}) to L{Phene} instance map @rtype: L{dict} """ phene_map = OrderedDict() for base in get_bases(cls) + [cls]: for name, value in base.__dict__.iteritems(): if isinstance(value, Phene): phene_map[name] = value phene_map.sort(key=lambda name: phene_map[name].rank, reverse=True) return phene_map
def __init__(self): self._registry = OrderedDict() self._traitname_grpname = OrderedDict() for grp_name, grp_items in self.OPTIONS: grp = TraitGroup(grp_name) self._registry[grp_name] = grp for trait_name, trait in grp_items: trait_name = trait_name.lower() grp.register_trait(trait_name, trait) self._traitname_grpname[trait_name] = grp_name
def __init__(self, parent, hide_one=True): QFrame.__init__(self, parent) self.setStyleSheet(TAB_STYLE) self._hide_one = hide_one self._tabs = OrderedDict() layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) self._btn_frame = QFrame(self) self._btn_grp = QButtonGroup(self._btn_frame) self._btn_grp.setExclusive(True) self._btn_layout = QHBoxLayout(self._btn_frame) self._btn_layout.insertStretch(0, 1) self._btn_layout.insertStretch(1, 1) self._stacked_frame = QStackedWidget(self) self._stacked_frame.setObjectName('stacked') layout.addWidget(self._btn_frame) layout.addWidget(self._stacked_frame) self._btn_frame.hide() self._current_name = None
def __init__(self, P, channels, filename, filename_hdf5, meta_data, settings, create_nc=True, reuse_nc=True, hdf5_create=True, hdf5_include_raw_images=True, hdf5_include_label_images=True, hdf5_include_features=True): super(TimeHolder, self).__init__() self.P = P self._iCurrentT = None self.channels = channels self._meta_data = meta_data self._settings = settings self._create_nc = create_nc self._reuse_nc = reuse_nc self._nc4_filename = filename self._dataset = None self._hdf5_create = hdf5_create self._hdf5_include_raw_images = hdf5_include_raw_images self._hdf5_include_label_images = hdf5_include_label_images self._hdf5_include_features = hdf5_include_features self._logger = logging.getLogger(self.__class__.__name__) # frames get an index representation with the NC file, starting at 0 frames = sorted(list(meta_data.times)) self._frames_to_idx = dict([(f,i) for i, f in enumerate(frames)]) self._idx_to_frames = dict([(i,f) for i, f in enumerate(frames)]) channels = sorted(list(meta_data.channels)) region_names = REGION_NAMES_PRIMARY + REGION_NAMES_SECONDARY region_channels = ['primary']*len(REGION_NAMES_PRIMARY) + \ ['secondary']*len(REGION_NAMES_SECONDARY) region_names2 = [('Primary', 'primary')] #channel_names2 = [('Primary'] settings.set_section('ObjectDetection') for prefix in ['secondary', 'tertiary']: if settings.get('Processing', '%s_processchannel' % prefix): for name in REGION_NAMES_SECONDARY: if settings.get2('%s_regions_%s' % (prefix, name)): region_names2.append((prefix.capitalize(), name)) self._channels_to_idx = dict([(f,i) for i, f in enumerate(channels)]) self._idx_to_channels = dict([(i,f) for i, f in enumerate(channels)]) self._regions_to_idx = dict([(n,i) for i, n in enumerate(region_names)]) self._regions_to_idx2 = OrderedDict([(n,i) for i, n in enumerate(region_names2)]) if self._hdf5_create: f = h5py.File(filename_hdf5, 'w') self._hdf5_file = f
class TraitGroup(object): def __init__(self, name): self.name = name self._registry = OrderedDict() def register_trait(self, name, trait): self._registry[name] = trait def get_trait(self, name): return self._registry[name] def get_trait_names(self): return self._registry.keys()
class _Section(object): SECTION_NAME = None OPTIONS = None def __init__(self): self._registry = OrderedDict() self._traitname_grpname = OrderedDict() for grp_name, grp_items in self.OPTIONS: grp = TraitGroup(grp_name) self._registry[grp_name] = grp for trait_name, trait in grp_items: trait_name = trait_name.lower() grp.register_trait(trait_name, trait) self._traitname_grpname[trait_name] = grp_name def get_group(self, name): return self._registry[name] def get_group_names(self): return self._registry.keys() def get_trait(self, trait_name): grp_name = self._traitname_grpname[trait_name] grp = self._registry[grp_name] return grp.get_trait(trait_name) def get_trait_names(self): names = [] for grp in self._registry.values(): names += grp.get_trait_names() return set(names) def get_trait_names_for_group(self, name): grp = self.get_group(name) return grp.get_trait_names()
def run(self, *args, **options): results = OrderedDict() for instance in self._instances.itervalues(): inst_args = list(args) if not instance.REQUIRES is None: if not 'requirements' in options: raise ValueError(( "PluginManager(%s).run needs 'requirements' options, " "because Plugin instances '%s' defines requirements." % (self.name, instance.name))) requirements = options['requirements'] for idx in range(len(instance.REQUIRES)): value = instance.get_requirement_info(idx)[1] data = requirements[idx].get_requirement(value) inst_args.append(data) results[instance.name] = instance.run(*inst_args) return results
class ClassifierService(object): def __init__(self, path): self.strPath = path self._dctClassifiers = None self._updateClassifiers() def _updateClassifiers(self): self._dctClassifiers = OrderedDict() for strName in os.listdir(self.strPath): strPathClassifier = os.path.join(self.strPath, strName) if os.path.isdir(strPathClassifier) and strName[0] not in ['.', '_']: oClassifier = Classifier(strName, strPathClassifier) self._dctClassifiers[strName] = oClassifier def getAll(self, update): logging.info("getAll, update: %s" % update) if update: self._updateClassifiers() return self._dctClassifiers.values() def getClassInfos(self, name): logging.info("getClassInfos") oClassifier = self._dctClassifiers[name] return oClassifier.classInfos def getFeatureInfos(self, name): logging.info("getFeatureInfos") oClassifier = self._dctClassifiers[name] return oClassifier.featureInfos def getSampleInfos(self, classifierName, className): logging.info("getClassSamples %s %s" % (classifierName, className)) oClassifier = self._dctClassifiers[classifierName] return oClassifier.getSamples(className) def getFeatureData(self, classifierName, featureNames): logging.info("getFeatureData %s %s" % (classifierName, featureNames)) oClassifier = self._dctClassifiers[classifierName] return oClassifier.getFeatureData(featureNames)
def export_to_xml(self, path, names_to_labels, imagecontainer): impl = minidom.getDOMImplementation() ann = self._annotations for plateid in ann: # load plate specific meta data imagecontainer.set_plate(plateid) meta_data = imagecontainer.get_meta_data() time_points = meta_data.times # the reference time on which this file is based on min_time = time_points[0] for position in ann[plateid]: ann2 = ann[plateid][position] bycn = OrderedDict() for time in ann2: for cn in ann2[time]: if not cn in bycn: bycn[cn] = OrderedDict() bycn[cn][time] = ann2[time][cn] doc = impl.createDocument(None, 'CellCounter_Marker_File', None) top = doc.documentElement element = doc.createElement('Marker_Data') top.appendChild(element) idx_base = time_points.index(min_time) for cn in bycn: element2 = doc.createElement('Marker_Type') element.appendChild(element2) element3 = doc.createElement('Type') class_label = names_to_labels[cn] text = doc.createTextNode(str(class_label)) element3.appendChild(text) element2.appendChild(element3) for time in bycn[cn]: idx = time_points.index(time) + 1 - idx_base for item in bycn[cn][time]: element3 = doc.createElement('Marker') element4 = doc.createElement('MarkerX') text = doc.createTextNode(str(item[0])) element4.appendChild(text) element3.appendChild(element4) element4 = doc.createElement('MarkerY') text = doc.createTextNode(str(item[1])) element4.appendChild(text) element3.appendChild(element4) element4 = doc.createElement('MarkerZ') text = doc.createTextNode(str(idx)) element4.appendChild(text) element3.appendChild(element4) element2.appendChild(element3) filename = 'PL%s___P%s___T%05d.xml' % \ (plateid, position, min_time) f = file(os.path.join(path, filename), 'w') doc.writexml(f, indent=' ', addindent=' ', encoding='utf8', newl='\n') f.close()
class PluginBay(QFrame): def __init__(self, parent, plugin_manager, settings): super(QFrame, self).__init__(parent) self.plugin_manager = plugin_manager self.plugin_manager.register_observer(self) self.settings = settings self._plugins = OrderedDict() self.setStyleSheet("PluginItem { border: 1px solid black; background: white; }") layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) frame1 = QFrame(self) self._frame2 = QFrame(self) layout.addWidget(frame1) layout.addSpacing(10) layout.addWidget(self._frame2) label = QLabel('%s plugins' % plugin_manager.display_name, frame1) label.setStyleSheet("font-weight: bold;") btn = QPushButton('Add', frame1) btn.clicked.connect(self._on_add_plugin) self._cb = QComboBox(frame1) self._set_plugin_labels() layout = QHBoxLayout(frame1) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(label) layout.addWidget(self._cb, 1) layout.addWidget(btn) layout = QVBoxLayout(self._frame2) layout.setContentsMargins(0, 0, 0, 0) def init(self): self.reset() for plugin_name in self.plugin_manager.get_plugin_names(): self.add_plugin(plugin_name) def notify(self, plugin_name, removed): pass def _set_plugin_labels(self): self._cb.clear() for name, label in self.plugin_manager.get_plugin_labels(): self._cb.addItem(label, name) def reset(self): self._set_plugin_labels() for plugin_name in self._plugins.keys()[:]: self.remove_plugin(plugin_name) def add_plugin(self, plugin_name): plugin = self.plugin_manager.get_plugin_instance(plugin_name) item = PluginItem(self._frame2, plugin, self.settings) item.remove_item.connect(functools.partial(self._on_remove_plugin, plugin_name)) layout = self._frame2.layout() layout.insertWidget(0, item) self._plugins[plugin_name] = item def remove_plugin(self, plugin_name): layout = self._frame2.layout() item = self._plugins[plugin_name] item.close() layout.removeWidget(item) del self._plugins[plugin_name] def _on_add_plugin(self): name_cls = self._cb.itemData(self._cb.currentIndex()) plugin_name = self.plugin_manager.add_instance(name_cls, self.settings) self.add_plugin(plugin_name) def _on_remove_plugin(self, plugin_name): instance = self.plugin_manager.get_plugin_instance(plugin_name) result = False n = len(instance.referees) if n == 0: result = question(None, 'Removing the plugin "%s"' % plugin_name, "Are you sure to remove this plugin?") elif n > 0: detail = '\n'.join(['%s (%s)' % x[:2] for x in instance.referees]) result = question(None, 'Removing the plugin "%s"' % plugin_name, '%d other plugin%s require%s this plugin.\n\nAre you sure to remove this plugin?' % (n, 's' if n > 1 else '', 's' if n == 1 else ''), detail=detail, icon=QMessageBox.Warning) if result: self.remove_plugin(plugin_name) self.plugin_manager.remove_instance(plugin_name, self.settings)
class PluginManager(object): PREFIX = 'plugin' LABEL = '' def __init__(self, display_name, name, section): super(PluginManager, self).__init__() self.display_name = display_name self.name = name self.section = section self._plugins = OrderedDict() self._instances = OrderedDict() self._observer = [] def init_from_settings(self, settings): plugin_params = {} plugin_cls_names = {} for option_name in settings.options(self.section): items = option_name.split('__') if len(items ) > 4 and items[0] == self.PREFIX and items[1] == self.name: plugin_cls_name = items[2] plugin_name = items[3] params = items[4] if not plugin_name in plugin_cls_names: plugin_cls_names[plugin_name] = plugin_cls_name else: assert plugin_cls_names[plugin_name] == plugin_cls_name plugin_params.setdefault(plugin_name, []).append( (option_name, params)) for plugin_name in plugin_params: plugin_cls_name = plugin_cls_names[plugin_name] plugin_cls = self._plugins[plugin_cls_name] param_manager = \ ParamManager.from_settings(plugin_cls, plugin_name, settings, self, plugin_params[plugin_name]) instance = plugin_cls(plugin_name, param_manager) self._instances[plugin_name] = instance self.notify_instance_modified(plugin_name) for observer in self._observer: observer.init() def clear(self): for plugin_name, instance in self._instances.iteritems(): instance.close() self.notify_instance_modified(plugin_name, True) self._instances.clear() def add_instance(self, plugin_cls_name, settings): if not plugin_cls_name in self._plugins: raise ValueError("Plugin '%s' not registered for '%s'." % (plugin_cls_name, self.name)) plugin_cls = self._plugins[plugin_cls_name] plugin_name = self._get_plugin_name(plugin_cls) param_manager = ParamManager(plugin_cls, plugin_name, settings, self) instance = plugin_cls(plugin_name, param_manager) self._instances[plugin_name] = instance self.notify_instance_modified(plugin_name) return plugin_name def remove_instance(self, plugin_name, settings): if not plugin_name in self._instances: raise ValueError("Plugin instance '%s' not found for '%s'." % (plugin_name, self.name)) plugin = self._instances[plugin_name] plugin.close() del self._instances[plugin_name] self.notify_instance_modified(plugin_name, True) def notify_instance_modified(self, plugin_name, removed=False): for observer in self._observer: observer.notify(plugin_name, removed) def _get_plugin_name(self, plugin_cls): """ generate new plugin name which is not used yet. starting at the plugin class NAME and appending numbers from 2 to n, like 'primary', 'primary2', 'primary3' """ cnt = 2 result = plugin_cls.NAME while result in self._instances: result = plugin_cls.NAME + str(cnt) cnt += 1 return result def get_trait_name_template(self, plugin_cls_name, plugin_name): return '__'.join( [self.PREFIX, self.name, plugin_cls_name, plugin_name, '%s']) def register_plugin(self, plugin_cls): self._plugins[plugin_cls.NAME] = plugin_cls def register_observer(self, observer): self._observer.append(observer) def unregister_observer(self, observer): self._observer.remove(observer) def add_referee_to_instance(self, plugin_name, referee): instance = self.get_plugin_instance(plugin_name) instance.add_referee(referee) def remove_referee_from_instance(self, plugin_name, referee): instance = self.get_plugin_instance(plugin_name) instance.remove_referee(referee) def handle_referee(self, plugin_name_new, plugin_name_old, referee): # remove old and add new referee to instance #print self.name, plugin_name_new, plugin_name_old, referee if plugin_name_old in self._instances: self.remove_referee_from_instance(plugin_name_old, referee) if plugin_name_new in self._instances: self.add_referee_to_instance(plugin_name_new, referee) def get_referees_for_instance(self, plugin_name): instance = self.get_plugin_instance(plugin_name) return instance.referees def get_plugin_cls_names(self): return self._plugins.keys() def get_plugin_labels(self): return [(name, cls.LABEL) for name, cls in self._plugins.iteritems()] def get_plugin_names(self): return sorted(self._instances.keys()) def get_plugin_cls(self, name): return self._plugins[name] def get_plugin_instance(self, name): return self._instances[name] def number_loaded_plugins(self): """Return the number of plugins that are invoked if run is executed.""" return len(self._instances) # FIXME **option is dangerous, what if one calls run(foo=bar) @stopwatch(level=logging.INFO) def run(self, *args, **options): results = OrderedDict() for instance in self._instances.itervalues(): inst_args = list(args) if not instance.REQUIRES is None: if not 'requirements' in options: raise ValueError(( "PluginManager(%s).run needs 'requirements' options, " "because Plugin instances '%s' defines requirements." % (self.name, instance.name))) requirements = options['requirements'] for idx in range(len(instance.REQUIRES)): value = instance.get_requirement_info(idx)[1] data = requirements[idx].get_requirement(value) inst_args.append(data) results[instance.name] = instance.run(*inst_args) return results
class TimeHolder(OrderedDict): NC_GROUP_RAW = 'raw' NC_GROUP_LABEL = 'label' NC_GROUP_FEATURE = 'feature' NC_ZLIB = True NC_SHUFFLE = True def __init__(self, P, channels, filename, filename_hdf5, meta_data, settings, create_nc=True, reuse_nc=True, hdf5_create=True, hdf5_include_raw_images=True, hdf5_include_label_images=True, hdf5_include_features=True): super(TimeHolder, self).__init__() self.P = P self._iCurrentT = None self.channels = channels self._meta_data = meta_data self._settings = settings self._create_nc = create_nc self._reuse_nc = reuse_nc self._nc4_filename = filename self._dataset = None self._hdf5_create = hdf5_create self._hdf5_include_raw_images = hdf5_include_raw_images self._hdf5_include_label_images = hdf5_include_label_images self._hdf5_include_features = hdf5_include_features self._logger = logging.getLogger(self.__class__.__name__) # frames get an index representation with the NC file, starting at 0 frames = sorted(list(meta_data.times)) self._frames_to_idx = dict([(f,i) for i, f in enumerate(frames)]) self._idx_to_frames = dict([(i,f) for i, f in enumerate(frames)]) channels = sorted(list(meta_data.channels)) region_names = REGION_NAMES_PRIMARY + REGION_NAMES_SECONDARY region_channels = ['primary']*len(REGION_NAMES_PRIMARY) + \ ['secondary']*len(REGION_NAMES_SECONDARY) region_names2 = [('Primary', 'primary')] #channel_names2 = [('Primary'] settings.set_section('ObjectDetection') for prefix in ['secondary', 'tertiary']: if settings.get('Processing', '%s_processchannel' % prefix): for name in REGION_NAMES_SECONDARY: if settings.get2('%s_regions_%s' % (prefix, name)): region_names2.append((prefix.capitalize(), name)) self._channels_to_idx = dict([(f,i) for i, f in enumerate(channels)]) self._idx_to_channels = dict([(i,f) for i, f in enumerate(channels)]) self._regions_to_idx = dict([(n,i) for i, n in enumerate(region_names)]) self._regions_to_idx2 = OrderedDict([(n,i) for i, n in enumerate(region_names2)]) if self._hdf5_create: f = h5py.File(filename_hdf5, 'w') self._hdf5_file = f def create_nc4(self): settings = self._settings if (self._create_nc and self._reuse_nc and self._dataset is None and os.path.isfile(self._nc4_filename)): dataset = netCDF4.Dataset(self._nc4_filename, 'a') # decide which parts need to be reprocessed based on changes # between the saved (from nc4) and the current settings # load settings from nc4 file #var = str(dataset.variables['settings'][:][0]) #settings2 = settings.copy() #settings2.from_string(var) # compare current and saved settings and decide which data is to # process again by setting the *_finished variables to zero # valid = {'primary' : [True, True], # 'secondary' : [True, True], # } # for name in ['primary', 'secondary']: # channel_id = settings2.get(SECTION_NAME_OBJECTDETECTION, # '%s_channelid' % name) # idx = dataset.variables['channels_idx'][:] == channel_id # if (not settings.compare(settings2, SECTION_NAME_OBJECTDETECTION, # '%s_image' % name) or # not settings.compare(settings2, SECTION_NAME_OBJECTDETECTION, # 'secondary_registration') or # not valid[name][0]): # dataset.variables['raw_images_finished'][:,idx] = 0 # valid['primary'] = [False, False] # valid['secondary'] = [False, False] # idx = dataset.variables['region_channels'][:] == name # if (not settings.compare(settings2, SECTION_NAME_OBJECTDETECTION, # '%s_segmentation' % name) or # not valid[name][1]): # dataset.variables['label_images_finished'][:,idx] = 0 # valid['primary'] = [False, False] # valid['secondary'] = [False, False] elif self._create_nc and self._dataset is None: meta = self._meta_data dim_t = meta.dim_t dim_c = meta.dim_c w = meta.real_image_width h = meta.real_image_height channels = sorted(list(meta.channels)) region_names = REGION_NAMES_PRIMARY + REGION_NAMES_SECONDARY region_channels = ['primary']*len(REGION_NAMES_PRIMARY) + \ ['secondary']*len(REGION_NAMES_SECONDARY) dataset = netCDF4.Dataset(self._nc4_filename, 'w', format='NETCDF4') dataset.createDimension('frames', dim_t) dataset.createDimension('channels', dim_c) dataset.createDimension('height', h) dataset.createDimension('width', w) dataset.createDimension('regions', len(region_names)) dataset.createDimension('one', 1) frames = sorted(list(meta.times)) var = dataset.createVariable('frames_idx', 'u4', 'frames') var.description = 'Mapping from indices to frames.' var[:] = frames var = dataset.createVariable('settings', str, 'one') var.description = 'Cecog settings used for the generation of this '\ 'netCDF file. Current cecog and this settings '\ 'are compared hierarchically leading to a '\ 'stepwise invalidation of preprocessed values.' raw_g = dataset.createGroup(self.NC_GROUP_RAW) raw_g.description = 'Converted raw images as processed by cecog '\ 'after 8bit conversion, registration, and '\ 'z-projection/selection.' label_g = dataset.createGroup(self.NC_GROUP_LABEL) label_g.description = 'Label images as a result of object '\ 'detection.' object_g = dataset.createGroup('object') object_g.description = 'General object values and mapping' feature_g = dataset.createGroup(self.NC_GROUP_FEATURE) feature_g.description = 'Feature values' for channel_id in meta.channels: var = raw_g.createVariable(channel_id, 'u1', ('frames', 'height', 'width'), zlib=self.NC_ZLIB, shuffle=self.NC_SHUFFLE, chunksizes=(1, h, w)) # FIXME: not working for dim_t == 1 (no timelapse data) var.valid = [0] * dim_t #print channel_id, dim_t, var.valid for channel_name in REGION_NAMES.keys(): channel_g = label_g.createGroup(channel_name) grp1 = object_g.createGroup(channel_name) grp2 = feature_g.createGroup(channel_name) for region_name in REGION_NAMES[channel_name]: var = channel_g.createVariable(region_name, 'i2', ('frames', 'height', 'width'), zlib=self.NC_ZLIB, shuffle=self.NC_SHUFFLE, chunksizes=(1, h, w)) var.valid = [0] * dim_t grp1.createGroup(region_name) grp2.createGroup(region_name) var = dataset.createVariable('channels_idx', str, 'channels') var[:] = numpy.asarray(channels, 'O') var = dataset.createVariable('region_names', str, 'regions') var[:] = numpy.asarray(region_names, 'O') var = dataset.createVariable('region_channels', str, 'regions') var[:] = numpy.asarray(region_channels, 'O') dataset.createVariable('raw_images', 'u1', ('frames', 'channels', 'height', 'width'), zlib='True', shuffle=False, chunksizes=(1, 1, h, w) ) finished = dataset.createVariable('raw_images_finished', 'i1', ('frames', 'channels')) finished[:] = 0 dataset.createVariable('label_images', 'i2', ('frames', 'regions', 'height', 'width'), zlib='True', shuffle=False, chunksizes=(1, 1, h, w) ) finished = dataset.createVariable('label_images_finished', 'i1', ('frames', 'regions')) finished[:] = 0 else: dataset = None if not dataset is None: # update the settings to the current version var = dataset.variables['settings'] var[:] = numpy.asarray(settings.to_string(), 'O') self._dataset = dataset @staticmethod def nc_valid_set(var, idx, value): helper = var.valid if len(helper.shape) == 0: helper = value else: helper[idx] = value var.valid = helper def close_all(self): if not self._dataset is None: self._dataset.close() self._dataset = None self._create_nc = False if self._hdf5_create: self._hdf5_file.close() self._hdf5_create = False def __del__(self): self.close_all() def initTimePoint(self, iT): self._iCurrentT = iT def getCurrentTimePoint(self): return self._iCurrentT def getCurrentChannels(self): return self[self._iCurrentT] def purge_features(self): for channels in self.itervalues(): for channel in channels.itervalues(): channel.purge(features={}) def apply_channel(self, oChannel): iT = self._iCurrentT if not iT in self: self[iT] = OrderedDict() self[iT][oChannel.NAME] = oChannel self[iT].sort(key = lambda x: self[iT][x]) def apply_segmentation(self, channel, primary_channel=None): self.create_nc4() valid = False desc = '[P %s, T %05d, C %s]' % (self.P, self._iCurrentT, channel.strChannelId) name = channel.NAME.lower() if self._create_nc or self._reuse_nc: grp = self._dataset.groups[self.NC_GROUP_LABEL] grp = grp.groups[name] frame_idx = self._frames_to_idx[self._iCurrentT] if self._reuse_nc: for region_name in channel.lstAreaSelection: var = grp.variables[region_name] if len(var.valid.shape) == 0: frame_valid = var.valid else: frame_valid = var.valid[frame_idx] if frame_valid: img_label = ccore.numpy_to_image(var[frame_idx], copy=True) img_xy = channel.meta_image.image container = ccore.ImageMaskContainer(img_xy, img_label, False, True, True) channel.dctContainers[region_name] = container valid = True else: valid = False break if not valid: channel.apply_segmentation(primary_channel) if self._create_nc: for region_name in channel.lstAreaSelection: var = grp.variables[region_name] container = channel.dctContainers[region_name] var[frame_idx] = \ container.img_labels.toArray(copy=False) self.nc_valid_set(var, frame_idx, 1) self._logger.debug('Label images %s written to nc4 file.' %\ desc) else: self._logger.debug('Label images %s loaded from nc4 file.' %\ desc) if self._hdf5_create and self._hdf5_include_label_images: meta = self._meta_data w = meta.real_image_width h = meta.real_image_height f = self._hdf5_file if 'labeled_images' in f: labeled_images = f['labeled_images'] else: nr_labels = len(self._regions_to_idx2) dt = h5py.special_dtype(vlen=str) names = f.create_dataset('label_names', (nr_labels, 2), dt) for tpl, idx in self._regions_to_idx2.iteritems(): names[idx] = tpl labeled_images = f.create_dataset('label_images', (nr_labels, meta.dim_t, meta.dim_z, w, h), 'int32', compression='szip', chunks=(1,1,meta.dim_z,w,h)) frame_idx = self._frames_to_idx[self._iCurrentT] for region_name in channel.lstAreaSelection: idx = self._regions_to_idx2[(channel.NAME, region_name)] container = channel.dctContainers[region_name] array = container.img_labels.toArray(copy=False) labeled_images[idx, frame_idx, 0] = numpy.require(array, 'int32') def prepare_raw_image(self, channel): self.create_nc4() desc = '[P %s, T %05d, C %s]' % (self.P, self._iCurrentT, channel.strChannelId) if self._create_nc or self._reuse_nc: grp = self._dataset.groups[self.NC_GROUP_RAW] var = grp.variables[channel.strChannelId] frame_idx = self._frames_to_idx[self._iCurrentT] if len(var.valid.shape) == 0: frame_valid = var.valid else: frame_valid = var.valid[frame_idx] if self._reuse_nc and frame_valid: coordinate = Coordinate(position=self.P, time=self._iCurrentT, channel=channel.strChannelId, zslice=1) meta_image = MetaImage(image_container=None, coordinate=coordinate) img = ccore.numpy_to_image(var[frame_idx], copy=True) meta_image.set_image(img) meta_image.set_raw_image(img) channel.meta_image = meta_image self._logger.debug('Raw image %s loaded from nc4 file.' % desc) else: channel.apply_zselection() channel.normalize_image() channel.apply_registration() if self._create_nc: img = channel.meta_image.image grp = self._dataset.groups[self.NC_GROUP_RAW] var = grp.variables[channel.strChannelId] var[frame_idx] = img.toArray(copy=False) self.nc_valid_set(var, frame_idx, 1) self._logger.debug('Raw image %s written to nc4 file.' % desc) if self._hdf5_create and self._hdf5_include_raw_images: meta = self._meta_data w = meta.real_image_width h = meta.real_image_height f = self._hdf5_file if 'images' in f: images = f['images'] else: images = f.create_dataset('pre_images', (meta.dim_c, meta.dim_t, meta.dim_z, w, h), 'uint8', compression='szip', chunks=(1,1,meta.dim_z,w,h)) dt = h5py.special_dtype(vlen=str) channels = f.create_dataset('channel_names', (meta.dim_c,), dt) for idx in range(meta.dim_c): channels[idx] = self._idx_to_channels[idx] frame_idx = self._frames_to_idx[self._iCurrentT] channel_idx = self._channels_to_idx[channel.strChannelId] img = channel.meta_image.image array = img.toArray(copy=False) print array.shape, (meta.dim_c, meta.dim_t, meta.dim_z, w, h), frame_idx, channel_idx images[channel_idx, frame_idx, 0] = array def apply_features(self, channel): self.create_nc4() valid = False desc = '[P %s, T %05d, C %s]' % (self.P, self._iCurrentT, channel.strChannelId) name = channel.NAME.lower() channel.apply_features() if self._hdf5_create and self._hdf5_include_features: meta = self._meta_data w = meta.real_image_width h = meta.real_image_height f = self._hdf5_file if 'features' in f: features = f['features'] else: features = f.create_group('features') if 'objects' in f: objects = f['objects'] else: objects = f.create_group('objects') # #nr_objects # # data_f = features.create_dataset(str(self._iCurrentT), (), 'float32', # compression='szip', chunks=()) # data_o = objects.create_dataset(str(self._iCurrentT), (), 'float32', # compression='szip', chunks=()) # # nr_labels = len(self._regions_to_idx2) # dt = h5py.special_dtype(vlen=str) # names = f.create_dataset('label_names', (nr_labels, 2), dt) # for tpl, idx in self._regions_to_idx2.iteritems(): # names[idx] = tpl # labeled_images = f.create_dataset('labeled_images', (nr_labels, meta.dim_t, meta.dim_z, w, h), # 'int32', compression='szip', chunks=(1,1,meta.dim_z,w,h)) # # frame_idx = self._frames_to_idx[self._iCurrentT] # for region_name in channel.lstAreaSelection: # idx = self._regions_to_idx2[(channel.NAME, region_name)] # container = channel.dctContainers[region_name] # array = container.img_labels.toArray(copy=False) # labeled_images[idx, frame_idx, 0] = numpy.require(array, 'int32') def extportObjectCounts(self, filename, P, meta_data, prim_info=None, sec_info=None, sep='\t'): f = file(filename, 'w') has_header = False for frame, channels in self.iteritems(): #channels.sort(key = lambda x: channels[x]) line1 = [] line2 = [] line3 = [] line4 = [] items = [] coordinate = Coordinate(position=P, time=frame) prefix = [frame, meta_data.get_timestamp_relative(coordinate)] prefix_names = ['frame', 'time'] for channel in channels.values(): if channel.NAME == 'Primary' and not prim_info is None: region_info = prim_info elif channel.NAME == 'Secondary' and not sec_info is None: region_info = sec_info else: region_info = None if not region_info is None: region_name, class_names = region_info if not has_header: keys = ['total'] + class_names line4 += keys line3 += ['total'] + ['class']*len(class_names) line1 += [channel.NAME.upper()] * len(keys) line2 += [region_name] * len(keys) if channel.has_region(region_name): region = channel.get_region(region_name) total = len(region) count = dict([(x, 0) for x in class_names]) # in case just total counts are needed if len(class_names) > 0: for obj in region.values(): count[obj.strClassName] += 1 items += [total] + [count[x] for x in class_names] else: items += [numpy.NAN] * (len(class_names) + 1) if not has_header: has_header = True prefix_str = [''] * len(prefix) f.write('%s\n' % sep.join(prefix_str + line1)) f.write('%s\n' % sep.join(prefix_str + line2)) f.write('%s\n' % sep.join(prefix_str + line3)) f.write('%s\n' % sep.join(prefix_names + line4)) f.write('%s\n' % sep.join(map(str, prefix + items))) f.close() def extportObjectDetails(self, filename, sep='\t', excel_style=False): f = file(filename, 'w') feature_lookup = OrderedDict() feature_lookup['mean'] = 'n2_avg' feature_lookup['sd'] = 'n2_stddev' feature_lookup['size'] = 'roisize' has_header = False line1 = [] line2 = [] line3 = [] for frame, channels in self.iteritems(): items = [] prim_region = channels.values()[0].get_region('primary') for obj_id in prim_region: prefix = [frame, obj_id] prefix_names = ['frame', 'objID'] items = [] for channel in channels.values(): for region_id in channel.region_names(): region = channel.get_region(region_id) if obj_id in region: #FIXME: feature_lookup2 = feature_lookup.copy() for k,v in feature_lookup2.items(): if not region.hasFeatureName(v): del feature_lookup2[k] if not has_header: keys = ['classLabel', 'className'] if channel.NAME == 'Primary': keys += ['centerX', 'centerY'] keys += feature_lookup2.keys() if excel_style: line1 += [channel.NAME.upper()] * len(keys) line2 += [region_id] * len(keys) line3 += keys else: line1 += ['%s_%s_%s' % (channel.NAME.upper(), region_id, key) for key in keys] obj = region[obj_id] #print feature_lookup2.keys(), feature_lookup2.values() #fn = region.getFeatureNames() #print zip(fn, obj.aFeatures) features = region.getFeaturesByNames(obj_id, feature_lookup2.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) if excel_style: line1 = prefix_str + line1 line2 = prefix_str + line2 line3 = prefix_names + line3 f.write('%s\n' % sep.join(line1)) f.write('%s\n' % sep.join(line2)) f.write('%s\n' % sep.join(line3)) else: line1 = prefix_names + line1 f.write('%s\n' % sep.join(line1)) f.write('%s\n' % sep.join(map(str, prefix + items))) f.close() def extportImageFileNames(self, output_path, position_str, imagecontainer, channel_mapping): channel_mapping_reversed = dict([(v,k) for k,v in channel_mapping.iteritems()]) filename = os.path.join(output_path, 'P%s__image_files.txt' % self.P) importer = imagecontainer._importer table = {} for c in channel_mapping: table[c] = [] for t in self.keys(): for c in channel_mapping.values(): for z in importer.dimension_lookup[position_str][t][c]: c_name = channel_mapping_reversed[c] table[c_name].append(os.path.join(importer.path, importer.dimension_lookup[position_str][t][c][z])) f = open(filename, 'w') f.write("\t".join(table.keys()) + "\n") for image_file_names in zip(*table.values()): f.write("\t".join(image_file_names) + "\n") f.close()
class PluginBay(QFrame): def __init__(self, parent, plugin_manager, settings): super(QFrame, self).__init__(parent) self.plugin_manager = plugin_manager self.plugin_manager.register_observer(self) self.settings = settings self._plugins = OrderedDict() self.setStyleSheet( "PluginItem { border: 1px solid black; background: white; }") layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) frame1 = QFrame(self) self._frame2 = QFrame(self) layout.addWidget(frame1) layout.addSpacing(10) layout.addWidget(self._frame2) label = QLabel('%s plugins' % plugin_manager.display_name, frame1) label.setStyleSheet("font-weight: bold;") btn = QPushButton('Add', frame1) btn.clicked.connect(self._on_add_plugin) self._cb = QComboBox(frame1) self._set_plugin_labels() layout = QHBoxLayout(frame1) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(label) layout.addWidget(self._cb, 1) layout.addWidget(btn) layout = QVBoxLayout(self._frame2) layout.setContentsMargins(0, 0, 0, 0) def init(self): self.reset() for plugin_name in self.plugin_manager.get_plugin_names(): self.add_plugin(plugin_name) def notify(self, plugin_name, removed): pass def _set_plugin_labels(self): self._cb.clear() for name, label in self.plugin_manager.get_plugin_labels(): self._cb.addItem(label, name) def reset(self): self._set_plugin_labels() for plugin_name in self._plugins.keys()[:]: self.remove_plugin(plugin_name) def add_plugin(self, plugin_name): plugin = self.plugin_manager.get_plugin_instance(plugin_name) item = PluginItem(self._frame2, plugin, self.settings) item.remove_item.connect( functools.partial(self._on_remove_plugin, plugin_name)) layout = self._frame2.layout() layout.insertWidget(0, item) self._plugins[plugin_name] = item def remove_plugin(self, plugin_name): layout = self._frame2.layout() item = self._plugins[plugin_name] item.close() layout.removeWidget(item) del self._plugins[plugin_name] def _on_add_plugin(self): name_cls = self._cb.itemData(self._cb.currentIndex()) plugin_name = self.plugin_manager.add_instance(name_cls, self.settings) self.add_plugin(plugin_name) def _on_remove_plugin(self, plugin_name): instance = self.plugin_manager.get_plugin_instance(plugin_name) result = False n = len(instance.referees) if n == 0: result = question(None, 'Removing the plugin "%s"' % plugin_name, "Are you sure to remove this plugin?") elif n > 0: detail = '\n'.join(['%s (%s)' % x[:2] for x in instance.referees]) result = question( None, 'Removing the plugin "%s"' % plugin_name, '%d other plugin%s require%s this plugin.\n\nAre you sure to remove this plugin?' % (n, 's' if n > 1 else '', 's' if n == 1 else ''), detail=detail, icon=QMessageBox.Warning) if result: self.remove_plugin(plugin_name) self.plugin_manager.remove_instance(plugin_name, self.settings)
def __init__(self): QMainWindow.__init__(self) qApp._main_window = self self._is_initialized = False self._debug = False self._imagecontainer = None self._meta_data = None self._browser = None self.setWindowTitle(self.TITLE + '[*]') central_widget = QFrame(self) self.setCentralWidget(central_widget) action_about = self.create_action('&About', slot=self._on_about) action_quit = self.create_action('&Quit', slot=self._on_quit) action_pref = self.create_action('&Preferences', slot=self._on_preferences) #action_new = self.create_action('&New...', shortcut=QKeySequence.New, # icon='filenew') action_open = self.create_action('&Open Settings...', shortcut=QKeySequence.Open, slot=self._on_file_open ) action_save = self.create_action('&Save Settings', shortcut=QKeySequence.Save, slot=self._on_file_save ) self.action_save = action_save action_save_as = self.create_action('&Save Settings As...', shortcut=QKeySequence.SaveAs, slot=self._on_file_save_as ) menu_file = self.menuBar().addMenu('&File') self.add_actions(menu_file, (action_about, action_pref, None, action_open, None, action_save, action_save_as, None, action_quit)) action_open = self.create_action('&Open Browser...', shortcut=QKeySequence('CTRL+B'), slot=self._on_browser_open ) menu_browser = self.menuBar().addMenu('&Browser') self.add_actions(menu_browser, (action_open, #None, action_save, action_save_as, #None, action_quit )) action_log = self.create_action('&Show Log Window...', shortcut=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=QKeySequence.HelpContents, slot=self._on_help_startup ) menu_help = self.menuBar().addMenu('&Help') self.add_actions(menu_help, (action_help_startup,)) qApp._statusbar = QStatusBar(self) self.setStatusBar(qApp._statusbar) self._selection = QListWidget(central_widget) self._selection.setViewMode(QListView.IconMode) #self._selection.setUniformItemSizes(True) self._selection.setIconSize(QSize(35, 35)) self._selection.setGridSize(QSize(140, 60)) #self._selection.setWrapping(False) self._selection.setMovement(QListView.Static) #self._selection.setFlow(QListView.TopToBottom) #self._selection.setSpacing(12) self._selection.setMaximumWidth(self._selection.gridSize().width() + 5) self._selection.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._selection.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)) self._pages = QStackedWidget(central_widget) 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), OutputFrame(self._settings, self._pages), ProcessingFrame(self._settings, self._pages), ] if ANALYZER_CONFIG.get('Analyzer', 'cluster_support'): self._tabs.append(ClusterFrame(self._settings, self._pages)) 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 = QLabel(central_widget) w_logo.setPixmap(QPixmap(':cecog_logo_w145')) layout = QGridLayout(central_widget) layout.addWidget(self._selection, 0, 0) layout.addWidget(w_logo, 1, 0, Qt.AlignBottom | Qt.AlignHCenter) layout.addWidget(self._pages, 0, 1, 2, 1) qApp._log_handler = GuiLogHandler(self) qApp._log_window = LogWindow(qApp._log_handler) qApp._log_window.setGeometry(50, 50, 600, 300) logger = logging.getLogger() qApp._log_handler.setLevel(logging.NOTSET) formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') qApp._log_handler.setFormatter(formatter) #logger.addHandler(self._handler) logger.setLevel(logging.NOTSET) qApp._image_dialog = None qApp._graphics = None self.setGeometry(0, 0, 1100, 750) self.setMinimumSize(QSize(700, 600)) self.show() self.center() self.raise_() self._is_initialized = True
class CellAnalyzer(PropertyManager): PROPERTIES = \ dict(P = StringProperty(True, doc=''), bCreateImages = BooleanProperty(True, doc="Create output images"), iBinningFactor = IntProperty(None, is_mandatory=True, doc=''), detect_objects = BooleanProperty(True), time_holder = InstanceProperty(None, TimeHolder, doc="Instance of TimeHolder.", is_mandatory=True), ) __attributes__ = [Attribute('_channel_registry'), Attribute('_iT'), Attribute('_oLogger'), ] def __init__(self, **dctOptions): super(CellAnalyzer, self).__init__(**dctOptions) self._oLogger = logging.getLogger(self.__class__.__name__) def initTimepoint(self, iT): self._channel_registry = OrderedDict() self._iT = iT self.time_holder.initTimePoint(iT) def register_channel(self, channel): self._channel_registry[channel.NAME] = channel def get_channel_names(self): return self._channel_registry.keys() def get_channel(self, name): return self._channel_registry[name] def process(self, apply=True, extract_features=True): # sort by Channel `RANK` channels = sorted(self._channel_registry.values()) primary_channel = None for channel in channels: self.time_holder.prepare_raw_image(channel) if self.detect_objects: self.time_holder.apply_segmentation(channel, primary_channel) if extract_features: self.time_holder.apply_features(channel) if primary_channel is None: assert channel.RANK == 1 primary_channel = channel if apply: for channel in channels: self.time_holder.apply_channel(channel) def purge(self, features=None): for oChannel in self._channel_registry.values(): if not features is None and oChannel.strChannelId in features: channelFeatures = features[oChannel.strChannelId] else: channelFeatures = None oChannel.purge(features=channelFeatures) def exportLabelImages(self, pathOut, compression='LZW'): for name, channel in self._channel_registry.iteritems(): channel_id = channel.strChannelId for strRegion, oContainer in channel.dctContainers.iteritems(): strPathOutImage = os.path.join(pathOut, channel_id, strRegion) safe_mkdirs(strPathOutImage) oContainer.exportLabelImage(os.path.join(strPathOutImage, 'P%s_T%05d.tif' % (self.P, self._iT)), compression) def getImageSize(self, name): oChannel = self._channel_registry[name] w = oChannel.meta_image.width h = oChannel.meta_image.height return (w,h) def render(self, strPathOut, dctRenderInfo=None, strFileSuffix='.jpg', strCompression='98', writeToDisc=True, images=None): lstImages = [] if not images is None: lstImages += images if dctRenderInfo is None: for name, oChannel in self._channel_registry.iteritems(): for strRegion, oContainer in oChannel.dctContainers.iteritems(): strHexColor, fAlpha = oChannel.dctAreaRendering[strRegion] imgRaw = oChannel.meta_image.image imgCon = ccore.Image(imgRaw.width, imgRaw.height) ccore.drawContour(oContainer.getBinary(), imgCon, 255, False) lstImages.append((imgRaw, strHexColor, 1.0)) lstImages.append((imgCon, strHexColor, fAlpha)) else: for channel_name, dctChannelInfo in dctRenderInfo.iteritems(): if channel_name in self._channel_registry: oChannel = self._channel_registry[channel_name] if 'raw' in dctChannelInfo: strHexColor, fAlpha = dctChannelInfo['raw'] lstImages.append((oChannel.meta_image.image, strHexColor, fAlpha)) if 'contours' in dctChannelInfo: # transform the old dict-style to the new tuple-style, # which allows multiple definitions for one region if type(dctChannelInfo['contours']) == types.DictType: lstContourInfos = [(k,)+v for k,v in dctChannelInfo['contours'].iteritems()] else: lstContourInfos = dctChannelInfo['contours'] for tplData in lstContourInfos: strRegion, strNameOrColor, fAlpha, bShowLabels = tplData[:4] # draw contours only if region is present if oChannel.has_region(strRegion): if len(tplData) > 4: bThickContours = tplData[4] else: bThickContours = False if strNameOrColor == 'class_label': oContainer = oChannel.dctContainers[strRegion] oRegion = oChannel.get_region(strRegion) dctLabels = {} dctColors = {} for iObjId, oObj in oRegion.iteritems(): iLabel = oObj.iLabel if not iLabel is None: if not iLabel in dctLabels: dctLabels[iLabel] = [] dctLabels[iLabel].append(iObjId) dctColors[iLabel] = oObj.strHexColor #print dctLabels imgRaw = oChannel.meta_image.image imgCon2 = ccore.Image(imgRaw.width, imgRaw.height) for iLabel, lstObjIds in dctLabels.iteritems(): imgCon = ccore.Image(imgRaw.width, imgRaw.height) oContainer.drawContoursByIds(lstObjIds, 255, imgCon, bThickContours, False) lstImages.append((imgCon, dctColors[iLabel], fAlpha)) if type(bShowLabels) == types.BooleanType and bShowLabels: # oContainer.drawTextsByIds(lstObjIds, lstObjIds, imgCon2) #else: oContainer.drawTextsByIds(lstObjIds, [str(iLabel)]*len(lstObjIds), imgCon2) lstImages.append((imgCon2, '#FFFFFF', 1.0)) else: oContainer = oChannel.dctContainers[strRegion] oRegion = oChannel.get_region(strRegion) lstObjIds = oRegion.keys() imgRaw = oChannel.meta_image.image imgCon = ccore.Image(imgRaw.width, imgRaw.height) if not strNameOrColor is None: oContainer.drawContoursByIds(lstObjIds, 255, imgCon, bThickContours, False) else: strNameOrColor = '#FFFFFF' lstImages.append((imgCon, strNameOrColor, fAlpha)) if bShowLabels: imgCon2 = ccore.Image(imgRaw.width, imgRaw.height) oContainer.drawLabelsByIds(lstObjIds, imgCon2) lstImages.append((imgCon2, '#FFFFFF', 1.0)) if len(lstImages) > 0: imgRgb = ccore.makeRGBImage([x[0].getView() for x in lstImages], [ccore.RGBValue(*hexToRgb(x[1])) for x in lstImages], [x[2] for x in lstImages]) if writeToDisc: strFilePath = os.path.join(strPathOut, "P%s_T%05d%s" % (self.P, self._iT, strFileSuffix)) safe_mkdirs(strPathOut) ccore.writeImage(imgRgb, strFilePath, strCompression) self._oLogger.debug("* rendered image written '%s'" % strFilePath) else: strFilePath = '' return imgRgb, strFilePath def collectObjects(self, plate_id, P, lstReader, oLearner, byTime=True): #channel_name = oLearner.strChannelId strRegionId = oLearner.strRegionId img_rgb = None self._oLogger.debug('* collecting samples...') # bSuccess = True # channels = sorted(self._channel_registry.values()) # primary_cChannel = None # for channel2 in lstChannels: # # self.time_holder.prepare_raw_image(channel) # self.time_holder.apply_segmentation(oChannel2, oPrimaryChannel) # # if oPrimaryChannel is None: # assert oChannel2.RANK == 1 # oPrimaryChannel = oChannel2 self.process(apply = False, extract_features = False) # self._channel_registry oChannel = self._channel_registry[oLearner.channel_name] oContainer = oChannel.get_container(strRegionId) objects = oContainer.getObjects() object_lookup = {} for oReader in lstReader: lstCoordinates = None if (byTime and P == oReader.getPosition() and self._iT in oReader): lstCoordinates = oReader[self._iT] elif (not byTime and P in oReader): lstCoordinates = oReader[P] #print "moo", P, oReader.getPosition(), byTime, self._iT in oReader #print lstCoordinates, byTime, self.P, oReader.keys() if not lstCoordinates is None: #print self.iP, self._iT, lstCoordinates for dctData in lstCoordinates: label = dctData['iClassLabel'] if (label in oLearner.dctClassNames and dctData['iPosX'] >= 0 and dctData['iPosX'] < oContainer.width and dctData['iPosY'] >= 0 and dctData['iPosY'] < oContainer.height): center1 = ccore.Diff2D(dctData['iPosX'], dctData['iPosY']) # test for obj_id "under" annotated pixel first obj_id = oContainer.img_labels[center1] # if not background: valid obj_id found if obj_id > 0: dict_append_list(object_lookup, label, obj_id) # otherwise try to find nearest object in a search # radius of 30 pixel (compatibility with CellCounter) else: dists = [] for obj_id, obj in objects.iteritems(): diff = obj.oCenterAbs - center1 dist_sq = diff.squaredMagnitude() # limit to 30 pixel radius if dist_sq < 900: dists.append((obj_id, dist_sq)) if len(dists) > 0: dists.sort(lambda a,b: cmp(a[1], b[1])) obj_id = dists[0][0] dict_append_list(object_lookup, label, obj_id) object_ids = set(flatten(object_lookup.values())) objects_del = set(objects.keys()) - object_ids for obj_id in objects_del: oContainer.delObject(obj_id) self.time_holder.apply_features(oChannel) region = oChannel.get_region(strRegionId) learner_objects = [] for label, object_ids in object_lookup.iteritems(): class_name = oLearner.dctClassNames[label] hex_color = oLearner.dctHexColors[class_name] rgb_value = ccore.RGBValue(*hexToRgb(hex_color)) for obj_id in object_ids: obj = region[obj_id] obj.iLabel = label obj.strClassName = class_name obj.strHexColor = hex_color if (obj.oRoi.upperLeft[0] >= 0 and obj.oRoi.upperLeft[1] >= 0 and obj.oRoi.lowerRight[0] < oContainer.width and obj.oRoi.lowerRight[1] < oContainer.height): iCenterX, iCenterY = obj.oCenterAbs strPathOutLabel = os.path.join(oLearner.dctEnvPaths['samples'], oLearner.dctClassNames[label]) safe_mkdirs(strPathOutLabel) strFilenameBase = 'PL%s___P%s___T%05d___X%04d___Y%04d' % (plate_id, self.P, self._iT, iCenterX, iCenterY) obj.sample_id = strFilenameBase learner_objects.append(obj) strFilenameImg = os.path.join(strPathOutLabel, '%s___img.png' % strFilenameBase) strFilenameMsk = os.path.join(strPathOutLabel, '%s___msk.png' % strFilenameBase) # FIXME: export Objects is segfaulting for objects # where its bounding box is touching the border # i.e. one corner point equals zero! oContainer.exportObject(obj_id, strFilenameImg, strFilenameMsk) oContainer.markObjects([obj_id], rgb_value, False, True) #print obj_id, obj.oCenterAbs, iCenterX, iCenterY print '*** CSdebug: drawFilledCircle', iCenterX, iCenterY ccore.drawFilledCircle(ccore.Diff2D(iCenterX, iCenterY), 3, oContainer.img_rgb, rgb_value) if len(learner_objects) > 0: oLearner.applyObjects(learner_objects) # we don't want to apply None for feature names oLearner.setFeatureNames(oChannel.lstFeatureNames) strPathOut = os.path.join(oLearner.dctEnvPaths['controls']) safe_mkdirs(strPathOut) oContainer.exportRGB(os.path.join(strPathOut, "P%s_T%05d_C%s_R%s.jpg" %\ (self.P, self._iT, oLearner.strChannelId, oLearner.strRegionId)), '90') img_rgb = oContainer.img_rgb return img_rgb def classifyObjects(self, oPredictor): channel_name = oPredictor.strChannelId strRegionId = oPredictor.strRegionId oChannel = self._channel_registry[channel_name] oRegion = oChannel.get_region(strRegionId) for iObjId, oObj in oRegion.iteritems(): iLabel, dctProb = oPredictor.predict(oObj.aFeatures.copy(), oRegion.getFeatureNames()) oObj.iLabel = iLabel oObj.dctProb = dctProb oObj.strClassName = oPredictor.dctClassNames[iLabel] oObj.strHexColor = oPredictor.dctHexColors[oObj.strClassName]
class Classifier(object): def __init__(self, name=None, path=None): #super(Classifier, self).__init__() self.name = name self.path = path self.dctClassInfos = OrderedDict() self.dctFeatureInfos = OrderedDict() self.isInitialized = False #self._loadInfos() def _loadInfos(self): print "LOAD" if not self.isInitialized: self._oLearner = BaseLearner(strEnvPath=self.path) try: self._oLearner.importFromArff() try: self._oLearner.importSampleNames() except IOError: has_samples = False else: has_samples = True #print has_samples except IOError: pass else: print "import %s" % self.name for iLabel in self._oLearner.lstClassLabels: strName = self._oLearner.dctClassNames[iLabel] strHexColor = self._oLearner.dctHexColors[strName] if strName in self._oLearner.dctFeatureData: oClass = Class(strName, iLabel, len(self._oLearner.dctFeatureData[strName]), hexToFlexColor(strHexColor)) oClass.oClassifier = self dctFeatures = {} for iIdx, strFeatureName in enumerate(self._oLearner.lstFeatureNames): dctFeatures[strFeatureName] = list(self._oLearner.dctFeatureData[strName][:,iIdx]) oClass.features = dctFeatures if has_samples: oClass.sample_names = [Sample(os.path.join(self._oLearner.dctEnvPaths['samples'], strName, filename)) for filename in self._oLearner.dctSampleNames[strName]] #print strName,self._oLearner.dctSampleNames[strName] self.dctClassInfos[strName] = oClass self.isInitialized = True for strFeatureName in self._oLearner.lstFeatureNames: self.dctFeatureInfos[strFeatureName] = Feature(strFeatureName) @property def classes(self): self._loadInfos() return self.dctClassInfos.values() @property def classInfos(self): self._loadInfos() logging.debug("classes: %s" % len(self.dctClassInfos.values())) return self.dctClassInfos.values() @property def featureInfos(self): self._loadInfos() logging.debug("features: %s" % len(self.dctFeatureInfos.values())) return self.dctFeatureInfos.values() def getSamples(self, className): self._loadInfos() strPathSamples = os.path.join(self._oLearner.dctEnvPaths['samples'], className) lstResults = [] if os.path.isdir(strPathSamples): #print len(self._oLearner.lstFeatureNames), len() dctImagePairs = OrderedDict() for strName, oMatch in collect_files_by_regex(strPathSamples, '(?P<prefix>.+?)__(?P<type>(img)|(msk)).+?', ['.png', '.jpg']): strPrefix = oMatch.group('prefix') strType = oMatch.group('type') if not strPrefix in dctImagePairs: dctImagePairs[strPrefix] = {} dctImagePairs[strPrefix][strType] = strName iIdx = 0 for dctPair in dctImagePairs.values(): #oContainer = ccore.SingleObjectContainer(dctPair['img'], dctPair['msk']) #strCoords = ",".join(map(str,flatten(oContainer.getCrackCoordinates(1)))) #print dctPair['img'], dctPair['msk'] #dctFeatures = {} #for iF, strFeatureName in enumerate(self._oLearner.lstFeatureNames): # dctFeatures[strFeatureName] = self._oLearner.dctFeatureData[className][iIdx][iF] oSample = Sample(dctPair['img']) lstResults.append(oSample) iIdx += 1 #break return lstResults def getFeatureData(self, featureNames): self._loadInfos() lstFeatureData = [] if len(featureNames) == 1: strFeatureName = featureNames[0] for strClassName, oClass in self.dctClassInfos.iteritems(): aY, aX = numpy.histogram(oClass.features[strFeatureName], normed=True) lstData = [dict(x=fX, y=fY) for fX,fY in zip(aX, aY)] lstFeatureData.append(lstData) elif len(featureNames) == 2: for strClassName, oClass in self.dctClassInfos.iteritems(): iSize = len(oClass.features.values()[0]) lstData = [dict([(strFeatureName, oClass.features[strFeatureName][iIdx]) for strFeatureName in featureNames]) for iIdx in range(iSize)] lstFeatureData.append(lstData) #print lstFeatureData return lstFeatureData
def initTimepoint(self, iT): self._channel_registry = OrderedDict() self._iT = iT self.time_holder.initTimePoint(iT)
class TabControl(QFrame): """General tab control: list of buttons at the top and stacked widget below""" current_changed = pyqtSignal(int) def __init__(self, parent, hide_one=True): QFrame.__init__(self, parent) self.setStyleSheet(TAB_STYLE) self._hide_one = hide_one self._tabs = OrderedDict() layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) self._btn_frame = QFrame(self) self._btn_grp = QButtonGroup(self._btn_frame) self._btn_grp.setExclusive(True) self._btn_layout = QHBoxLayout(self._btn_frame) self._btn_layout.insertStretch(0, 1) self._btn_layout.insertStretch(1, 1) self._stacked_frame = QStackedWidget(self) self._stacked_frame.setObjectName('stacked') layout.addWidget(self._btn_frame) layout.addWidget(self._stacked_frame) self._btn_frame.hide() self._current_name = None def add_tab(self, name, frame): scroll_area = QScrollArea(self) scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) scroll_area.setWidgetResizable(True) scroll_area.setFrameShape(QFrame.NoFrame) scroll_area.setWidget(frame) btn = QPushButton(name, self._btn_frame) btn.setObjectName('tab') btn.setFlat(True) btn.setCheckable(True) btn.toggled.connect(functools.partial(self._on_btn_toggled, name)) self._btn_grp.addButton(btn) self._tabs[name] = (scroll_area, frame, btn) self._stacked_frame.addWidget(scroll_area) self._btn_layout.insertWidget(len(self._tabs), btn) if not self._hide_one or len(self._tabs) > 1: self._btn_frame.show() self._current_name = name def remove_tab(self, name): scroll_area = self._tabs[name][0] btn = self._tabs[name][1] self._btn_layout.removeWidget(btn) self._stacked_frame.removeWidget(scroll_area) if (self._hide_one and len(self._tabs) <= 1) or (not self._hide_one and len(self._tabs) == 0): self._btn_frame.hide() def set_active(self, name, toggle=True): scroll_area = self._tabs[name][0] if toggle: btn = self._tabs[name][2] btn.setChecked(True) self._stacked_frame.setCurrentWidget(scroll_area) self._current_name = name self.current_changed.emit(self._tabs.index(name)) def set_active_index(self, index): name = self._tabs.keys()[index] self.set_active(name) def _on_btn_toggled(self, name): self.set_active(name, toggle=False) def enable_non_active(self, state=True): for name in self._tabs: frame, btn = self._tabs[name][1:] if frame != self._stacked_frame.currentWidget(): btn.setEnabled(state) def get_frame(self, name): return self._tabs[name][1] @property def current_name(self): return self._current_name @property def current_index(self): return self._tabs.index(self._current_name)
def __init__(self): self._registry = OrderedDict()
class BaseLearner(LoggerMixin, OptionManager): ANNOTATIONS = 'annotations' OPTIONS = {"strEnvPath" : Option(".", callback="_onEnvPath"), "lstClassDefinitions" : Option([], callback="_onDefineClasses"), "strArffFileName" : Option("features.arff"), "strSparseFileName" : Option("features.sparse"), "strDefinitionFileName" : Option("class_definition.txt"), "filename_pickle" : Option("learner.pkl"), } __attributes__ = ['dctFeatureData', 'dctSampleData', 'dctClassNames', 'dctClassLabels', 'lstFeatureNames', 'dctHexColors', 'dctEnvPaths', 'dctImageObjects'] def __init__(self, **options): self.dctFeatureData = OrderedDict() self.dctClassNames = {} self.dctClassLabels = {} self.lstFeatureNames = None self.dctHexColors = {} self.dctSampleNames = {} self.dctEnvPaths = {} self.hasZeroInsert = False self.dctImageObjects = OrderedDict() super(BaseLearner, self).__init__(**options) def __getstate__(self): dctState = get_attribute_values(self) return dctState def __setstate__(self, state): set_attribute_values(self, state) def clear(self): self.dctFeatureData.clear() self.dctClassNames.clear() self.dctClassLabels.clear() self.lstFeatureNames = None self.dctHexColors.clear() self.dctSampleNames.clear() self.dctImageObjects.clear() def mergeClasses(self, info, mapping): newl = copy.deepcopy(self) newl.dctClassNames = {} newl.dctClassLabels = {} newl.dctHexColors = {} for label, name, color in info: newl.dctClassNames[label] = name newl.dctClassLabels[name] = label newl.dctHexColors[name] = color data = OrderedDict() for new_label, label_list in mapping.iteritems(): new_name = newl.dctClassNames[new_label] if not new_name in data: data[new_name] = [] for old_label in label_list: old_name = self.dctClassNames[old_label] data[new_name].extend(self.dctFeatureData[old_name]) for name in data: data[name] = numpy.asarray(data[name]) newl.dctFeatureData = data return newl @property def lstClassNames(self): return [self.dctClassNames[x] for x in self.lstClassLabels] @property def lstClassLabels(self): return sorted(self.dctClassNames.keys()) @property def iClassNumber(self): return len(self.dctClassNames) @property def lstHexColors(self): return [self.dctHexColors[x] for x in self.lstClassNames] @property def names2samples(self): return dict([(n, len(self.dctFeatureData.get(n, []))) for n in self.lstClassNames]) @property def l2nl(self): ''' convert a label into a new label (new labels are continuous from 0..number of classes ''' return dict([(l,i) for i,l in enumerate(self.lstClassLabels)]) @property def nl2l(self): ''' convert a new label into the original label ''' return dict([(i,l) for i,l in enumerate(self.lstClassLabels)]) #def getFeaturesByName(self, featureName): def initEnv(self): env_path = self.getOption('strEnvPath') if not os.path.isdir(env_path): raise IOError("Classifier environment path '%s' does not exist." % env_path) for strName, strPath in self.dctEnvPaths.iteritems(): safe_mkdirs(strPath) def _onDefineClasses(self, lstClassDefinitions): for dctClassDescription in lstClassDefinitions: strClassName = dctClassDescription['name'] iClassLabel = dctClassDescription['label'] tplColor = dctClassDescription['color'] # FIXME: folders not supported yet!!! if ('folders' not in dctClassDescription or dctClassDescription['folders'] is None or len(dctClassDescription['folders']) == 0): lstFolders = [strClassName] else: lstFolders = dctClassDescription['folders'] self.dctClassNames[iClassLabel] = strClassName self.dctClassLabels[strClassName] = iClassLabel self.dctHexColors[strClassName] = rgbToHex(*tplColor) def _onEnvPath(self, strEnvPath): self.dctEnvPaths = {'samples' : os.path.join(strEnvPath, "samples"), self.ANNOTATIONS : os.path.join(strEnvPath, self.ANNOTATIONS), 'data': os.path.join(strEnvPath, "data"), 'controls': os.path.join(strEnvPath, "controls"), } def getPath(self, strName): path = self.dctEnvPaths[strName] if not os.path.exists(path): os.mkdir(path) return path def get_env_path(self): return self.getOption('strEnvPath') def set_env_path(self, path): self.setOption('strEnvPath', path) self._onEnvPath(path) def loadDefinition(self, path=None, filename=None): if filename is None: filename = self.getOption('strDefinitionFileName') if path is None: path = self.getOption('strEnvPath') f = open(os.path.join(path, filename), "rb") reader = csv.reader(f, delimiter='\t', quoting=csv.QUOTE_NONE) self.dctClassNames.clear() self.dctClassLabels.clear() self.dctHexColors.clear() for row in reader: label = int(row[0]) name = row[1] color = row[2] self.dctClassNames[label] = name self.dctClassLabels[name] = label self.dctHexColors[name] = color f.close() def saveDefinition(self, path=None, filename=None): if filename is None: filename = self.getOption('strDefinitionFileName') if path is None: path = self.getOption('strEnvPath') f = open(os.path.join(path, filename), "wb") writer = csv.writer(f, delimiter='\t', quoting=csv.QUOTE_NONE) for class_name in self.lstClassNames: class_label = self.dctClassLabels[class_name] color = self.dctHexColors[class_name] writer.writerow([class_label, class_name, color]) f.close() def exportRanges(self, strFilePath=None, strFileName=None): if strFileName is None: strFileName = os.path.splitext(self.getOption('strArffFileName'))[0] strFileName += '.range' if strFilePath is None: strFilePath = self.dctEnvPaths['data'] all_features = numpy.asarray(flatten(self.dctFeatureData.values())) features_min = numpy.min(all_features, 0) features_max = numpy.max(all_features, 0) f = file(os.path.join(strFilePath, strFileName), 'w') f.write('x\n') f.write('-1 1\n') for idx, (m1, m2) in enumerate(zip(features_min, features_max)): f.write('%d %.10e %.10e\n' % (idx+1, m1, m2)) f.close() def importFromArff(self, strFilePath=None, strFileName=None): if strFileName is None: strFileName = self.getOption('strArffFileName') if strFilePath is None: strFilePath = self.dctEnvPaths['data'] oReader = ArffReader(os.path.join(strFilePath, strFileName)) self.dctFeatureData = oReader.dctFeatureData self.dctClassNames = oReader.dctClassNames self.dctClassLabels = oReader.dctClassLabels self.lstFeatureNames = oReader.lstFeatureNames self.dctHexColors = oReader.dctHexColors self.hasZeroInsert = oReader.hasZeroInsert #print self.dctClassLabels #print self.dctClassNames #print self.dctFeatureData.keys() def check(self): filename = os.path.splitext(self.getOption('strArffFileName'))[0] result = {'path_env' : self.getOption('strEnvPath'), 'path_data' : self.dctEnvPaths['data'], 'path_samples' : self.dctEnvPaths['samples'], 'path_annotations' : self.dctEnvPaths['annotations'], 'model' : os.path.join(self.dctEnvPaths['data'], '%s.model' % filename), 'range' : os.path.join(self.dctEnvPaths['data'], '%s.range' % filename), 'conf' : os.path.join(self.dctEnvPaths['data'], '%s.confusion.txt' % filename), 'arff' : os.path.join(self.dctEnvPaths['data'], self.getOption('strArffFileName')), 'definition' : os.path.join(self.getOption('strEnvPath'), self.getOption('strDefinitionFileName')), } result.update({'has_path_data' : os.path.isdir(self.dctEnvPaths['data']), 'has_path_samples' : os.path.isdir(self.dctEnvPaths['samples']), 'has_path_annotations' : os.path.isdir(self.dctEnvPaths['annotations']), 'has_model' : os.path.isfile(os.path.join(self.dctEnvPaths['data'], '%s.model' % filename)), 'has_range' : os.path.isfile(os.path.join(self.dctEnvPaths['data'], '%s.range' % filename)), 'has_conf' : os.path.isfile(os.path.join(self.dctEnvPaths['data'], '%s.confusion.txt' % filename)), 'has_arff' : os.path.isfile(os.path.join(self.dctEnvPaths['data'], self.getOption('strArffFileName'))), 'has_definition' : os.path.isfile(os.path.join(self.getOption('strEnvPath'), self.getOption('strDefinitionFileName'))), } ) return result def exportToArff(self, strFilePath=None, strFileName=None): if strFileName is None: strFileName = self.getOption('strArffFileName') if strFilePath is None: strFilePath = self.dctEnvPaths['data'] #print self.hasZeroInsert oWriter = ArffWriter(os.path.join(strFilePath, strFileName), self.lstFeatureNames, self.dctClassLabels, dctHexColors=self.dctHexColors, hasZeroInsert=self.hasZeroInsert) oWriter.writeAllFeatureData(self.dctFeatureData) oWriter.close() def exportToSparse(self, strFilePath=None, strFileName=None): if strFileName is None: strFileName = self.getOption('strSparseFileName') if strFilePath is None: strFilePath = self.dctEnvPaths['data'] oWriter = SparseWriter(os.path.join(strFilePath, strFileName), self.lstFeatureNames, self.dctClassLabels) oWriter.writeAllFeatureData(self.dctFeatureData) oWriter.close() def importSampleNames(self, strFilePath=None, strFileName=None): if strFileName is None: strFileName = os.path.splitext(self.getOption('strArffFileName'))[0] strFileName = '%s.samples.txt' % strFileName if strFilePath is None: strFilePath = self.dctEnvPaths['data'] f = file(os.path.join(strFilePath, strFileName), 'r') self.dctSampleNames = {} for line in f: class_name, file_name = line.strip().split('\t') if class_name in self.dctClassLabels: if not class_name in self.dctSampleNames: self.dctSampleNames[class_name] = [] self.dctSampleNames[class_name].append(file_name) f.close() def exportSampleNames(self, strFilePath=None, strFileName=None): if strFileName is None: strFileName = os.path.splitext(self.getOption('strArffFileName'))[0] strFileName = '%s.samples.txt' % strFileName if strFilePath is None: strFilePath = self.dctEnvPaths['data'] f = file(os.path.join(strFilePath, strFileName), 'w') for class_name, samples in self.dctSampleNames.iteritems(): for sample_name in samples: f.write('%s\t%s\n' % (class_name, sample_name)) f.close() def export(self): self.exportToArff() self.exportToSparse() self.exportSampleNames()
def extportObjectDetails(self, filename, sep='\t', excel_style=False): f = file(filename, 'w') feature_lookup = OrderedDict() feature_lookup['mean'] = 'n2_avg' feature_lookup['sd'] = 'n2_stddev' feature_lookup['size'] = 'roisize' has_header = False line1 = [] line2 = [] line3 = [] for frame, channels in self.iteritems(): items = [] prim_region = channels.values()[0].get_region('primary') for obj_id in prim_region: prefix = [frame, obj_id] prefix_names = ['frame', 'objID'] items = [] for channel in channels.values(): for region_id in channel.region_names(): region = channel.get_region(region_id) if obj_id in region: #FIXME: feature_lookup2 = feature_lookup.copy() for k,v in feature_lookup2.items(): if not region.hasFeatureName(v): del feature_lookup2[k] if not has_header: keys = ['classLabel', 'className'] if channel.NAME == 'Primary': keys += ['centerX', 'centerY'] keys += feature_lookup2.keys() if excel_style: line1 += [channel.NAME.upper()] * len(keys) line2 += [region_id] * len(keys) line3 += keys else: line1 += ['%s_%s_%s' % (channel.NAME.upper(), region_id, key) for key in keys] obj = region[obj_id] #print feature_lookup2.keys(), feature_lookup2.values() #fn = region.getFeatureNames() #print zip(fn, obj.aFeatures) features = region.getFeaturesByNames(obj_id, feature_lookup2.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) if excel_style: line1 = prefix_str + line1 line2 = prefix_str + line2 line3 = prefix_names + line3 f.write('%s\n' % sep.join(line1)) f.write('%s\n' % sep.join(line2)) f.write('%s\n' % sep.join(line3)) else: line1 = prefix_names + line1 f.write('%s\n' % sep.join(line1)) f.write('%s\n' % sep.join(map(str, prefix + items))) f.close()
class AnalyzerMainWindow(QMainWindow): TITLE = 'CecogAnalyzer' NAME_FILTERS = ['Settings files (*.conf)', 'All files (*.*)'] modified = pyqtSignal('bool') def __init__(self): QMainWindow.__init__(self) qApp._main_window = self self._is_initialized = False self._debug = False self._imagecontainer = None self._meta_data = None self._browser = None self.setWindowTitle(self.TITLE + '[*]') central_widget = QFrame(self) self.setCentralWidget(central_widget) action_about = self.create_action('&About', slot=self._on_about) action_quit = self.create_action('&Quit', slot=self._on_quit) action_pref = self.create_action('&Preferences', slot=self._on_preferences) #action_new = self.create_action('&New...', shortcut=QKeySequence.New, # icon='filenew') action_open = self.create_action('&Open Settings...', shortcut=QKeySequence.Open, slot=self._on_file_open ) action_save = self.create_action('&Save Settings', shortcut=QKeySequence.Save, slot=self._on_file_save ) self.action_save = action_save action_save_as = self.create_action('&Save Settings As...', shortcut=QKeySequence.SaveAs, slot=self._on_file_save_as ) menu_file = self.menuBar().addMenu('&File') self.add_actions(menu_file, (action_about, action_pref, None, action_open, None, action_save, action_save_as, None, action_quit)) action_open = self.create_action('&Open Browser...', shortcut=QKeySequence('CTRL+B'), slot=self._on_browser_open ) menu_browser = self.menuBar().addMenu('&Browser') self.add_actions(menu_browser, (action_open, #None, action_save, action_save_as, #None, action_quit )) action_log = self.create_action('&Show Log Window...', shortcut=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=QKeySequence.HelpContents, slot=self._on_help_startup ) menu_help = self.menuBar().addMenu('&Help') self.add_actions(menu_help, (action_help_startup,)) qApp._statusbar = QStatusBar(self) self.setStatusBar(qApp._statusbar) self._selection = QListWidget(central_widget) self._selection.setViewMode(QListView.IconMode) #self._selection.setUniformItemSizes(True) self._selection.setIconSize(QSize(35, 35)) self._selection.setGridSize(QSize(140, 60)) #self._selection.setWrapping(False) self._selection.setMovement(QListView.Static) #self._selection.setFlow(QListView.TopToBottom) #self._selection.setSpacing(12) self._selection.setMaximumWidth(self._selection.gridSize().width() + 5) self._selection.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._selection.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)) self._pages = QStackedWidget(central_widget) 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), OutputFrame(self._settings, self._pages), ProcessingFrame(self._settings, self._pages), ] if ANALYZER_CONFIG.get('Analyzer', 'cluster_support'): self._tabs.append(ClusterFrame(self._settings, self._pages)) 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 = QLabel(central_widget) w_logo.setPixmap(QPixmap(':cecog_logo_w145')) layout = QGridLayout(central_widget) layout.addWidget(self._selection, 0, 0) layout.addWidget(w_logo, 1, 0, Qt.AlignBottom | Qt.AlignHCenter) layout.addWidget(self._pages, 0, 1, 2, 1) qApp._log_handler = GuiLogHandler(self) qApp._log_window = LogWindow(qApp._log_handler) qApp._log_window.setGeometry(50, 50, 600, 300) logger = logging.getLogger() qApp._log_handler.setLevel(logging.NOTSET) formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s') qApp._log_handler.setFormatter(formatter) #logger.addHandler(self._handler) logger.setLevel(logging.NOTSET) qApp._image_dialog = None qApp._graphics = None self.setGeometry(0, 0, 1100, 750) self.setMinimumSize(QSize(700, 600)) self.show() self.center() self.raise_() self._is_initialized = True def closeEvent(self, event): ''' The app should quit when the main window is closed. ''' if not self._exit_app(): event.ignore() def test_r_import(self): try: import rpy2.robjects as robjects import rpy2.rinterface as rinterface import rpy2.robjects.numpy2ri # some tests x = robjects.r['pi'] v = robjects.FloatVector([1.1, 2.2, 3.3, 4.4, 5.5, 6.6]) m = robjects.r['matrix'](v, nrow=2) has_R_version = True version = '%s.%s' % (robjects.r['version'][5][0], robjects.r['version'][6][0]) except: has_R_version = False msg = 'R installation not found.\n\n'\ 'To use HMM error correction or plotting functions '\ 'R >= Version 2.9 must be installed together with these.'\ 'packages:\n' msg += ', '.join(R_LIBRARIES) msg += '\n\nSee http://www.r-project.org\n\n' critical(self, 'R installation not found', info=msg, detail_tb=True) if has_R_version: missing_libs = [] buffer = [] rinterface.setWriteConsole(lambda x: buffer.append(x)) for lib_name in R_LIBRARIES: try: robjects.r['library'](lib_name) except: missing_libs.append(lib_name) rinterface.setWriteConsole(None) if len(missing_libs) > 0: msg = 'Missing R package(s)\n\n' msg += ', '.join(missing_libs) msg += '\n\nSee http://www.r-project.org\n\n' msg += '\n'.join(buffer) critical(self, 'Missing R libraries', info=msg, detail_tb=True) qApp.valid_R_version = False else: qApp.valid_R_version = True 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 = QListWidgetItem(self._selection) button.setIcon(QIcon(widget.ICON)) button.setText(widget.get_name()) button.setTextAlignment(Qt.AlignHCenter) #button.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) #self.connect(button, ) # scroll_area = QScrollArea(self._pages) # scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) # scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # scroll_area.setWidgetResizable(True) # scroll_area.setWidget(widget) # # self._pages.addWidget(scroll_area) 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 _exit_app(self): do_exit = False if not self._debug: if question(self, 'Do you really want to exit?', modal=True): if self._check_settings_saved() != QMessageBox.Cancel: do_exit = True qApp.exit() else: do_exit = True qApp.exit() return do_exit def center(self): screen = 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 = 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) 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 self.setWindowTitle('%s - %s[*]' % (self.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) self.settings_changed(False) 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.TITLE, filename)) self.settings_changed(False) status('Settings successfully saved.') def _on_about(self): print "about" dialog = QDialog(self) #dialog.setBackgroundRole(QPalette.Dark) dialog.setStyleSheet('background: #000000; ' 'background-image: url(:cecog_about)') dialog.setWindowTitle('About CecogAnalyzer') dialog.setFixedSize(400, 300) layout = QGridLayout() layout.setContentsMargins(0, 0, 0, 0) #image = QImage(':cecog_splash') #label1 = QLabel(dialog) #label1.setStyleSheet('background-image: url(:cecog_splash)') #label1.setPixmap(QPixmap.fromImage(image)) #layout.addWidget(label1, 0, 0) label2 = QLabel(dialog) label2.setStyleSheet('background: transparent;') label2.setAlignment(Qt.AlignCenter) label2.setText('CecogAnalyzer\nVersion %s\n\n' 'Copyright (c) 2006 - 2011\n' % VERSION) label3 = QLabel(dialog) label3.setStyleSheet('background: transparent;') label3.setTextFormat(Qt.AutoText) label3.setOpenExternalLinks(True) label3.setAlignment(Qt.AlignCenter) #palette = label2.palette() #palette.link = QBrush(QColor(200,200,200)) #label3.setPalette(palette) label3.setText('<style>a { color: green; } a:visited { color: green; }</style>' '<a href="http://cellcognition.org">cellcognition.org</a><br>') layout.addWidget(label2, 1, 0) layout.addWidget(label3, 2, 0) layout.setAlignment(Qt.AlignCenter | Qt.AlignBottom) dialog.setLayout(layout) dialog.show() def _on_preferences(self): print "pref" def _on_quit(self): self._exit_app() 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(get_package_path(), 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 = QPushButton('No', box) box.addButton(btn1, QMessageBox.NoRole) box.setDefaultButton(btn1) elif len(found_plates) > 0: btn1 = QPushButton('Rescan missing', box) box.addButton(btn1, QMessageBox.YesRole) box.setDefaultButton(btn1) else: btn1 = None btn2 = 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 trait_x0 = self._settings.get_trait(SECTION_NAME_GENERAL, 'crop_image_x0') trait_y0 = self._settings.get_trait(SECTION_NAME_GENERAL, 'crop_image_y0') trait_x1 = self._settings.get_trait(SECTION_NAME_GENERAL, 'crop_image_x1') trait_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 trait_x0.set_value(trait_x0.get_widget(), x0) trait_y0.set_value(trait_y0.get_widget(), y0) trait_x1.set_value(trait_x1.get_widget(), x1) trait_y0.set_value(trait_y1.get_widget(), y1) else: trait_x0.set_value(trait_x0.get_widget(), x0_) trait_y0.set_value(trait_y0.get_widget(), y0_) trait_x1.set_value(trait_x1.get_widget(), x1_) trait_y0.set_value(trait_y1.get_widget(), y1_) # Set GUI widget valid ranges trait_x0.set_min_value(x0_) trait_x0.set_max_value(x1_) trait_y0.set_min_value(y0_) trait_y0.set_max_value(y1_) trait_x1.set_min_value(x0_) trait_x1.set_max_value(x1_) trait_y1.set_min_value(y0_) trait_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) @pyqtSlot() def _on_file_open(self): if self._check_settings_saved() != QMessageBox.Cancel: dir = '' if not self._settings_filename is None: settings_filename = convert_package_path(self._settings_filename) if os.path.isfile(settings_filename): dir = settings_filename filename = QFileDialog.getOpenFileName(self, 'Open config file', dir, ';;'.join(self.NAME_FILTERS)) if filename: self._read_settings(filename) self._clear_browser() self.set_modules_active(state=False) @pyqtSlot() def _on_file_save(self): self.save_settings(False) @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() del self._browser # FIXME: necessary step to prevent crash after loading of new image container gc.collect() self._browser = None def _on_show_log_window(self): logger = logging.getLogger() logger.addHandler(qApp._log_handler) qApp._log_window.show() qApp._log_window.raise_() def __get_save_as_filename(self): dir = '' if not self._settings_filename is None: settings_filename = convert_package_path(self._settings_filename) if os.path.isfile(settings_filename): dir = settings_filename filename = 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 __init__(self, name): self.name = name self._registry = OrderedDict()