class CONFIDENCE(object): UNKNOWN = None GUESSING = 1 NOT_SURE = 2 PRETTY_SURE = 3 ABSOLUTELY_SURE = 4 INT_TO_CODE = ut.odict([ (ABSOLUTELY_SURE, 'absolutely_sure'), (PRETTY_SURE, 'pretty_sure'), (NOT_SURE, 'not_sure'), (GUESSING, 'guessing'), (UNKNOWN, 'unspecified'), ]) INT_TO_NICE = ut.odict([ (ABSOLUTELY_SURE, 'Doubtless'), (PRETTY_SURE, 'Sure'), (NOT_SURE, 'Unsure'), (GUESSING, 'Guessing'), (UNKNOWN, 'Unspecified'), ]) CODE_TO_NICE = ut.map_keys(INT_TO_CODE, INT_TO_NICE) CODE_TO_INT = ut.invert_dict(INT_TO_CODE) NICE_TO_CODE = ut.invert_dict(CODE_TO_NICE) NICE_TO_INT = ut.invert_dict(INT_TO_NICE)
class QUAL(object): EXCELLENT = 5 GOOD = 4 OK = 3 POOR = 2 JUNK = 1 UNKNOWN = None INT_TO_CODE = ut.odict([ (EXCELLENT, 'excellent'), (GOOD, 'good'), (OK, 'ok'), (POOR, 'poor'), (JUNK, 'junk'), (UNKNOWN, 'unspecified'), ]) INT_TO_NICE = ut.odict([ (EXCELLENT, 'Excellent'), (GOOD, 'Good'), (OK, 'OK'), (POOR, 'Poor'), (JUNK, 'Junk'), (UNKNOWN, 'Unspecified'), ]) CODE_TO_NICE = ut.map_keys(INT_TO_CODE, INT_TO_NICE) CODE_TO_INT = ut.invert_dict(INT_TO_CODE) NICE_TO_CODE = ut.invert_dict(CODE_TO_NICE) NICE_TO_INT = ut.invert_dict(INT_TO_NICE)
class META_DECISION(object): # NOQA """ Enumerated types of review codes and texts Notes: unreviewed: we dont have a meta decision same: we know this is the same animal through non-visual means diff: we know this is the different animal through non-visual means Example: >>> # ENABLE_DOCTEST >>> from wbia.constants import * # NOQA >>> assert hasattr(META_DECISION, 'CODE') >>> assert hasattr(META_DECISION, 'NICE') >>> code1 = META_DECISION.INT_TO_CODE[META_DECISION.NULL] >>> code2 = META_DECISION.CODE.NULL >>> assert code1 == code2 >>> nice1 = META_DECISION.INT_TO_NICE[META_DECISION.NULL] >>> nice2 = META_DECISION.NICE.NULL >>> assert nice1 == nice2 """ NULL = None DIFF = 0 SAME = 1 INT_TO_CODE = ut.odict([(NULL, 'null'), (DIFF, 'diff'), (SAME, 'same')]) INT_TO_NICE = ut.odict([(NULL, 'NULL'), (DIFF, 'Different'), (SAME, 'Same')]) CODE_TO_NICE = ut.map_keys(INT_TO_CODE, INT_TO_NICE) CODE_TO_INT = ut.invert_dict(INT_TO_CODE) NICE_TO_CODE = ut.invert_dict(CODE_TO_NICE) NICE_TO_INT = ut.invert_dict(INT_TO_NICE)
def get_oracle_name_decision(metatup, ibs, qaid, choicetup, oracle_method=1): """ Find what the correct decision should be ibs is the database we are working with ibs_gt has pristine groundtruth """ if ut.VERBOSE: print('Oracle is making decision using oracle_method=%r' % oracle_method) if metatup is None: print('WARNING METATUP IS NONE') return None MAX_LOOK = 3 # the oracle should only see what the user sees (sorted_nids, sorted_nscore, sorted_rawscore, sorted_aids, sorted_ascores) = choicetup (ibs_gt, aid1_to_aid2) = metatup # Get the annotations that the user can see aid_list2 = ut.get_list_column(sorted_aids, 0) # Get the groundtruth name of the query aid2_to_aid1 = ut.invert_dict(aid1_to_aid2) qnid1 = ibs_gt.get_annot_name_rowids(aid2_to_aid1[qaid]) # Make an oracle decision by choosing a name (like a user would) if oracle_method == 1: chosen_names = oracle_method1(ibs_gt, ibs, qnid1, aid_list2, aid2_to_aid1, sorted_nids, MAX_LOOK) elif oracle_method == 2: chosen_names = oracle_method2(ibs_gt, qnid1) else: raise AssertionError('unknown oracle method %r' % (oracle_method, )) if ut.VERBOSE: print('Oracle decision is chosen_names=%r' % (chosen_names, )) return chosen_names
def get_oracle_name_decision(metatup, ibs, qaid, choicetup, oracle_method=1): """ Find what the correct decision should be ibs is the database we are working with ibs_gt has pristine groundtruth """ if ut.VERBOSE: print('Oracle is making decision using oracle_method=%r' % oracle_method) if metatup is None: print('WARNING METATUP IS NONE') return None MAX_LOOK = 3 # the oracle should only see what the user sees (sorted_nids, sorted_nscore, sorted_rawscore, sorted_aids, sorted_ascores) = choicetup (ibs_gt, aid1_to_aid2) = metatup # Get the annotations that the user can see aid_list2 = ut.get_list_column(sorted_aids, 0) # Get the groundtruth name of the query aid2_to_aid1 = ut.invert_dict(aid1_to_aid2) qnid1 = ibs_gt.get_annot_name_rowids(aid2_to_aid1[qaid]) # Make an oracle decision by choosing a name (like a user would) if oracle_method == 1: chosen_names = oracle_method1(ibs_gt, ibs, qnid1, aid_list2, aid2_to_aid1, sorted_nids, MAX_LOOK) elif oracle_method == 2: chosen_names = oracle_method2(ibs_gt, qnid1) else: raise AssertionError('unknown oracle method %r' % (oracle_method,)) if ut.VERBOSE: print('Oracle decision is chosen_names=%r' % (chosen_names,)) return chosen_names
def _update_state_gco(model, weight_key='cut_weight', name_label_key='name_label'): import networkx as nx # Get nx graph properties external_nodes = sorted(list(model.graph.nodes())) external_edges = list(model.graph.edges()) edge_to_weights = nx.get_edge_attributes(model.graph, weight_key) node_to_labeling = nx.get_node_attributes(model.graph, name_label_key) edge_weights = ut.dict_take(edge_to_weights, external_edges, 0) external_labeling = [ node_to_labeling.get(node, -node) for node in external_nodes ] # Map to internal ids for pygco internal_nodes = ut.rebase_labels(external_nodes) extern2_intern = dict(zip(external_nodes, internal_nodes)) internal_edges = ut.unflat_take(extern2_intern, external_edges) internal_labeling = ut.rebase_labels(external_labeling) internal_labeling = np.array(internal_labeling) internal_edges = np.array(internal_edges) n_nodes = len(internal_nodes) # Model state model.n_nodes = n_nodes model.extern2_intern = extern2_intern model.intern2_extern = ut.invert_dict(extern2_intern) model.edges = internal_edges model.edge_weights = edge_weights # Model parameters model.labeling = np.zeros(model.n_nodes, dtype=np.int32) model._update_labels(labeling=internal_labeling) model._update_weights()
def config_graph_subattrs(cfg, depc): # TODO: if this hack is fully completed need a way of getting the # full config belonging to both chip + feat # cfg = request.config.feat_cfg import networkx as netx tablename = ut.invert_dict(depc.configclass_dict)[cfg.__class__] #tablename = cfg.get_config_name() ancestors = netx.dag.ancestors(depc.graph, tablename) subconfigs_ = ut.dict_take(depc.configclass_dict, ancestors, None) subconfigs = ut.filter_Nones(subconfigs_) # NOQA
class EVIDENCE_DECISION(object): # NOQA """ TODO: change to EVIDENCE_DECISION / VISUAL_DECISION Enumerated types of review codes and texts Notes: Unreviewed: Not comparared yet. nomatch: Visually comparable and the different match: Visually comparable and the same notcomp: Not comparable means it is actually impossible to determine. unknown: means that it was reviewed, but we just can't figure it out. """ UNREVIEWED = None NEGATIVE = 0 POSITIVE = 1 INCOMPARABLE = 2 UNKNOWN = 3 INT_TO_CODE = ut.odict([ (POSITIVE, 'match'), (NEGATIVE, 'nomatch'), (INCOMPARABLE, 'notcomp'), (UNKNOWN, 'unknown'), (UNREVIEWED, 'unreviewed'), ]) INT_TO_NICE = ut.odict([ (POSITIVE, 'Positive'), (NEGATIVE, 'Negative'), (INCOMPARABLE, 'Incomparable'), (UNKNOWN, 'Unknown'), (UNREVIEWED, 'Unreviewed'), ]) CODE_TO_NICE = ut.map_keys(INT_TO_CODE, INT_TO_NICE) CODE_TO_INT = ut.invert_dict(INT_TO_CODE) NICE_TO_CODE = ut.invert_dict(CODE_TO_NICE) NICE_TO_INT = ut.invert_dict(INT_TO_NICE) MATCH_CODE = CODE_TO_INT
def static_new(cls, depc, parent_rowids, cfgdict=None, tablename=None): """ hack for autoreload """ request = cls() if tablename is None: try: if hasattr(cls, '_tablename'): tablename = cls._tablename else: tablename = ut.invert_dict(depc.requestclass_dict)[cls] except Exception as ex: ut.printex(ex, 'tablename must be given') raise request.tablename = tablename request.parent_rowids = parent_rowids request.depc = depc if cfgdict is None: cfgdict = {} configclass = depc.configclass_dict[tablename] config = configclass(**cfgdict) request.config = config # HACK FOR IBEIS request.params = dict(config.parse_items()) # HACK-ier FOR BACKWARDS COMPATABILITY if True: # params.featweight_cfgstr = query_cfg._featweight_cfg.get_cfgstr() # TODO: if this hack is fully completed need a way of getting the # full config belonging to both chip + feat try: request.params['chip_cfgstr'] = config.chip_cfg.get_cfgstr() request.params['chip_cfg_dict'] = config.chip_cfg.asdict() request.params['feat_cfgstr'] = config.feat_cfg.get_cfgstr() request.params[ 'hesaff_params'] = config.feat_cfg.get_hesaff_params() request.params[ 'featweight_cfgstr'] = config.feat_weight_cfg.get_cfgstr() except AttributeError: pass request.qparams = ut.DynStruct() for key, val in request.params.items(): setattr(request.qparams, key, val) return request
def static_new(cls, depc, parent_rowids, cfgdict=None, tablename=None): """ hack for autoreload """ request = cls() if tablename is None: try: if hasattr(cls, '_tablename'): tablename = cls._tablename else: tablename = ut.invert_dict(depc.requestclass_dict)[cls] except Exception as ex: ut.printex(ex, 'tablename must be given') raise request.tablename = tablename request.parent_rowids = parent_rowids request.depc = depc if cfgdict is None: cfgdict = {} configclass = depc.configclass_dict[tablename] config = configclass(**cfgdict) request.config = config # HACK FOR IBEIS request.params = dict(config.parse_items()) # HACK-ier FOR BACKWARDS COMPATABILITY if True: #params.featweight_cfgstr = query_cfg._featweight_cfg.get_cfgstr() # TODO: if this hack is fully completed need a way of getting the # full config belonging to both chip + feat try: request.params['chip_cfgstr'] = config.chip_cfg.get_cfgstr() request.params['chip_cfg_dict'] = config.chip_cfg.asdict() request.params['feat_cfgstr'] = config.feat_cfg.get_cfgstr() request.params['hesaff_params'] = config.feat_cfg.get_hesaff_params() request.params['featweight_cfgstr'] = config.feat_weight_cfg.get_cfgstr() except AttributeError: pass request.qparams = ut.DynStruct() for key, val in request.params.items(): setattr(request.qparams, key, val) return request
def __init__(self, infr, selected_aids=[], use_image=False, temp_nids=None): super(AnnotGraphInteraction, self).__init__() self.infr = infr self.selected_aids = selected_aids self.node2_aid = nx.get_node_attributes(self.infr.graph, 'aid') self.aid2_node = ut.invert_dict(self.node2_aid) node2_label = { #node: '%d:aid=%r' % (node, aid) node: 'aid=%r' % (aid) for node, aid in self.node2_aid.items() } #self.show_cuts = False self.use_image = use_image self.show_cuts = False self.config = InferenceConfig() nx.set_node_attributes(self.infr.graph, name='label', values=node2_label)
def __init__(verif, infr): verif.rng = np.random.RandomState(4033913) verif.dummy_params = { NEGTV: { 'mean': 0.2, 'std': 0.25 }, POSTV: { 'mean': 0.85, 'std': 0.2 }, INCMP: { 'mean': 0.15, 'std': 0.1 }, } verif.score_dist = randn verif.infr = infr verif.orig_nodes = set(infr.aids) verif.orig_labels = infr.get_node_attrs('orig_name_label') verif.orig_groups = ut.invert_dict(verif.orig_labels, False) verif.orig_groups = ut.map_vals(set, verif.orig_groups)
def netrun(): r""" CommandLine: # --- UTILITY python -m ibeis_cnn --tf get_juction_dpath --show # --- DATASET BUILDING --- # Build Dataset Aliases python -m ibeis_cnn --tf netrun --db PZ_MTEST --acfg ctrl --ensuredata --show python -m ibeis_cnn --tf netrun --db PZ_Master1 --acfg timectrl --ensuredata python -m ibeis_cnn --tf netrun --db PZ_Master1 --acfg timectrl:pername=None --ensuredata python -m ibeis_cnn --tf netrun --db PZ_Master1 --acfg timectrl:pername=None --ensuredata python -m ibeis_cnn --tf netrun --db mnist --ensuredata --show python -m ibeis_cnn --tf netrun --db mnist --ensuredata --show --datatype=category python -m ibeis_cnn --tf netrun --db mnist --ensuredata --show --datatype=siam-patch python -m ibeis_cnn --tf netrun --db PZ_Master1 --acfg ctrl:pername=None,excluderef=False,contributor_contains=FlankHack --ensuredata --show --datatype=siam-part # Parts based datasets python -m ibeis_cnn --tf netrun --db PZ_MTEST --acfg ctrl --datatype=siam-part --ensuredata --show % Patch based dataset (big one) python -m ibeis_cnn --tf netrun --db PZ_Master1 --acfg default:is_known=True,qmin_pername=2,view=primary,species=primary,minqual=ok --ensuredata --show --vtd python -m ibeis_cnn --tf netrun --ds pzm4 --weights=new --arch=siaml2_128 --train --monitor python -m ibeis_cnn --tf netrun --ds pzm4 --arch=siaml2_128 --test python -m ibeis_cnn --tf netrun --ds pzm4 --arch=siaml2_128 --veryverbose --no-flask # --- TRAINING --- python -m ibeis_cnn --tf netrun --db PZ_Master1 --acfg default:is_known=True,qmin_pername=2,view=primary,species=primary,minqual=ok --weights=new --arch=siaml2_128 --train --monitor python -m ibeis_cnn --tf netrun --ds timectrl_pzmaster1 --acfg ctrl:pername=None,excluderef=False,contributor_contains=FlankHack --train --weights=new --arch=siaml2_128 --monitor # NOQA python -m ibeis_cnn --tf netrun --ds timectrl_pzmaster1 --acfg ctrl:pername=None,excluderef=False --train --weights=new --arch=siaml2_128 --monitor # NOQA python -m ibeis_cnn --tf netrun --ds pzmtest --weights=new --arch=siaml2_128 --train --monitor --DEBUG_AUGMENTATION python -m ibeis_cnn --tf netrun --ds pzmtest --weights=new --arch=siaml2_128 --train --monitor python -m ibeis_cnn --tf netrun --ds flankhack --weights=new --arch=siaml2_partmatch --train --monitor --learning_rate=.00001 python -m ibeis_cnn --tf netrun --ds flankhack --weights=new --arch=siam_deepfaceish --train --monitor --learning_rate=.00001 # Different ways to train mnist python -m ibeis_cnn --tf netrun --db mnist --weights=new --arch=mnist_siaml2 --train --monitor --datatype=siam-patch python -m ibeis_cnn --tf netrun --db mnist --weights=new --arch=mnist-category --train --monitor --datatype=category # --- INITIALIZED-TRAINING --- python -m ibeis_cnn --tf netrun --ds pzmtest --arch=siaml2_128 --weights=gz-gray:current --train --monitor # --- TESTING --- python -m ibeis_cnn --tf netrun --db liberty --weights=liberty:current --arch=siaml2_128 --test python -m ibeis_cnn --tf netrun --db PZ_Master0 --weights=combo:current --arch=siaml2_128 --testall Example: >>> # DISABLE_DOCTEST >>> from ibeis_cnn.netrun import * # NOQA >>> netrun() >>> ut.show_if_requested() """ ut.colorprint('[netrun] NET RUN', 'red') requests, hyperparams, tags = parse_args() ds_tag = tags['ds_tag'] datatype = tags['datatype'] extern_ds_tag = tags['extern_ds_tag'] arch_tag = tags['arch_tag'] checkpoint_tag = tags['checkpoint_tag'] # ---------------------------- # Choose the main dataset ut.colorprint('[netrun] Ensuring Dataset', 'yellow') dataset = ingest_data.grab_dataset(ds_tag, datatype) if extern_ds_tag is not None: extern_dpath = ingest_data.get_extern_training_dpath(extern_ds_tag) else: extern_dpath = None print('dataset.training_dpath = %r' % (dataset.training_dpath,)) print('Dataset Alias Key: %r' % (dataset.alias_key,)) print('Current Dataset Tag: %r' % ( ut.invert_dict(DS_TAG_ALIAS2).get(dataset.alias_key, None),)) if requests['ensuredata']: # Print alias key that maps to this particular dataset if ut.show_was_requested(): interact_ = dataset.interact() # NOQA return print('...exiting') sys.exit(1) # ---------------------------- # Choose model architecture # TODO: data will need to return info about number of labels in viewpoint models # Specify model archichitecture ut.colorprint('[netrun] Architecture Specification', 'yellow') if arch_tag == 'siam2stream': model = models.SiameseCenterSurroundModel( data_shape=dataset.data_shape, training_dpath=dataset.training_dpath, **hyperparams) elif arch_tag.startswith('siam'): model = models.SiameseL2( data_shape=dataset.data_shape, arch_tag=arch_tag, training_dpath=dataset.training_dpath, **hyperparams) elif arch_tag == 'mnist-category': model = models.MNISTModel( data_shape=dataset.data_shape, output_dims=dataset.output_dims, arch_tag=arch_tag, training_dpath=dataset.training_dpath, **hyperparams) pass else: raise ValueError('Unknown arch_tag=%r' % (arch_tag,)) ut.colorprint('[netrun] Initialize archchitecture', 'yellow') model.init_arch() # ---------------------------- # Choose weight initialization ut.colorprint('[netrun] Setting weights', 'yellow') if checkpoint_tag == 'new': ut.colorprint('[netrun] * Initializing new weights', 'lightgray') model.reinit_weights() else: checkpoint_tag = model.resolve_fuzzy_checkpoint_pattern( checkpoint_tag, extern_dpath) ut.colorprint('[netrun] * Resolving weights checkpoint_tag=%r' % (checkpoint_tag,), 'lightgray') if extern_dpath is not None: model.load_extern_weights(dpath=extern_dpath, checkpoint_tag=checkpoint_tag) elif model.has_saved_state(checkpoint_tag=checkpoint_tag): model.load_model_state(checkpoint_tag=checkpoint_tag) else: model_state_fpath = model.get_model_state_fpath( checkpoint_tag=checkpoint_tag) print('model_state_fpath = %r' % (model_state_fpath,)) ut.checkpath(model_state_fpath, verbose=True) print('Known checkpoints are: ' + ut.repr3(model.list_saved_checkpoints())) raise ValueError(('Unresolved weight init: ' 'checkpoint_tag=%r, extern_ds_tag=%r') % ( checkpoint_tag, extern_ds_tag,)) #print('Model State:') #print(model.get_state_str()) # ---------------------------- if not model.is_train_state_initialized(): ut.colorprint('[netrun] Need to initialize training state', 'yellow') X_train, y_train = dataset.subset('train') model.ensure_data_params(X_train, y_train) # Run Actions if requests['train']: ut.colorprint('[netrun] Training Requested', 'yellow') # parse training arguments config = ut.argparse_dict(dict( era_size=15, max_epochs=1200, rate_decay=.8, )) model.monitor_config.update(**config) X_train, y_train = dataset.subset('train') X_valid, y_valid = dataset.subset('valid') model.fit(X_train, y_train, X_valid=X_valid, y_valid=y_valid) elif requests['test']: #assert model.best_results['epoch'] is not None ut.colorprint('[netrun] Test Requested', 'yellow') if requests['testall']: ut.colorprint('[netrun] * Testing on all data', 'lightgray') X_test, y_test = dataset.subset('all') flat_metadata = dataset.subset_metadata('all') else: ut.colorprint('[netrun] * Testing on test subset', 'lightgray') X_test, y_test = dataset.subset('test') flat_metadata = dataset.subset_metadata('test') data, labels = X_test, y_test dataname = dataset.alias_key experiments.test_siamese_performance(model, data, labels, flat_metadata, dataname) else: if not ut.get_argflag('--cmd'): raise ValueError('nothing here. need to train or test') if requests['publish']: ut.colorprint('[netrun] Publish Requested', 'yellow') publish_dpath = ut.truepath('~/Dropbox/IBEIS') published_model_state = ut.unixjoin( publish_dpath, model.arch_tag + '_model_state.pkl') ut.copy(model.get_model_state_fpath(), published_model_state) ut.view_directory(publish_dpath) print('You need to get the dropbox link and ' 'register it into the appropriate file') # pip install dropbox # https://www.dropbox.com/developers/core/start/python # import dropbox # need oauth #client.share('/myfile.txt', short_url=False) # https://cthulhu.dyn.wildme.io/public/models/siaml2_128_model_state.pkl if ut.get_argflag('--cmd'): ut.embed()
def _inject_getter_attrs(metaself, objname, attrs, configurable_attrs, depc_name=None, depcache_attrs=None, settable_attrs=None, aliased_attrs=None): """ Used by the metaclass to inject methods and properties into the class inheriting from ObjectList1D """ if settable_attrs is None: settable_attrs = [] settable_attrs = set(settable_attrs) # Inform the class of which variables will be injected metaself._settable_attrs = settable_attrs metaself._attrs = attrs metaself._configurable_attrs = configurable_attrs if depcache_attrs is None: metaself._depcache_attrs = [] else: metaself._depcache_attrs = [ '%s_%s' % (tbl, col) for tbl, col in depcache_attrs ] if aliased_attrs is not None: metaself._attrs_aliases = aliased_attrs else: metaself._attrs_aliases = {} # if not getattr(metaself, '__needs_inject__', True): # return attr_to_aliases = ut.invert_dict(metaself._attrs_aliases, unique_vals=False) # What is difference between configurable and depcache getters? # Could depcache getters just be made configurable? # I guess its just an efficincy thing. Actually its config2_-vs-config # FIXME: rectify differences between normal / configurable / depcache # getter def _make_caching_setter(attrname, _rowid_setter): def _setter(self, values, *args, **kwargs): if self._ibs is None: self._internal_attrs[attrname] = values else: if self._caching and attrname in self._internal_attrs: self._internal_attrs[attrname] = values _rowid_setter(self, self._rowids, values) ut.set_funcname(_setter, '_set_' + attrname) return _setter def _make_caching_getter(attrname, _rowid_getter): def _getter(self): if self._ibs is None or (self._caching and attrname in self._internal_attrs): data = self._internal_attrs[attrname] else: data = _rowid_getter(self, self._rowids) if self._caching: self._internal_attrs[attrname] = data return data ut.set_funcname(_getter, '_get_' + attrname) return _getter # make default version use implicit rowids and another # that takes explicit rowids. def _make_setters(objname, attrname): ibs_funcname = 'set_%s_%s' % (objname, attrname) def _rowid_setter(self, rowids, values, *args, **kwargs): ibs_callable = getattr(self._ibs, ibs_funcname) ibs_callable(rowids, values, *args, **kwargs) ut.set_funcname(_rowid_setter, '_rowid_set_' + attrname) _setter = _make_caching_setter(attrname, _rowid_setter) return _rowid_setter, _setter # --- def _make_getters(objname, attrname): ibs_funcname = 'get_%s_%s' % (objname, attrname) def _rowid_getter(self, rowids): ibs_callable = getattr(self._ibs, ibs_funcname) data = ibs_callable(rowids) if self._asarray: data = np.array(data) return data ut.set_funcname(_rowid_getter, '_rowid_get_' + attrname) _getter = _make_caching_getter(attrname, _rowid_getter) return _rowid_getter, _getter def _make_cfg_getters(objname, attrname): ibs_funcname = 'get_%s_%s' % (objname, attrname) def _rowid_getter(self, rowids): ibs_callable = getattr(self._ibs, ibs_funcname) data = ibs_callable(rowids, config2_=self._config) if self._asarray: data = np.array(data) return data ut.set_funcname(_rowid_getter, '_rowid_get_' + attrname) _getter = _make_caching_getter(attrname, _rowid_getter) return _rowid_getter, _getter def _make_depc_getters(depc_name, attrname, tbl, col): def _rowid_getter(self, rowids): depc = getattr(self._ibs, depc_name) data = depc.get(tbl, rowids, col, config=self._config) if self._asarray: data = np.array(data) return data ut.set_funcname(_rowid_getter, '_rowid_get_' + attrname) _getter = _make_caching_getter(attrname, _rowid_getter) return _rowid_getter, _getter # Collect setter / getter functions and properties rowid_getters = [] getters = [] setters = [] properties = [] for attrname in attrs: _rowid_getter, _getter = _make_getters(objname, attrname) if attrname in settable_attrs: _rowid_setter, _setter = _make_setters(objname, attrname) setters.append(_setter) else: _setter = None prop = property(fget=_getter, fset=_setter) rowid_getters.append((attrname, _rowid_getter)) getters.append(_getter) properties.append((attrname, prop)) for attrname in configurable_attrs: _rowid_getter, _getter = _make_cfg_getters(objname, attrname) prop = property(fget=_getter) rowid_getters.append((attrname, _rowid_getter)) getters.append(_getter) properties.append((attrname, prop)) if depcache_attrs is not None: for tbl, col in depcache_attrs: attrname = '%s_%s' % (tbl, col) _rowid_getter, _getter = _make_depc_getters( depc_name, attrname, tbl, col) prop = property(fget=_getter, fset=None) rowid_getters.append((attrname, _rowid_getter)) getters.append(_getter) properties.append((attrname, prop)) aliases = [] # Inject all gathered information for attrname, func in rowid_getters: funcname = ut.get_funcname(func) setattr(metaself, funcname, func) # ensure aliases have rowid getters for alias in attr_to_aliases.get(attrname, []): alias_funcname = '_rowid_get_' + alias setattr(metaself, alias_funcname, func) for func in getters: funcname = ut.get_funcname(func) setattr(metaself, funcname, func) for func in setters: funcname = ut.get_funcname(func) setattr(metaself, funcname, func) for attrname, prop in properties: setattr(metaself, attrname, prop) for alias in attr_to_aliases.pop(attrname, []): aliases.append((alias, attrname)) setattr(metaself, alias, prop) if ut.get_argflag('--autogen-core'): # TODO: turn on autogenertion given a flag def expand_closure_source(funcname, func): source = ut.get_func_sourcecode(func) closure_vars = [ (k, v.cell_contents) for k, v in zip(func.func_code.co_freevars, func.func_closure) ] source = ut.unindent(source) import re for k, v in closure_vars: source = re.sub('\\b' + k + '\\b', ut.repr2(v), source) source = re.sub('def .*\(self', 'def ' + funcname + '(self', source) source = ut.indent(source.strip(), ' ') + '\n' return source explicit_lines = [] # build explicit version for jedi? for funcname, func in getters: source = expand_closure_source(funcname, func) explicit_lines.append(source) # build explicit version for jedi? for funcname, func in setters: source = expand_closure_source(funcname, func) explicit_lines.append(source) for attrname, prop in properties: getter_name = None if prop.fget is None else ut.get_funcname( prop.fget) setter_name = None if prop.fset is None else ut.get_funcname( prop.fset) source = ' %s = property(%s, %s)' % (attrname, getter_name, setter_name) explicit_lines.append(source) for alias, attrname in aliases: source = ' %s = %s' % (alias, attrname) explicit_lines.append(source) explicit_source = '\n'.join([ 'from ibeis import _ibeis_object', '', '', 'class _%s_base_class(_ibeis_object.ObjectList1D):', ' __needs_inject__ = False', '', ]) % (objname, ) explicit_source += '\n'.join(explicit_lines) explicit_fname = '_autogen_%s_base.py' % (objname, ) from os.path import dirname, join ut.writeto(join(dirname(__file__), explicit_fname), explicit_source + '\n') if attr_to_aliases: raise AssertionError('Unmapped aliases %r' % (attr_to_aliases, ))
class VIEW(object): """ categorical viewpoint using the faces of a Rhombicuboctahedron References: https://en.wikipedia.org/wiki/Rhombicuboctahedron """ UNKNOWN = None R = 1 FR = 2 F = 3 FL = 4 L = 5 BL = 6 B = 7 BR = 8 U = 9 UF = 10 UB = 11 UL = 12 UR = 13 UFL = 14 UFR = 15 UBL = 16 UBR = 17 D = 18 DF = 19 DB = 20 DL = 21 DR = 22 DFL = 23 DFR = 24 DBL = 25 DBR = 26 INT_TO_CODE = ut.odict([ (UNKNOWN, 'unknown'), (R, 'right'), (FR, 'frontright'), (F, 'front'), (FL, 'frontleft'), (L, 'left'), (BL, 'backleft'), (B, 'back'), (BR, 'backright'), (U, 'up'), (UF, 'upfront'), (UB, 'upback'), (UL, 'upleft'), (UR, 'upright'), (UFL, 'upfrontleft'), (UFR, 'upfrontright'), (UBL, 'upbackleft'), (UBR, 'upbackright'), (D, 'down'), (DF, 'downfront'), (DB, 'downback'), (DL, 'downleft'), (DR, 'downright'), (DFL, 'downfrontleft'), (DFR, 'downfrontright'), (DBL, 'downbackleft'), (DBR, 'downbackright'), ]) INT_TO_NICE = ut.odict([ (UNKNOWN, 'Unknown'), (R, 'Right'), (FR, 'Front-Right'), (F, 'Front'), (FL, 'Front-Left'), (L, 'Left'), (BL, 'Back-Left'), (B, 'Back'), (BR, 'Back-Right'), (U, 'Up'), (UF, 'Up-Front'), (UB, 'Up-Back'), (UL, 'Up-Left'), (UR, 'Up-Right'), (UFL, 'Up-Front-Left'), (UFR, 'Up-Front-Right'), (UBL, 'Up-Back-Left'), (UBR, 'Up-Back-Right'), (D, 'Down'), (DF, 'Down-Front'), (DB, 'Down-Back'), (DL, 'Down-Left'), (DR, 'Down-Right'), (DFL, 'Down-Front-Left'), (DFR, 'Down-Front-Right'), (DBL, 'Down-Back-Left'), (DBR, 'Down-Back-Right'), ]) CODE_TO_NICE = ut.map_keys(INT_TO_CODE, INT_TO_NICE) CODE_TO_INT = ut.invert_dict(INT_TO_CODE) NICE_TO_CODE = ut.invert_dict(CODE_TO_NICE) NICE_TO_INT = ut.invert_dict(INT_TO_NICE) DIST = { # DIST 0 PAIRS (B, B): 0, (BL, BL): 0, (BR, BR): 0, (D, D): 0, (DB, DB): 0, (DBL, DBL): 0, (DBR, DBR): 0, (DF, DF): 0, (DFL, DFL): 0, (DFR, DFR): 0, (DL, DL): 0, (DR, DR): 0, (F, F): 0, (FL, FL): 0, (FR, FR): 0, (L, L): 0, (R, R): 0, (U, U): 0, (UB, UB): 0, (UBL, UBL): 0, (UBR, UBR): 0, (UF, UF): 0, (UFL, UFL): 0, (UFR, UFR): 0, (UL, UL): 0, (UR, UR): 0, # DIST 1 PAIRS (B, BL): 1, (B, BR): 1, (B, DB): 1, (B, DBL): 1, (B, DBR): 1, (B, UB): 1, (B, UBL): 1, (B, UBR): 1, (BL, DBL): 1, (BL, L): 1, (BL, UBL): 1, (BR, DBR): 1, (BR, R): 1, (BR, UBR): 1, (D, DB): 1, (D, DBL): 1, (D, DBR): 1, (D, DF): 1, (D, DFL): 1, (D, DFR): 1, (D, DL): 1, (D, DR): 1, (DB, DBL): 1, (DB, DBR): 1, (DBL, DL): 1, (DBL, L): 1, (DBR, DR): 1, (DBR, R): 1, (DF, DFL): 1, (DF, DFR): 1, (DF, F): 1, (DFL, DL): 1, (DFL, F): 1, (DFL, FL): 1, (DFL, L): 1, (DFR, DR): 1, (DFR, F): 1, (DFR, FR): 1, (DFR, R): 1, (DL, L): 1, (DR, R): 1, (F, FL): 1, (F, FR): 1, (F, UF): 1, (F, UFL): 1, (F, UFR): 1, (FL, L): 1, (FL, UFL): 1, (FR, R): 1, (FR, UFR): 1, (L, UBL): 1, (L, UFL): 1, (L, UL): 1, (R, UBR): 1, (R, UFR): 1, (R, UR): 1, (U, UB): 1, (U, UBL): 1, (U, UBR): 1, (U, UF): 1, (U, UFL): 1, (U, UFR): 1, (U, UL): 1, (U, UR): 1, (UB, UBL): 1, (UB, UBR): 1, (UBL, UL): 1, (UBR, UR): 1, (UF, UFL): 1, (UF, UFR): 1, (UFL, UL): 1, (UFR, UR): 1, # DIST 2 PAIRS (B, D): 2, (B, DL): 2, (B, DR): 2, (B, L): 2, (B, R): 2, (B, U): 2, (B, UL): 2, (B, UR): 2, (BL, BR): 2, (BL, D): 2, (BL, DB): 2, (BL, DBR): 2, (BL, DFL): 2, (BL, DL): 2, (BL, FL): 2, (BL, U): 2, (BL, UB): 2, (BL, UBR): 2, (BL, UFL): 2, (BL, UL): 2, (BR, D): 2, (BR, DB): 2, (BR, DBL): 2, (BR, DFR): 2, (BR, DR): 2, (BR, FR): 2, (BR, U): 2, (BR, UB): 2, (BR, UBL): 2, (BR, UFR): 2, (BR, UR): 2, (D, F): 2, (D, FL): 2, (D, FR): 2, (D, L): 2, (D, R): 2, (DB, DF): 2, (DB, DFL): 2, (DB, DFR): 2, (DB, DL): 2, (DB, DR): 2, (DB, L): 2, (DB, R): 2, (DB, UB): 2, (DB, UBL): 2, (DB, UBR): 2, (DBL, DBR): 2, (DBL, DF): 2, (DBL, DFL): 2, (DBL, DFR): 2, (DBL, DR): 2, (DBL, FL): 2, (DBL, UB): 2, (DBL, UBL): 2, (DBL, UBR): 2, (DBL, UFL): 2, (DBL, UL): 2, (DBR, DF): 2, (DBR, DFL): 2, (DBR, DFR): 2, (DBR, DL): 2, (DBR, FR): 2, (DBR, UB): 2, (DBR, UBL): 2, (DBR, UBR): 2, (DBR, UFR): 2, (DBR, UR): 2, (DF, DL): 2, (DF, DR): 2, (DF, FL): 2, (DF, FR): 2, (DF, L): 2, (DF, R): 2, (DF, UF): 2, (DF, UFL): 2, (DF, UFR): 2, (DFL, DFR): 2, (DFL, DR): 2, (DFL, FR): 2, (DFL, UBL): 2, (DFL, UF): 2, (DFL, UFL): 2, (DFL, UFR): 2, (DFL, UL): 2, (DFR, DL): 2, (DFR, FL): 2, (DFR, UBR): 2, (DFR, UF): 2, (DFR, UFL): 2, (DFR, UFR): 2, (DFR, UR): 2, (DL, DR): 2, (DL, F): 2, (DL, FL): 2, (DL, UBL): 2, (DL, UFL): 2, (DL, UL): 2, (DR, F): 2, (DR, FR): 2, (DR, UBR): 2, (DR, UFR): 2, (DR, UR): 2, (F, L): 2, (F, R): 2, (F, U): 2, (F, UL): 2, (F, UR): 2, (FL, FR): 2, (FL, U): 2, (FL, UBL): 2, (FL, UF): 2, (FL, UFR): 2, (FL, UL): 2, (FR, U): 2, (FR, UBR): 2, (FR, UF): 2, (FR, UFL): 2, (FR, UR): 2, (L, U): 2, (L, UB): 2, (L, UF): 2, (R, U): 2, (R, UB): 2, (R, UF): 2, (UB, UF): 2, (UB, UFL): 2, (UB, UFR): 2, (UB, UL): 2, (UB, UR): 2, (UBL, UBR): 2, (UBL, UF): 2, (UBL, UFL): 2, (UBL, UFR): 2, (UBL, UR): 2, (UBR, UF): 2, (UBR, UFL): 2, (UBR, UFR): 2, (UBR, UL): 2, (UF, UL): 2, (UF, UR): 2, (UFL, UFR): 2, (UFL, UR): 2, (UFR, UL): 2, (UL, UR): 2, # DIST 3 PAIRS (B, DF): 3, (B, DFL): 3, (B, DFR): 3, (B, FL): 3, (B, FR): 3, (B, UF): 3, (B, UFL): 3, (B, UFR): 3, (BL, DF): 3, (BL, DFR): 3, (BL, DR): 3, (BL, F): 3, (BL, R): 3, (BL, UF): 3, (BL, UFR): 3, (BL, UR): 3, (BR, DF): 3, (BR, DFL): 3, (BR, DL): 3, (BR, F): 3, (BR, L): 3, (BR, UF): 3, (BR, UFL): 3, (BR, UL): 3, (D, UB): 3, (D, UBL): 3, (D, UBR): 3, (D, UF): 3, (D, UFL): 3, (D, UFR): 3, (D, UL): 3, (D, UR): 3, (DB, F): 3, (DB, FL): 3, (DB, FR): 3, (DB, U): 3, (DB, UFL): 3, (DB, UFR): 3, (DB, UL): 3, (DB, UR): 3, (DBL, F): 3, (DBL, FR): 3, (DBL, R): 3, (DBL, U): 3, (DBL, UF): 3, (DBL, UR): 3, (DBR, F): 3, (DBR, FL): 3, (DBR, L): 3, (DBR, U): 3, (DBR, UF): 3, (DBR, UL): 3, (DF, U): 3, (DF, UBL): 3, (DF, UBR): 3, (DF, UL): 3, (DF, UR): 3, (DFL, R): 3, (DFL, U): 3, (DFL, UB): 3, (DFL, UR): 3, (DFR, L): 3, (DFR, U): 3, (DFR, UB): 3, (DFR, UL): 3, (DL, FR): 3, (DL, R): 3, (DL, U): 3, (DL, UB): 3, (DL, UBR): 3, (DL, UF): 3, (DL, UFR): 3, (DR, FL): 3, (DR, L): 3, (DR, U): 3, (DR, UB): 3, (DR, UBL): 3, (DR, UF): 3, (DR, UFL): 3, (F, UB): 3, (F, UBL): 3, (F, UBR): 3, (FL, R): 3, (FL, UB): 3, (FL, UBR): 3, (FL, UR): 3, (FR, L): 3, (FR, UB): 3, (FR, UBL): 3, (FR, UL): 3, (L, UBR): 3, (L, UFR): 3, (L, UR): 3, (R, UBL): 3, (R, UFL): 3, (R, UL): 3, # DIST 4 PAIRS (B, F): 4, (BL, FR): 4, (BR, FL): 4, (D, U): 4, (DB, UF): 4, (DBL, UFR): 4, (DBR, UFL): 4, (DF, UB): 4, (DFL, UBR): 4, (DFR, UBL): 4, (DL, UR): 4, (DR, UL): 4, (L, R): 4, # UNDEFINED DIST PAIRS (B, UNKNOWN): None, (BL, UNKNOWN): None, (BR, UNKNOWN): None, (D, UNKNOWN): None, (DB, UNKNOWN): None, (DBL, UNKNOWN): None, (DBR, UNKNOWN): None, (DF, UNKNOWN): None, (DFL, UNKNOWN): None, (DFR, UNKNOWN): None, (DL, UNKNOWN): None, (DR, UNKNOWN): None, (F, UNKNOWN): None, (FL, UNKNOWN): None, (FR, UNKNOWN): None, (L, UNKNOWN): None, (R, UNKNOWN): None, (U, UNKNOWN): None, (UB, UNKNOWN): None, (UBL, UNKNOWN): None, (UBR, UNKNOWN): None, (UF, UNKNOWN): None, (UFL, UNKNOWN): None, (UFR, UNKNOWN): None, (UL, UNKNOWN): None, (UNKNOWN, B): None, (UNKNOWN, BL): None, (UNKNOWN, BR): None, (UNKNOWN, D): None, (UNKNOWN, DB): None, (UNKNOWN, DBL): None, (UNKNOWN, DBR): None, (UNKNOWN, DF): None, (UNKNOWN, DFL): None, (UNKNOWN, DFR): None, (UNKNOWN, DL): None, (UNKNOWN, DR): None, (UNKNOWN, F): None, (UNKNOWN, FL): None, (UNKNOWN, FR): None, (UNKNOWN, L): None, (UNKNOWN, R): None, (UNKNOWN, U): None, (UNKNOWN, UB): None, (UNKNOWN, UBL): None, (UNKNOWN, UBR): None, (UNKNOWN, UF): None, (UNKNOWN, UFL): None, (UNKNOWN, UFR): None, (UNKNOWN, UL): None, (UNKNOWN, UR): None, (UR, UNKNOWN): None, (UNKNOWN, UNKNOWN): None, } # make distance symmetric for (f1, f2), d in list(DIST.items()): DIST[(f2, f1)] = d
QUAL_OK = 'ok' QUAL_POOR = 'poor' QUAL_JUNK = 'junk' QUAL_UNKNOWN = 'UNKNOWN' QUALITY_INT_TO_TEXT = OrderedDict([ (5, QUAL_EXCELLENT,), (4, QUAL_GOOD,), (3, QUAL_OK,), (2, QUAL_POOR,), # oops forgot 1. will be mapped to poor (0, QUAL_JUNK,), (-1, QUAL_UNKNOWN,), ]) QUALITY_TEXT_TO_INT = ut.invert_dict(QUALITY_INT_TO_TEXT) QUALITY_INT_TO_TEXT[1] = QUAL_JUNK #QUALITY_TEXT_TO_INTS = ut.invert_dict(QUALITY_INT_TO_TEXT) QUALITY_TEXT_TO_INTS = ut.group_items( list(QUALITY_INT_TO_TEXT.keys()), list(QUALITY_INT_TO_TEXT.values())) QUALITY_TEXT_TO_INTS[QUAL_UNKNOWN] = -1 QUALITY_INT_TO_TEXT[None] = QUALITY_INT_TO_TEXT[-1] SEX_INT_TO_TEXT = { None: 'UNKNOWN NAME', -1 : 'UNKNOWN SEX', 0 : 'Female', 1 : 'Male', }
def nx_transitive_reduction(G, mode=1): """ References: https://en.wikipedia.org/wiki/Transitive_reduction#Computing_the_reduction_using_the_closure http://dept-info.labri.fr/~thibault/tmp/0201008.pdf http://stackoverflow.com/questions/17078696/im-trying-to-perform-the-transitive-reduction-of-directed-graph-in-python CommandLine: python -m utool.util_graph nx_transitive_reduction --show Example: >>> # DISABLE_DOCTEST >>> from utool.util_graph import * # NOQA >>> import utool as ut >>> import networkx as nx >>> G = nx.DiGraph([('a', 'b'), ('a', 'c'), ('a', 'e'), >>> ('a', 'd'), ('b', 'd'), ('c', 'e'), >>> ('d', 'e'), ('c', 'e'), ('c', 'd')]) >>> G = testdata_graph()[1] >>> G_tr = nx_transitive_reduction(G, mode=1) >>> G_tr2 = nx_transitive_reduction(G, mode=1) >>> ut.quit_if_noshow() >>> import plottool as pt >>> G_ = nx.dag.transitive_closure(G) >>> pt.show_nx(G , pnum=(1, 5, 1), fnum=1) >>> pt.show_nx(G_tr , pnum=(1, 5, 2), fnum=1) >>> pt.show_nx(G_tr2 , pnum=(1, 5, 3), fnum=1) >>> pt.show_nx(G_ , pnum=(1, 5, 4), fnum=1) >>> pt.show_nx(nx.dag.transitive_closure(G_tr), pnum=(1, 5, 5), fnum=1) >>> ut.show_if_requested() """ import utool as ut import networkx as nx has_cycles = not nx.is_directed_acyclic_graph(G) if has_cycles: # FIXME: this does not work for cycle graphs. # Need to do algorithm on SCCs G_orig = G G = nx.condensation(G_orig) nodes = list(G.nodes()) node2_idx = ut.make_index_lookup(nodes) # For each node u, perform DFS consider its set of (non-self) children C. # For each descendant v, of a node in C, remove any edge from u to v. if mode == 1: G_tr = G.copy() for parent in G_tr.nodes(): # Remove self loops if G_tr.has_edge(parent, parent): G_tr.remove_edge(parent, parent) # For each child of the parent for child in list(G_tr.successors(parent)): # Preorder nodes includes its argument (no added complexity) for gchild in list(G_tr.successors(child)): # Remove all edges from parent to non-child descendants for descendant in nx.dfs_preorder_nodes(G_tr, gchild): if G_tr.has_edge(parent, descendant): G_tr.remove_edge(parent, descendant) if has_cycles: # Uncondense graph uncondensed_G_tr = G.__class__() mapping = G.graph['mapping'] uncondensed_G_tr.add_nodes_from(mapping.keys()) inv_mapping = ut.invert_dict(mapping, unique_vals=False) for u, v in G_tr.edges(): u_ = inv_mapping[u][0] v_ = inv_mapping[v][0] uncondensed_G_tr.add_edge(u_, v_) for key, path in inv_mapping.items(): if len(path) > 1: directed_cycle = list(ut.itertwo(path, wrap=True)) uncondensed_G_tr.add_edges_from(directed_cycle) G_tr = uncondensed_G_tr else: def make_adj_matrix(G): edges = list(G.edges()) edge2_idx = ut.partial(ut.dict_take, node2_idx) uv_list = ut.lmap(edge2_idx, edges) A = np.zeros((len(nodes), len(nodes))) A[tuple(np.array(uv_list).T)] = 1 return A G_ = nx.dag.transitive_closure(G) A = make_adj_matrix(G) B = make_adj_matrix(G_) #AB = A * B #AB = A.T.dot(B) AB = A.dot(B) #AB = A.dot(B.T) A_and_notAB = np.logical_and(A, np.logical_not(AB)) tr_uvs = np.where(A_and_notAB) #nodes = G.nodes() edges = list(zip(*ut.unflat_take(nodes, tr_uvs))) G_tr = G.__class__() G_tr.add_nodes_from(nodes) G_tr.add_edges_from(edges) if has_cycles: # Uncondense graph uncondensed_G_tr = G.__class__() mapping = G.graph['mapping'] uncondensed_G_tr.add_nodes_from(mapping.keys()) inv_mapping = ut.invert_dict(mapping, unique_vals=False) for u, v in G_tr.edges(): u_ = inv_mapping[u][0] v_ = inv_mapping[v][0] uncondensed_G_tr.add_edge(u_, v_) for key, path in inv_mapping.items(): if len(path) > 1: directed_cycle = list(ut.itertwo(path, wrap=True)) uncondensed_G_tr.add_edges_from(directed_cycle) G_tr = uncondensed_G_tr return G_tr
def test_vsone_errors(ibs, daids, qaid2_qres_vsmany, qaid2_qres_vsone, incinfo): """ ibs1 = ibs_gt ibs2 = ibs (the current test database, sorry for the backwardness) aid1_to_aid2 - maps annots from ibs1 to ibs2 """ WASH = 'wash' BOTH_FAIL = 'both_fail' SINGLETON = 'singleton' VSMANY_OUTPERFORMED = 'vsmany_outperformed' VSMANY_DOMINATES = 'vsmany_dominates' VSMANY_WINS = 'vsmany_wins' VSONE_WINS = 'vsone_wins' if 'testcases' not in incinfo: testcases = {} for case in [WASH, BOTH_FAIL, SINGLETON, VSMANY_OUTPERFORMED, VSMANY_DOMINATES, VSMANY_WINS, VSONE_WINS]: testcases[case] = [] incinfo['testcases'] = testcases testcases = incinfo['testcases'] def append_case(case, testtup): print('APPENDED NEW TESTCASE: case=%r' % (case,)) print('* testup = %r' % (testtup,)) print('* vuuid = %r' % (ibs_gt.get_annot_visual_uuids(testtup.qaid_t),)) if ut.get_argflag('--interupt-case') and case in [VSMANY_WINS, VSMANY_DOMINATES]: incinfo['interactive'] = True incinfo['use_oracle'] = False incinfo['STOP'] = True if ut.is_developer(): import plottool as pt # NOQA IPYTHON_COMMANDS = """ >>> %pylab qt4 >>> from ibeis.viz.interact import interact_matches # NOQA >>> #qres_vsmany = ut.search_stack_for_localvar('qres_vsmany') >>> ibs = ut.search_stack_for_localvar('ibs') >>> daids = ut.search_stack_for_localvar('daids') >>> qnid_t = ut.search_stack_for_localvar('qnid_t') >>> qres_vsone = ut.search_stack_for_localvar('qres_vsone') >>> all_nids_t = ut.search_stack_for_localvar('all_nids_t') >>> # Find index in daids of correct matches >>> cm = qres_vsone >>> correct_indices = np.where(np.array(all_nids_t) == qnid_t)[0] >>> correct_aids2 = ut.take(daids, correct_indices) >>> qaid = cm.qaid >>> aid = correct_aids2[0] >>> # Report visual uuid for inclusion or exclusion in script >>> print(ibs.get_annot_visual_uuids([qaid, aid])) >>> # Feature match things >>> print('cm.filtkey_list = %r' % (cm.filtkey_list,)) >>> fm = cm.aid2_fm[aid] >>> fs = cm.aid2_fs[aid] >>> fsv = cm.aid2_fsv[aid] >>> mx = 2 >>> qfx, dfx = fm[mx] >>> fsv_single = fsv[mx] >>> fs_single = fs[mx] >>> # check featweights >>> data_featweights = ibs.get_annot_fgweights([aid])[0] >>> data_featweights[dfx] >>> fnum = pt.next_fnum() >>> bad_aid = cm.get_top_aids()[0] >>> #match_interaction_good = interact_matches.MatchInteraction(ibs, cm, aid, annot_mode=1) >>> #match_interaction_bad = interact_matches.MatchInteraction(ibs, cm, bad_aid) >>> match_interaction_good = cm.ishow_matches(ibs, aid, annot_mode=1, fnum=1) >>> match_interaction_bad = cm.ishow_matches(ibs, bad_aid, annot_mode=1, fnum=2) >>> match_interaction = match_interaction_good >>> self = match_interaction >>> self.select_ith_match(mx) >>> #impossible_to_match = len(correct_indices) > 0 """ y = """ >>> from os.path import exists >>> import vtool as vt >>> import vtool.patch as vtpatch >>> import vtool.image as vtimage # NOQA >>> chip_list = ibs.get_annot_chips([aid]) >>> kpts_list = ibs.get_annot_kpts([aid]) >>> probchip_fpath_list = ibs.get_probchip_fpath(aid) >>> probchip_list = [vt.imread(fpath, grayscale=True) if exists(fpath) else None for fpath in probchip_fpath_list] >>> kpts = kpts_list[0] >>> probchip = probchip_list[0] >>> kp = kpts[dfx] >>> patch = vt.get_warped_patch(probchip, kp)[0].astype(np.float32) / 255.0 >>> fnum2 = pt.next_fnum() >>> pt.figure(fnum2, pnum=(1, 2, 1), doclf=True, docla=True) >>> pt.imshow(probchip) >>> pt.draw_kpts2([kp]) >>> pt.figure(fnum2, pnum=(1, 2, 2)) >>> pt.imshow(patch * 255) >>> pt.update() >>> vt.gaussian_average_patch(patch) >>> cm.ishow_top(ibs, annot_mode=1) """ y ut.set_clipboard(IPYTHON_COMMANDS) #ut.spawn_delayed_ipython_paste() ut.embed(remove_pyqt_hook=False) IPYTHON_COMMANDS testcases[case].append(testtup) for qaid in six.iterkeys(qaid2_qres_vsmany): qres_vsmany = qaid2_qres_vsmany[qaid] qres_vsone = qaid2_qres_vsone[qaid] nscoretup_vsone = qres_vsone.get_nscoretup() nscoretup_vsmany = qres_vsmany.get_nscoretup() metatup = incinfo['metatup'] ibs_gt, aid1_to_aid2 = metatup aid2_to_aid1 = ut.invert_dict(aid1_to_aid2) top_aids_vsone = ut.get_list_column(nscoretup_vsone.sorted_aids, 0) top_aids_vsmany = ut.get_list_column(nscoretup_vsmany.sorted_aids, 0) # tranform to groundtruth database coordinates all_daids_t = ut.dict_take_list(aid2_to_aid1, daids) top_aids_vsone_t = ut.dict_take_list(aid2_to_aid1, top_aids_vsone) top_aids_vsmany_t = ut.dict_take_list(aid2_to_aid1, top_aids_vsmany) qaid_t = aid2_to_aid1[qaid] aids_tup = (all_daids_t, top_aids_vsone_t, top_aids_vsmany_t, (qaid_t,),) nids_tup = ibs_gt.unflat_map(ibs_gt.get_annot_nids, aids_tup) (all_nids_t, top_nids_vsone_t, top_nids_vsmany_t, (qnid_t,),) = nids_tup vsmany_rank = ut.listfind(top_nids_vsmany_t, qnid_t) vsone_rank = ut.listfind(top_nids_vsone_t, qnid_t) impossible_to_match = ut.listfind(all_nids_t, qnid_t) is None # Sort the test case into a category testtup = TestTup(qaid_t, qaid, vsmany_rank, vsone_rank) if vsmany_rank is None and vsone_rank is None and impossible_to_match: append_case(SINGLETON, testtup) elif vsmany_rank is not None and vsone_rank is None: if vsmany_rank < 5: append_case(VSMANY_DOMINATES, testtup) else: append_case(VSMANY_OUTPERFORMED, testtup) elif vsmany_rank is None: append_case(BOTH_FAIL, testtup) elif vsone_rank > vsmany_rank: append_case(VSMANY_WINS, testtup) elif vsone_rank < vsmany_rank: append_case(VSONE_WINS, testtup) elif vsone_rank == vsmany_rank: append_case(WASH, testtup) else: raise AssertionError('unenumerated case') count_dict = ut.count_dict_vals(testcases) print('+--') #print(ut.dict_str(testcases)) print('---') print(ut.dict_str(count_dict)) print('L__')
( 2, QUAL_POOR, ), # oops forgot 1. will be mapped to poor ( 0, QUAL_JUNK, ), ( -1, QUAL_UNKNOWN, ), ]) QUALITY_TEXT_TO_INT = ut.invert_dict(QUALITY_INT_TO_TEXT) QUALITY_INT_TO_TEXT[1] = QUAL_JUNK # QUALITY_TEXT_TO_INTS = ut.invert_dict(QUALITY_INT_TO_TEXT) QUALITY_TEXT_TO_INTS = ut.group_items(list(QUALITY_INT_TO_TEXT.keys()), list(QUALITY_INT_TO_TEXT.values())) QUALITY_TEXT_TO_INTS[QUAL_UNKNOWN] = -1 QUALITY_INT_TO_TEXT[None] = QUALITY_INT_TO_TEXT[-1] SEX_INT_TO_TEXT = { None: 'UNKNOWN NAME', -1: 'UNKNOWN SEX', 0: 'Female', 1: 'Male', 2: 'INDETERMINATE SEX', } SEX_TEXT_TO_INT = ut.invert_dict(SEX_INT_TO_TEXT)
y ut.set_clipboard(IPYTHON_COMMANDS) #ut.spawn_delayed_ipython_paste() ut.embed(remove_pyqt_hook=False) IPYTHON_COMMANDS testcases[case].append(testtup) for qaid in six.iterkeys(qaid2_qres_vsmany): qres_vsmany = qaid2_qres_vsmany[qaid] qres_vsone = qaid2_qres_vsone[qaid] nscoretup_vsone = qres_vsone.get_nscoretup() nscoretup_vsmany = qres_vsmany.get_nscoretup() metatup = incinfo['metatup'] ibs_gt, aid1_to_aid2 = metatup aid2_to_aid1 = ut.invert_dict(aid1_to_aid2) top_aids_vsone = ut.get_list_column(nscoretup_vsone.sorted_aids, 0) top_aids_vsmany = ut.get_list_column(nscoretup_vsmany.sorted_aids, 0) # tranform to groundtruth database coordinates all_daids_t = ut.dict_take_list(aid2_to_aid1, daids) top_aids_vsone_t = ut.dict_take_list(aid2_to_aid1, top_aids_vsone) top_aids_vsmany_t = ut.dict_take_list(aid2_to_aid1, top_aids_vsmany) qaid_t = aid2_to_aid1[qaid] aids_tup = ( all_daids_t, top_aids_vsone_t, top_aids_vsmany_t, (qaid_t, ), )
def check_results(ibs_gt, ibs2, aid1_to_aid2, aids_list1_, incinfo): """ reports how well the incremental query ran when the oracle was calling the shots. """ print('--------- CHECKING RESULTS ------------') testcases = incinfo.get('testcases') if testcases is not None: count_dict = ut.count_dict_vals(testcases) print('+--') #print(ut.dict_str(testcases)) print('---') print(ut.dict_str(count_dict)) print('L__') # TODO: dont include initially added aids in the result reporting aid_list1 = aids_list1_ # ibs_gt.get_valid_aids() #aid_list1 = ibs_gt.get_aids_with_groundtruth() aid_list2 = ibs2.get_valid_aids() nid_list1 = ibs_gt.get_annot_nids(aid_list1) nid_list2 = ibs2.get_annot_nids(aid_list2) # Group annotations from test and gt database by their respective names grouped_dict1 = ut.group_items(aid_list1, nid_list1) grouped_dict2 = ut.group_items(aid_list2, nid_list2) grouped_aids1 = list(six.itervalues(grouped_dict1)) grouped_aids2 = list(map(tuple, six.itervalues(grouped_dict2))) #group_nids1 = list(six.iterkeys(grouped_dict1)) #group_nids2 = list(six.iterkeys(grouped_dict2)) # Transform annotation ids from database1 space to database2 space grouped_aids1_t = [tuple(ut.dict_take_list(aid1_to_aid2, aids1)) for aids1 in grouped_aids1] set_grouped_aids1_t = set(grouped_aids1_t) set_grouped_aids2 = set(grouped_aids2) # Find names we got right. (correct groupings of annotations) # these are the annotation groups that are intersecting between # the test database and groundtruth database perfect_groups = set_grouped_aids2.intersection(set_grouped_aids1_t) # Find names we got wrong. (incorrect groupings of annotations) # The test database sets that were not perfect nonperfect_groups = set_grouped_aids2.difference(perfect_groups) # What we should have got # The ground truth database sets that were not fully identified missed_groups = set_grouped_aids1_t.difference(perfect_groups) # Mark non perfect groups by their error type false_negative_groups = [] # failed to link enough false_positive_groups = [] # linked too much for nonperfect_group in nonperfect_groups: if ut.is_subset_of_any(nonperfect_group, missed_groups): false_negative_groups.append(nonperfect_group) else: false_positive_groups.append(nonperfect_group) # Get some more info on the nonperfect groups # find which groups should have been linked aid2_to_aid1 = ut.invert_dict(aid1_to_aid2) false_negative_groups_t = [tuple(ut.dict_take_list(aid2_to_aid1, aids2)) for aids2 in false_negative_groups] false_negative_group_nids_t = ibs_gt.unflat_map(ibs_gt.get_annot_nids, false_negative_groups_t) assert all(map(ut.allsame, false_negative_group_nids_t)), 'inconsistent nids' false_negative_group_nid_t = ut.get_list_column(false_negative_group_nids_t, 0) # These are the links that should have been made missed_links = ut.group_items(false_negative_groups, false_negative_group_nid_t) print(ut.dict_str(missed_links)) print('# Name with failed links (FN) = %r' % len(false_negative_groups)) print('... should have reduced to %d names.' % (len(missed_links))) print('# Name with wrong links (FP) = %r' % len(false_positive_groups)) print('# Name correct names (TP) = %r' % len(perfect_groups))
def initialize_graph_and_model(infr): """ Unused in internal split stuff pt.qt4ensure() layout_info = pt.show_nx(graph, as_directed=False, fnum=1, layoutkw=dict(prog='neato'), use_image=True, verbose=0) ax = pt.gca() pt.zoom_factory() pt.interactions.PanEvents() """ #import networkx as nx #import itertools cm_list = infr.cm_list hack = True hack = False if hack: cm_list = cm_list[:10] qaid_list = [cm.qaid for cm in cm_list] daids_list = [cm.daid_list for cm in cm_list] unique_aids = sorted(ut.list_union(*daids_list + [qaid_list])) if hack: unique_aids = sorted(ut.isect(unique_aids, qaid_list)) aid2_aidx = ut.make_index_lookup(unique_aids) # Construct K-broken graph edges = [] edge_weights = [] #top = (infr.qreq_.qparams.K + 1) * 2 #top = (infr.qreq_.qparams.K) * 2 top = (infr.qreq_.qparams.K + 2) for count, cm in enumerate(cm_list): qidx = aid2_aidx[cm.qaid] score_list = cm.annot_score_list sortx = ut.argsort(score_list)[::-1] score_list = ut.take(score_list, sortx)[:top] daid_list = ut.take(cm.daid_list, sortx)[:top] for score, daid in zip(score_list, daid_list): if daid not in qaid_list: continue didx = aid2_aidx[daid] edge_weights.append(score) edges.append((qidx, didx)) # make symmetric directed_edges = dict(zip(edges, edge_weights)) # Find edges that point in both directions undirected_edges = {} for (u, v), w in directed_edges.items(): if (v, u) in undirected_edges: undirected_edges[(v, u)] += w undirected_edges[(v, u)] /= 2 else: undirected_edges[(u, v)] = w edges = list(undirected_edges.keys()) edge_weights = list(undirected_edges.values()) nodes = list(range(len(unique_aids))) nid_labeling = infr.qreq_.ibs.get_annot_nids(unique_aids) labeling = ut.rebase_labels(nid_labeling) import networkx as nx from ibeis.viz import viz_graph set_node_attrs = nx.set_node_attributes set_edge_attrs = nx.set_edge_attributes # Create match-based graph structure graph = nx.DiGraph() graph.add_nodes_from(nodes) graph.add_edges_from(edges) # Important properties nid_list = infr.qreq_.ibs.get_annot_nids(unique_aids) labeling = ut.rebase_labels(nid_list) set_node_attrs(graph, 'name_label', dict(zip(nodes, labeling))) set_edge_attrs(graph, 'weight', dict(zip(edges, edge_weights))) # Visualization properties import plottool as pt ax2_aid = ut.invert_dict(aid2_aidx) set_node_attrs(graph, 'aid', ax2_aid) viz_graph.ensure_node_images(infr.qreq_.ibs, graph) set_node_attrs(graph, 'framewidth', dict(zip(nodes, [3.0] * len(nodes)))) set_node_attrs(graph, 'framecolor', dict(zip(nodes, [pt.DARK_BLUE] * len(nodes)))) ut.color_nodes(graph, labelattr='name_label') edge_colors = pt.scores_to_color(np.array(edge_weights), cmap_='viridis') #import utool #utool.embed() #edge_colors = [pt.color_funcs.ensure_base255(color) for color in edge_colors] #print('edge_colors = %r' % (edge_colors,)) set_edge_attrs(graph, 'color', dict(zip(edges, edge_colors))) # Build inference model from ibeis.algo.hots import graph_iden #graph_iden.rrr() model = graph_iden.InfrModel(graph) #model = graph_iden.InfrModel(len(nodes), edges, edge_weights, labeling=labeling) infr.model = model
def check_results(ibs_gt, ibs2, aid1_to_aid2, aids_list1_, incinfo): """ reports how well the incremental query ran when the oracle was calling the shots. """ print('--------- CHECKING RESULTS ------------') testcases = incinfo.get('testcases') if testcases is not None: count_dict = ut.count_dict_vals(testcases) print('+--') #print(ut.dict_str(testcases)) print('---') print(ut.dict_str(count_dict)) print('L__') # TODO: dont include initially added aids in the result reporting aid_list1 = aids_list1_ # ibs_gt.get_valid_aids() #aid_list1 = ibs_gt.get_aids_with_groundtruth() aid_list2 = ibs2.get_valid_aids() nid_list1 = ibs_gt.get_annot_nids(aid_list1) nid_list2 = ibs2.get_annot_nids(aid_list2) # Group annotations from test and gt database by their respective names grouped_dict1 = ut.group_items(aid_list1, nid_list1) grouped_dict2 = ut.group_items(aid_list2, nid_list2) grouped_aids1 = list(six.itervalues(grouped_dict1)) grouped_aids2 = list(map(tuple, six.itervalues(grouped_dict2))) #group_nids1 = list(six.iterkeys(grouped_dict1)) #group_nids2 = list(six.iterkeys(grouped_dict2)) # Transform annotation ids from database1 space to database2 space grouped_aids1_t = [ tuple(ut.dict_take_list(aid1_to_aid2, aids1)) for aids1 in grouped_aids1 ] set_grouped_aids1_t = set(grouped_aids1_t) set_grouped_aids2 = set(grouped_aids2) # Find names we got right. (correct groupings of annotations) # these are the annotation groups that are intersecting between # the test database and groundtruth database perfect_groups = set_grouped_aids2.intersection(set_grouped_aids1_t) # Find names we got wrong. (incorrect groupings of annotations) # The test database sets that were not perfect nonperfect_groups = set_grouped_aids2.difference(perfect_groups) # What we should have got # The ground truth database sets that were not fully identified missed_groups = set_grouped_aids1_t.difference(perfect_groups) # Mark non perfect groups by their error type false_negative_groups = [] # failed to link enough false_positive_groups = [] # linked too much for nonperfect_group in nonperfect_groups: if ut.is_subset_of_any(nonperfect_group, missed_groups): false_negative_groups.append(nonperfect_group) else: false_positive_groups.append(nonperfect_group) # Get some more info on the nonperfect groups # find which groups should have been linked aid2_to_aid1 = ut.invert_dict(aid1_to_aid2) false_negative_groups_t = [ tuple(ut.dict_take_list(aid2_to_aid1, aids2)) for aids2 in false_negative_groups ] false_negative_group_nids_t = ibs_gt.unflat_map(ibs_gt.get_annot_nids, false_negative_groups_t) assert all(map(ut.allsame, false_negative_group_nids_t)), 'inconsistent nids' false_negative_group_nid_t = ut.get_list_column( false_negative_group_nids_t, 0) # These are the links that should have been made missed_links = ut.group_items(false_negative_groups, false_negative_group_nid_t) print(ut.dict_str(missed_links)) print('# Name with failed links (FN) = %r' % len(false_negative_groups)) print('... should have reduced to %d names.' % (len(missed_links))) print('# Name with wrong links (FP) = %r' % len(false_positive_groups)) print('# Name correct names (TP) = %r' % len(perfect_groups))