# -*- coding: utf-8 -*-
"""
This module was never really finished. It is used in some cases
to display the results from a query in a qt window. It needs
some work if its to be re-integrated.
TODO:
Refresh name table on inspect gui close
"""
from __future__ import absolute_import, division, print_function, unicode_literals
from functools import partial
from guitool import (qtype, APIItemWidget, APIItemModel, FilterProxyModel,
ChangeLayoutContext)
from guitool.__PYQT__ import QtGui, QtCore
from ibeis.other import ibsfuncs
#from ibeis.viz import interact
from ibeis.viz import viz_helpers as vh
#from ibeis.algo.hots import chip_match
from plottool import fig_presenter
#from plottool import interact_helpers as ih
#import functools
import guitool
import numpy as np
import six
import utool
#from ibeis import constants as const
import utool as ut
from ibeis.gui import guiexcept
(print, rrr, profile) = utool.inject2(__name__, '[inspect_gui]')
MATCHED_STATUS_TEXT = 'Matched'
REVIEWED_STATUS_TEXT = 'Reviewed'
USE_FILTER_PROXY = False
[docs]class CustomFilterModel(FilterProxyModel):
def __init__(model, headers=None, parent=None, *args):
FilterProxyModel.__init__(model, parent=parent, *args)
model.ibswin = parent
model.imgsetid = -1 # negative one is an invalid imgsetid # seems unused
model.original_ider = None
model.sourcemodel = APIItemModel(parent=parent)
model.setSourceModel(model.sourcemodel)
print('[ibs_model] just set the sourcemodel')
def _update_headers(model, **headers):
def _null_ider(**kwargs):
return []
model.original_iders = headers.get('iders', [_null_ider])
if len(model.original_iders) > 0:
model.new_iders = model.original_iders[:]
model.new_iders[0] = model._ider
headers['iders'] = model.new_iders
model.sourcemodel._update_headers(**headers)
def _ider(model):
""" Overrides the API model ider to give only selected imageset ids """
return model.original_iders[0]()
def _change_imageset(model, imgsetid):
model.imgsetid = imgsetid
# seems unused
with ChangeLayoutContext([model]):
FilterProxyModel._update_rows(model)
[docs]def get_aidpair_from_qtindex(qres_wgt, qtindex):
model = qtindex.model()
qaid = model.get_header_data('qaid', qtindex)
daid = model.get_header_data('aid', qtindex)
return qaid, daid
[docs]def get_annotmatch_rowid_from_qtindex(qres_wgt, qtindex):
qaid, daid = get_aidpair_from_qtindex(qres_wgt, qtindex)
ibs = qres_wgt.ibs
annotmatch_rowid_list = ibs.add_annotmatch([qaid], [daid])
return annotmatch_rowid_list
[docs]def show_match_at_qtindex(qres_wgt, qtindex):
print('interact')
qaid, daid = get_aidpair_from_qtindex(qres_wgt, qtindex)
cm = qres_wgt.qaid2_cm[qaid]
match_interaction = cm.ishow_single_annotmatch(
qres_wgt.qreq_, daid, mode=0)
fig = match_interaction.fig
fig_presenter.bring_to_front(fig)
[docs]def review_match_at_qtindex(qres_wgt, qtindex):
print('review')
#qres_callback = partial(show_match_at_qtindex, qres_wgt, qtindex)
#ibsfuncs.assert_valid_aids(ibs, [aid1, aid2])
#update_callback = model._update
#ibs = qres_wgt.ibs
#qreq_ = qres_wgt.qreq_
#cm = qres_wgt.qaid2_cm[qaid]
#update_callback = None # hack (checking if necessary)
#backend_callback = qres_wgt.callback
qaid, daid = get_aidpair_from_qtindex(qres_wgt, qtindex)
tup = get_widget_review_vars(qres_wgt, qaid)
ibs, cm, qreq_, update_callback, backend_callback = tup
review_match(ibs, qaid, daid, update_callback=update_callback,
backend_callback=backend_callback, cm=cm, qreq_=qreq_)
# ______
[docs]def set_annot_pair_as_positive_match_(ibs, aid1, aid2, cm, qreq_, **kwargs):
def on_nontrivial_merge(ibs, aid1, aid2):
MERGE_NEEDS_INTERACTION = False
MERGE_NEEDS_VERIFICATION = True
if MERGE_NEEDS_INTERACTION:
raise guiexcept.NeedsUserInput('confirm merge')
elif MERGE_NEEDS_VERIFICATION:
name1, name2 = ibs.get_annot_names([aid1, aid2])
aid1_and_groundtruth = ibs.get_annot_groundtruth(aid1, noself=False)
aid2_and_groundtruth = ibs.get_annot_groundtruth(aid2, noself=False)
msgfmt = ut.codeblock('''
Confirm merge of animal {name1} and {name2}
{name1} has {num_gt1} annotations
{name2} has {num_gt2} annotations
''')
msg = msgfmt.format(name1=name1, name2=name2,
num_gt1=len(aid1_and_groundtruth),
num_gt2=len(aid2_and_groundtruth),)
if not guitool.are_you_sure(parent=None, msg=msg, default='Yes'):
raise guiexcept.UserCancel('canceled merge')
try:
status = ibs.set_annot_pair_as_positive_match(
aid1, aid2, on_nontrivial_merge=on_nontrivial_merge)
print('status = %r' % (status,))
except guiexcept.NeedsUserInput:
review_match(ibs, aid1, aid2, qreq_=qreq_, cm=cm, **kwargs)
except guiexcept.UserCancel:
print('user canceled positive match')
[docs]def set_annot_pair_as_negative_match_(ibs, aid1, aid2, cm, qreq_, **kwargs):
def on_nontrivial_split(ibs, aid1, aid2):
aid1_groundtruth = ibs.get_annot_groundtruth(aid1, noself=True)
print('There are %d annots in this name. Need more sophisticated split'
% (len(aid1_groundtruth)))
raise guiexcept.NeedsUserInput('non-trivial split')
try:
status = ibs.set_annot_pair_as_negative_match(
aid1, aid2, on_nontrivial_split=on_nontrivial_split)
print('status = %r' % (status,))
except guiexcept.NeedsUserInput:
review_match(ibs, aid1, aid2, qreq_=qreq_, cm=cm, **kwargs)
except guiexcept.UserCancel:
print('user canceled negative match')
[docs]def review_match(ibs, aid1, aid2, update_callback=None, backend_callback=None,
qreq_=None, cm=None, **kwargs):
print('Review match: ' + ibsfuncs.vsstr(aid1, aid2))
from ibeis.viz.interact import interact_name
#ibsfuncs.assert_valid_aids(ibs, [aid1, aid2])
mvinteract = interact_name.MatchVerificationInteraction(
ibs, aid1, aid2, fnum=64, update_callback=update_callback,
cm=cm,
qreq_=qreq_,
backend_callback=backend_callback, **kwargs)
return mvinteract
#ih.register_interaction(mvinteract)
[docs]def get_match_status(ibs, aid_pair):
""" Data role for status column
FIXME: no other function in this project takes a tuple of scalars as an
argument. Everything else is written in the context of lists, This function
should follow the same paradigm, but CustomAPI will have to change.
"""
aid1, aid2 = aid_pair
assert not utool.isiterable(aid1), 'aid1=%r, aid2=%r' % (aid1, aid2)
assert not utool.isiterable(aid2), 'aid1=%r, aid2=%r' % (aid1, aid2)
#text = ibsfuncs.vsstr(aid1, aid2)
text = ibs.get_match_text(aid1, aid2)
if text is None:
raise AssertionError('impossible state inspect_gui')
return text
[docs]def get_reviewed_status(ibs, aid_pair):
""" Data role for status column
FIXME: no other function in this project takes a tuple of scalars as an
argument. Everything else is written in the context of lists, This function
should follow the same paradigm, but CustomAPI will have to change.
"""
aid1, aid2 = aid_pair
assert not utool.isiterable(aid1), 'aid1=%r, aid2=%r' % (aid1, aid2)
assert not utool.isiterable(aid2), 'aid1=%r, aid2=%r' % (aid1, aid2)
#text = ibsfuncs.vsstr(aid1, aid2)
annotmach_reviewed = ibs.get_annot_pair_is_reviewed([aid1], [aid2])[0]
return 'Yes' if annotmach_reviewed else 'No'
#text = ibs.get_match_text(aid1, aid2)
#if text is None:
# raise AssertionError('impossible state inspect_gui')
#return 'No'
[docs]def get_match_status_bgrole(ibs, aid_pair):
""" Background role for status column """
aid1, aid2 = aid_pair
truth = ibs.get_match_truth(aid1, aid2)
#print('get status bgrole: %r truth=%r' % (aid_pair, truth))
truth_color = vh.get_truth_color(truth, base255=True, lighten_amount=0.35)
return truth_color
[docs]def get_reviewed_status_bgrole(ibs, aid_pair):
""" Background role for status column """
aid1, aid2 = aid_pair
truth = ibs.get_match_truth(aid1, aid2)
annotmach_reviewed = ibs.get_annot_pair_is_reviewed([aid1], [aid2])[0]
#truth = ibs.get_annot_pair_truth([aid1], [aid2])[0]
#print('get status bgrole: %r truth=%r' % (aid_pair, truth))
lighten_amount = .35 if annotmach_reviewed else .9
truth_color = vh.get_truth_color(truth, base255=True,
lighten_amount=lighten_amount)
#truth = ibs.get_match_truth(aid1, aid2)
#print('get status bgrole: %r truth=%r' % (aid_pair, truth))
#truth_color = vh.get_truth_color(truth, base255=True, lighten_amount=0.35)
return truth_color
[docs]def test_inspect_matches(ibs, qaid_list, daid_list):
"""
Args:
ibs (IBEISController):
qaid_list (list): query annotation id list
daid_list (list): database annotation id list
Returns:
dict: locals_
CommandLine:
python -m ibeis.gui.inspect_gui --test-test_inspect_matches --show
python -m ibeis.gui.inspect_gui --test-test_inspect_matches --show --nodelete
python -m ibeis.gui.inspect_gui --test-test_inspect_matches --cmd
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> import guitool
>>> ibs = ibeis.opendb(db='PZ_MTEST')
>>> assert ibs.dbname == 'PZ_MTEST', 'do not use on a real database'
>>> qaid_list = ibs.get_valid_aids()[0:5]
>>> daid_list = ibs.get_valid_aids()[0:20]
>>> if not ut.get_argflag('--nodelete'):
>>> ibs.delete_annotmatch(ibs._get_all_annotmatch_rowids())
>>> main_locals = test_inspect_matches(ibs, qaid_list, daid_list)
>>> main_execstr = ibeis.main_loop(main_locals)
>>> ut.quit_if_noshow()
>>> # TODO: add in qwin to main loop
>>> guitool.qtapp_loop(qwin=main_locals['qres_wgt'])
>>> print(main_execstr)
>>> exec(main_execstr)
"""
from ibeis.gui import inspect_gui
qreq_ = ibs.new_query_request(qaid_list, daid_list, cfgdict={'augment_queryside_hack': True})
cm_list = qreq_.execute()
tblname = ''
name_scoring = False
ranks_lt = 5
# This is where you create the result widigt
guitool.ensure_qapp()
print('[inspect_matches] make_qres_widget')
#ut.view_directory(ibs.get_match_thumbdir())
qres_wgt = inspect_gui.QueryResultsWidget(
ibs, cm_list, ranks_lt=ranks_lt, qreq_=qreq_, filter_reviewed=False,
filter_duplicate_namepair_matches=True)
print('[inspect_matches] show')
qres_wgt.show()
print('[inspect_matches] raise')
qres_wgt.raise_()
print('</inspect_matches>')
# simulate double click
#qres_wgt._on_click(qres_wgt.model.index(2, 2))
#qres_wgt._on_doubleclick(qres_wgt.model.index(2, 0))
locals_ = locals()
return locals_
[docs]def get_match_thumb_fname(cm, daid, qreq_):
"""
CommandLine:
python -m ibeis.gui.inspect_gui --exec-get_match_thumb_fname
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> cm, qreq_ = ibeis.testdata_cm('PZ_MTEST')
>>> thumbsize = (128, 128)
>>> daid = cm.get_top_aids()[0]
>>> match_thumb_fname = get_match_thumb_fname(cm, daid, qreq_)
>>> result = match_thumb_fname
>>> print(result)
match_aids=1,1_cfgstr=ubpzwu5k54h6xbnr.jpg
"""
# Make thumbnail name
config_hash = ut.hashstr27(qreq_.get_cfgstr())
qaid = cm.qaid
match_thumb_fname = 'match_aids=%d,%d_cfgstr=%s.jpg' % ((qaid, daid,
config_hash))
return match_thumb_fname
[docs]def ensure_match_img(ibs, cm, daid, qreq_=None, match_thumbtup_cache={}):
r"""
CommandLine:
python -m ibeis.gui.inspect_gui --test-ensure_match_img --show
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> # build test data
>>> cm, qreq_ = ibeis.testdata_cm()
>>> daid = cm.get_top_aids()[0]
>>> match_thumbtup_cache = {}
>>> # execute function
>>> match_thumb_fpath_ = ensure_match_img(qreq_.ibs, cm, daid, qreq_, match_thumbtup_cache)
>>> # verify results
>>> result = str(match_thumb_fpath_)
>>> print(result)
>>> ut.quit_if_noshow()
>>> ut.startfile(match_thumb_fpath_, quote=True)
"""
#from os.path import exists
match_thumbdir = ibs.get_match_thumbdir()
match_thumb_fname = get_match_thumb_fname(cm, daid, qreq_)
match_thumb_fpath_ = ut.unixjoin(match_thumbdir, match_thumb_fname)
#if exists(match_thumb_fpath_):
# return match_thumb_fpath_
if match_thumb_fpath_ in match_thumbtup_cache:
fpath = match_thumbtup_cache[match_thumb_fpath_]
else:
# TODO: just draw the image at the correct thumbnail size
# TODO: draw without matplotlib?
fpath = cm.imwrite_single_annotmatch(
qreq_, daid, fpath=match_thumb_fpath_, saveax=True, fnum=32,
notitle=True, verbose=False)
match_thumbtup_cache[match_thumb_fpath_] = fpath
return fpath
[docs]def make_qres_api(ibs, cm_list, ranks_lt=None, name_scoring=False,
filter_reviewed=False,
filter_duplicate_namepair_matches=False,
qreq_=None,
):
"""
Builds columns which are displayable in a ColumnListTableWidget
CommandLine:
python -m ibeis.gui.inspect_gui --test-test_inspect_matches --show
python -m ibeis.gui.inspect_gui --test-make_qres_api
Example:
>>> # ENABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> import guitool
>>> from ibeis.gui import inspect_gui
>>> cm_list, qreq_ = ibeis.main_helpers.testdata_cmlist()
>>> tblname = 'chipmatch'
>>> name_scoring = False
>>> ranks_lt = 5
>>> qres_api = make_qres_api(qreq_.ibs, cm_list, ranks_lt, name_scoring, qreq_=qreq_)
>>> print('qres_api = %r' % (qres_api,))
"""
if ut.VERBOSE:
print('[inspect] make_qres_api')
#ibs.cfg.other_cfg.ranks_lt = 2
# Overwrite
#ranks_lt_ = ibs.cfg.other_cfg.ensure_attr('ranks_lt', 2)
#filter_reviewed = ibs.cfg.other_cfg.ensure_attr('filter_reviewed', True)
#if filter_reviewed is None:
# # only filter big queries if not specified
# filter_reviewed = len(cm_list) > 6
#ranks_lt = ranks_lt if ranks_lt is not None else ranks_lt_
candidate_matches = get_automatch_candidates(
cm_list, ranks_lt=ranks_lt, name_scoring=name_scoring, ibs=ibs,
directed=False, filter_reviewed=filter_reviewed,
filter_duplicate_namepair_matches=filter_duplicate_namepair_matches
)
# Get extra info
(qaids, daids, scores, ranks) = candidate_matches
RES_THUMB_TEXT = 'ResThumb'
MATCH_THUMB_TEXT = 'MatchThumb'
col_name_list = [
'result_index',
'score',
REVIEWED_STATUS_TEXT,
MATCHED_STATUS_TEXT,
'querythumb',
RES_THUMB_TEXT,
'qname',
'name',
'rank',
'qaid',
'aid',
]
col_types_dict = dict([
('qaid', int),
('aid', int),
#('d_nGt', int),
#('q_nGt', int),
#('review', 'BUTTON'),
(MATCHED_STATUS_TEXT, str),
(REVIEWED_STATUS_TEXT, str),
('querythumb', 'PIXMAP'),
(RES_THUMB_TEXT, 'PIXMAP'),
('qname', str),
('name', str),
('score', float),
('rank', int),
('truth', bool),
('opt', int),
('result_index', int),
])
col_getter_dict = dict([
('qaid', np.array(qaids)),
('aid', np.array(daids)),
#('d_nGt', ibs.get_annot_num_groundtruth),
#('q_nGt', ibs.get_annot_num_groundtruth),
#('review', lambda rowid: get_buttontup),
(MATCHED_STATUS_TEXT, partial(get_match_status, ibs)),
(REVIEWED_STATUS_TEXT, partial(get_reviewed_status, ibs)),
('querythumb', ibs.get_annot_chip_thumbtup),
(RES_THUMB_TEXT, ibs.get_annot_chip_thumbtup),
('qname', ibs.get_annot_names),
('name', ibs.get_annot_names),
('score', np.array(scores)),
('rank', np.array(ranks)),
('result_index', np.arange(len(ranks))),
#('truth', truths),
#('opt', opts),
])
# default is 100
col_width_dict = {
'score': 75,
REVIEWED_STATUS_TEXT: 75,
MATCHED_STATUS_TEXT: 75,
'rank': 42,
'qaid': 42,
'aid': 42,
'result_index': 42,
'qname': 60,
'name': 60,
}
USE_MATCH_THUMBS = True
if USE_MATCH_THUMBS:
def get_match_thumbtup(ibs, qaid2_cm, qaids, daids, index, qreq_=None,
thumbsize=(128, 128), match_thumbtup_cache={}):
daid = daids[index]
qaid = qaids[index]
cm = qaid2_cm[qaid]
assert cm.qaid == qaid, 'aids do not aggree'
#cm = cm_list[qaid]
fpath = ensure_match_img(ibs, cm, daid, qreq_=qreq_,
match_thumbtup_cache=match_thumbtup_cache)
if isinstance(thumbsize, int):
thumbsize = (thumbsize, thumbsize)
thumbtup = (ut.augpath(fpath, 'thumb_%d,%d' % thumbsize), fpath, thumbsize,
[], [])
return thumbtup
col_name_list.insert(col_name_list.index(RES_THUMB_TEXT) + 1,
MATCH_THUMB_TEXT)
col_types_dict[MATCH_THUMB_TEXT] = 'PIXMAP'
qaid2_cm = {cm.qaid: cm for cm in cm_list}
get_match_thumbtup_ = partial(get_match_thumbtup, ibs, qaid2_cm,
qaids, daids, qreq_=qreq_,
match_thumbtup_cache={})
col_getter_dict[MATCH_THUMB_TEXT] = get_match_thumbtup_
col_bgrole_dict = {
MATCHED_STATUS_TEXT : partial(get_match_status_bgrole, ibs),
REVIEWED_STATUS_TEXT: partial(get_reviewed_status_bgrole, ibs),
}
# TODO: remove ider dict.
# it is massively unuseful
col_ider_dict = {
MATCHED_STATUS_TEXT : ('qaid', 'aid'),
REVIEWED_STATUS_TEXT : ('qaid', 'aid'),
#'d_nGt' : ('aid'),
#'q_nGt' : ('qaid'),
'querythumb' : ('qaid'),
'ResThumb' : ('aid'),
'qname' : ('qaid'),
'name' : ('aid'),
}
col_setter_dict = {
'qname': ibs.set_annot_names,
'name': ibs.set_annot_names
}
editable_colnames = ['truth', 'notes', 'qname', 'name', 'opt']
USE_BOOLS = False
if USE_BOOLS:
# DEPRICATED use tag funcs
boolean_annotmatch_columns = [
'is_hard',
'is_nondistinct',
'is_scenerymatch',
'is_photobomb',
]
def make_annotmatch_boolean_getter_wrapper(ibs, colname):
colname_getter = getattr(ibs, 'get_annotmatch_' + colname)
def getter_wrapper(aidpair):
qaid, daid = aidpair
annotmatch_rowid_list = ibs.add_annotmatch([qaid], [daid])
value_list = colname_getter(annotmatch_rowid_list)
value = value_list[0]
return value if value is not None else False
ut.set_funcname(getter_wrapper, 'getter_wrapper_' + colname)
return getter_wrapper
def make_annotmatch_boolean_setter_wrapper(ibs, colname):
colname_setter = getattr(ibs, 'set_annotmatch_' + colname)
def setter_wrapper(aidpair, value):
qaid, daid = aidpair
annotmatch_rowid_list = ibs.add_annotmatch([qaid], [daid])
value_list = [value]
return colname_setter(annotmatch_rowid_list, value_list)
ut.set_funcname(setter_wrapper, 'setter_wrapper_' + colname)
return setter_wrapper
for colname in boolean_annotmatch_columns:
#annotmatch_rowid_list = ibs.add_annotmatch(qaids, daids)
#col_name_list.append(colname)
col_name_list.insert(col_name_list.index('qname'), colname)
#rank
#col_ider_dict[colname] = annotmatch_rowid_list
col_ider_dict[colname] = ('qaid', 'aid')
col_types_dict[colname] = bool
col_getter_dict[colname] = make_annotmatch_boolean_getter_wrapper(
ibs, colname)
col_setter_dict[colname] = make_annotmatch_boolean_setter_wrapper(
ibs, colname)
col_width_dict[colname] = 70
editable_colnames.append(colname)
sortby = 'score'
def get_thumb_size():
return ibs.cfg.other_cfg.thumb_size
# Insert info into dict
qres_api = guitool.CustomAPI(col_name_list, col_types_dict,
col_getter_dict, col_bgrole_dict,
col_ider_dict, col_setter_dict,
editable_colnames, sortby, get_thumb_size,
True, col_width_dict)
return qres_api
[docs]def launch_review_matches_interface(ibs, cm_list, dodraw=False, filter_reviewed=False):
""" TODO: move to a more general function """
from ibeis.gui import inspect_gui
import guitool
guitool.ensure_qapp()
#backend_callback = back.front.update_tables
backend_callback = None
qres_wgt = inspect_gui.QueryResultsWidget(ibs, cm_list,
callback=backend_callback,
filter_reviewed=filter_reviewed)
if dodraw:
qres_wgt.show()
qres_wgt.raise_()
return qres_wgt
@profile
[docs]def get_automatch_candidates(cm_list, ranks_lt=5, directed=True,
name_scoring=False, ibs=None, filter_reviewed=False,
filter_duplicate_namepair_matches=False):
"""
Needs to be moved to a better file. Maybe something to do with
identification.
Returns a list of matches that should be inspected
This function is more lightweight than orgres or allres.
Used in inspect_gui and interact_qres2
Args:
cm_list (list): list of chip match objects
ranks_lt (int): put all ranks less than this number into the graph
directed (bool):
Returns:
tuple: candidate_matches = (qaid_arr, daid_arr, score_arr, rank_arr)
CommandLine:
python -m ibeis.expt.results_organizer --test-get_automatch_candidates:2
python -m ibeis.expt.results_organizer --test-get_automatch_candidates:0
Example0:
>>> # ENABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb('PZ_MTEST')
>>> qreq_ = ibeis.main_helpers.testdata_qreq_()
>>> cm_list = qreq_.execute()
>>> ranks_lt = 5
>>> directed = True
>>> name_scoring = False
>>> candidate_matches = get_automatch_candidates(cm_list, ranks_lt, directed, ibs=ibs)
>>> print(candidate_matches)
Example1:
>>> # UNSTABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb('PZ_MTEST')
>>> qaid_list = ibs.get_valid_aids()[0:5]
>>> daid_list = ibs.get_valid_aids()[0:20]
>>> cm_list = ibs.query_chips(qaid_list, daid_list)
>>> ranks_lt = 5
>>> directed = False
>>> name_scoring = False
>>> filter_reviewed = False
>>> filter_duplicate_namepair_matches = True
>>> candidate_matches = get_automatch_candidates(
... cm_list, ranks_lt, directed, name_scoring=name_scoring,
... filter_reviewed=filter_reviewed,
... filter_duplicate_namepair_matches=filter_duplicate_namepair_matches,
... ibs=ibs)
>>> print(candidate_matches)
Example3:
>>> # UNSTABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb('PZ_MTEST')
>>> qaid_list = ibs.get_valid_aids()[0:1]
>>> daid_list = ibs.get_valid_aids()[10:100]
>>> qaid2_cm = ibs.query_chips(qaid_list, daid_list)
>>> ranks_lt = 1
>>> directed = False
>>> name_scoring = False
>>> filter_reviewed = False
>>> filter_duplicate_namepair_matches = True
>>> candidate_matches = get_automatch_candidates(
... cm_list, ranks_lt, directed, name_scoring=name_scoring,
... filter_reviewed=filter_reviewed,
... filter_duplicate_namepair_matches=filter_duplicate_namepair_matches,
... ibs=ibs)
>>> print(candidate_matches)
Example4:
>>> # UNSTABLE_DOCTEST
>>> from ibeis.gui.inspect_gui import * # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb('PZ_MTEST')
>>> qaid_list = ibs.get_valid_aids()[0:10]
>>> daid_list = ibs.get_valid_aids()[0:10]
>>> qres_list = ibs.query_chips(qaid_list, daid_list)
>>> ranks_lt = 3
>>> directed = False
>>> name_scoring = False
>>> filter_reviewed = False
>>> filter_duplicate_namepair_matches = True
>>> candidate_matches = get_automatch_candidates(
... qaid2_cm, ranks_lt, directed, name_scoring=name_scoring,
... filter_reviewed=filter_reviewed,
... filter_duplicate_namepair_matches=filter_duplicate_namepair_matches,
... ibs=ibs)
>>> print(candidate_matches)
"""
import vtool as vt
from ibeis.algo.hots import chip_match
print(('[resorg] get_automatch_candidates('
'filter_reviewed={filter_reviewed},'
'filter_duplicate_namepair_matches={filter_duplicate_namepair_matches},'
'directed={directed},'
'ranks_lt={ranks_lt},'
).format(**locals()))
print('[resorg] len(cm_list) = %d' % (len(cm_list)))
qaids_stack = []
daids_stack = []
ranks_stack = []
scores_stack = []
# For each QueryResult, Extract inspectable candidate matches
if isinstance(cm_list, dict):
cm_list = list(cm_list.values())
for cm in cm_list:
if isinstance(cm, chip_match.ChipMatch):
daids = cm.get_top_aids(ntop=ranks_lt)
scores = cm.get_top_scores(ntop=ranks_lt)
ranks = np.arange(len(daids))
qaids = np.full(daids.shape, cm.qaid, dtype=daids.dtype)
else:
(qaids, daids, scores, ranks) = cm.get_match_tbldata(
ranks_lt=ranks_lt, name_scoring=name_scoring, ibs=ibs)
qaids_stack.append(qaids)
daids_stack.append(daids)
scores_stack.append(scores)
ranks_stack.append(ranks)
# Stack them into a giant array
# utool.embed()
qaid_arr = np.hstack(qaids_stack)
daid_arr = np.hstack(daids_stack)
score_arr = np.hstack(scores_stack)
rank_arr = np.hstack(ranks_stack)
# Sort by scores
sortx = score_arr.argsort()[::-1]
qaid_arr = qaid_arr[sortx]
daid_arr = daid_arr[sortx]
score_arr = score_arr[sortx]
rank_arr = rank_arr[sortx]
if filter_reviewed:
_is_reviewed = ibs.get_annot_pair_is_reviewed(qaid_arr.tolist(), daid_arr.tolist())
is_unreviewed = ~np.array(_is_reviewed, dtype=np.bool)
qaid_arr = qaid_arr.compress(is_unreviewed)
daid_arr = daid_arr.compress(is_unreviewed)
score_arr = score_arr.compress(is_unreviewed)
rank_arr = rank_arr.compress(is_unreviewed)
# Remove directed edges
if not directed:
#nodes = np.unique(directed_edges.flatten())
directed_edges = np.vstack((qaid_arr, daid_arr)).T
#idx1, idx2 = vt.intersect2d_indices(directed_edges, directed_edges[:, ::-1])
unique_rowx = vt.find_best_undirected_edge_indexes(directed_edges, score_arr)
qaid_arr = qaid_arr.take(unique_rowx)
daid_arr = daid_arr.take(unique_rowx)
score_arr = score_arr.take(unique_rowx)
rank_arr = rank_arr.take(unique_rowx)
# Filter Double Name Matches
if filter_duplicate_namepair_matches:
qnid_arr = ibs.get_annot_nids(qaid_arr)
dnid_arr = ibs.get_annot_nids(daid_arr)
if not directed:
directed_name_edges = np.vstack((qnid_arr, dnid_arr)).T
unique_rowx2 = vt.find_best_undirected_edge_indexes(directed_name_edges, score_arr)
else:
namepair_id_list = np.array(vt.compute_unique_data_ids_(list(zip(qnid_arr, dnid_arr))))
unique_namepair_ids, namepair_groupxs = vt.group_indices(namepair_id_list)
score_namepair_groups = vt.apply_grouping(score_arr, namepair_groupxs)
unique_rowx2 = np.array(sorted([
groupx[score_group.argmax()]
for groupx, score_group in zip(namepair_groupxs, score_namepair_groups)
]), dtype=np.int32)
qaid_arr = qaid_arr.take(unique_rowx2)
daid_arr = daid_arr.take(unique_rowx2)
score_arr = score_arr.take(unique_rowx2)
rank_arr = rank_arr.take(unique_rowx2)
candidate_matches = (qaid_arr, daid_arr, score_arr, rank_arr)
return candidate_matches
if __name__ == '__main__':
"""
CommandLine:
python -m ibeis.gui.inspect_gui --test-test_inspect_matches --show
python -m ibeis.gui.inspect_gui --test-test_inspect_matches --show
python -m ibeis.gui.inspect_gui
python -m ibeis.gui.inspect_gui --allexamples
python -m ibeis.gui.inspect_gui --allexamples --noface --nosrc
"""
import multiprocessing
multiprocessing.freeze_support() # for win32
import utool as ut # NOQA
ut.doctest_funcs()