# -*- coding: utf-8 -*-
"""
Interaction for a single annoation.
Also defines annotation context menu.
CommandLine:
python -m ibeis.viz.interact.interact_chip --test-ishow_chip --show --aid 2
"""
from __future__ import absolute_import, division, print_function, unicode_literals
from ibeis import viz
import utool as ut
import vtool as vt
import plottool as pt # NOQA
from functools import partial
import six
from ibeis import constants as const
from plottool import draw_func2 as df2
from plottool.viz_featrow import draw_feat_row
from ibeis.viz import viz_helpers as vh
from plottool import interact_helpers as ih
(print, rrr, profile) = ut.inject2(__name__, '[interact_chip]')
[docs]def interact_multichips(ibs, aid_list, config2_=None, **kwargs):
r"""
Args:
ibs (IBEISController): ibeis controller object
aid_list (list): list of annotation rowids
Returns:
MultiImageInteraction: iteract_obj
CommandLine:
python -m ibeis.viz.interact.interact_chip --exec-interact_multichips --show
Example:
>>> # SLOW_DOCTEST
>>> from ibeis.viz.interact.interact_chip import * # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb(defaultdb='testdb1')
>>> aid_list = ibs.get_valid_aids()
>>> iteract_obj = interact_multichips(ibs, aid_list)
>>> iteract_obj.start()
>>> result = ('iteract_obj = %s' % (str(iteract_obj),))
>>> print(result)
>>> ut.show_if_requested()
"""
# FIXME: needs to be flushed out a little
import plottool as pt
show_chip_list = [
partial(viz.show_chip, ibs, aid, config2_=config2_)
for aid in aid_list
]
vizkw = dict(ell=0, pts=1)
context_option_funcs = [
partial(build_annot_context_options, ibs, aid, config2_=config2_)
for aid in aid_list
]
iteract_obj = pt.interact_multi_image.MultiImageInteraction(
show_chip_list, context_option_funcs=context_option_funcs,
vizkw=vizkw, **kwargs)
return iteract_obj
[docs]def build_annot_context_options(ibs, aid, refresh_func=None,
with_interact_name=True,
with_interact_chip=True,
with_interact_image=True, config2_=None):
r"""
Args:
ibs (IBEISController): ibeis controller object
aid (int): annotation id
refresh_func (None): (default = None)
with_interact_name (bool): (default = True)
with_interact_chip (bool): (default = True)
with_interact_image (bool): (default = True)
config2_ (dict): (default = None)
Returns:
list: callback_list
CommandLine:
python -m ibeis.viz.interact.interact_chip --exec-build_annot_context_options
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.viz.interact.interact_chip import * # NOQA
>>> import ibeis
>>> ibs = ibeis.opendb(defaultdb='testdb1')
>>> aid = ibs.get_valid_aids()[0]
>>> refresh_func = None
>>> with_interact_name = True
>>> with_interact_chip = True
>>> with_interact_image = True
>>> config2_ = None
>>> callback_list = build_annot_context_options(ibs, aid, refresh_func,
>>> with_interact_name,
>>> with_interact_chip,
>>> with_interact_image,
>>> config2_)
>>> result = ('callback_list = %s' % (ut.list_str(callback_list, nl=4),))
>>> print(result)
"""
import guitool
is_exemplar = ibs.get_annot_exemplar_flags(aid)
def refresh_wrp(func):
def _wrp():
ret = func()
if refresh_func is None:
print('no refresh func')
else:
print('calling refresh_func=%r' % (refresh_func,))
refresh_func()
return ret
return _wrp
def newplot_wrp(func):
def _wrp():
import plottool as pt
ret = func()
pt.draw()
return ret
return _wrp
@refresh_wrp
def toggle_exemplar_func():
new_flag = not is_exemplar
print('set_annot_exemplar(%r, %r)' % (aid, new_flag))
ibs.set_annot_exemplar_flags(aid, new_flag)
def set_yaw_func(yawtext):
#@refresh_wrp()
def _wrap_yaw():
ibs.set_annot_yaw_texts([aid], [yawtext])
print('set_annot_yaw(%r, %r)' % (aid, yawtext))
return _wrap_yaw
def set_quality_func(qualtext):
#@refresh_wrp()
def _wrp_qual():
ibs.set_annot_quality_texts([aid], [qualtext])
print('set_annot_quality(%r, %r)' % (aid, qualtext))
return _wrp_qual
# Define popup menu
callback_list = []
nid = ibs.get_annot_name_rowids(aid)
if with_interact_chip:
callback_list += [
('Interact chip',
partial(
ishow_chip, ibs, aid, fnum=None, config2_=config2_))
]
if with_interact_name and not ibs.is_nid_unknown(nid):
from ibeis.viz.interact import interact_name
callback_list.append(
('Interact name', partial(interact_name.ishow_name, ibs,
nid, fnum=None))
)
from ibeis.viz import viz_graph
callback_list.append(
('Interact name graph',
partial(viz_graph.make_name_graph_interaction,
ibs, nids=None, aids=[aid])),
)
if with_interact_image:
gid = ibs.get_annot_gids(aid)
from ibeis.viz.interact import interact_annotations2
callback_list.append(
('Interact image',
partial(
interact_annotations2.ishow_image2, ibs, gid, fnum=None))
)
if True:
from ibeis import viz
callback_list.append(
('Show foreground mask',
newplot_wrp(lambda: viz.show_probability_chip(
ibs, aid, config2_=config2_))),
)
callback_list.append(
('Show foreground mask (blended)',
newplot_wrp(lambda: viz.show_probability_chip(
ibs, aid, config2_=config2_, blend=True))),
)
if True:
# Edit mask
callback_list.append(
('Edit mask',
partial(ibs.depc_annot.get_property, 'annotmask', aid, recompute=True))
)
current_qualtext = ibs.get_annot_quality_texts([aid])[0]
current_yawtext = ibs.get_annot_yaw_texts([aid])[0]
# Nested viewpoints
callback_list += [
#('Set Viewpoint: ' + key, set_yaw_func(key))
('Set &Viewpoint: ', [
('&' + str(count) + ' ' +
('*' if current_yawtext == key else '') + key,
set_yaw_func(key))
for count, key in
enumerate(six.iterkeys(const.VIEWTEXT_TO_YAW_RADIANS), start=1)
]),
]
# Nested qualities
callback_list += [
#('Set Quality: ' + key, set_quality_func(key))
('Set &Quality: ', [
('&' + str(count) + ' ' + ('*' if current_qualtext == key else '') +
'&' + key,
set_quality_func(key))
for count, key in
enumerate(six.iterkeys(const.QUALITY_TEXT_TO_INT), start=1)
]),
]
with_tags = True
if with_tags:
from ibeis import tag_funcs
case_list = tag_funcs.get_available_annot_tags()
tags = ibs.get_annot_case_tags([aid])[0]
tags = [_.lower() for _ in tags]
case_hotlink_list = guitool.make_word_hotlinks(case_list,
after_colon=True)
def _wrap_set_annot_prop(prop, toggle_val):
if ut.VERBOSE:
print('[SETTING] Clicked set prop=%r to val=%r' %
(prop, toggle_val,))
ibs.set_annot_prop(prop, [aid], [toggle_val])
if ut.VERBOSE:
print('[SETTING] done')
annot_tag_options = []
for case, case_hotlink in zip(case_list, case_hotlink_list):
toggle_val = case.lower() not in tags
fmtstr = 'Mark %s case' if toggle_val else 'Untag %s'
annot_tag_options += [
#(fmtstr % (case_hotlink,), lambda:
#ibs.set_annotmatch_prop(case, _get_annotmatch_rowid(),
# [toggle_val])),
#(fmtstr % (case_hotlink,), partial(ibs.set_annotmatch_prop,
#case, [annotmatch_rowid], [toggle_val])),
(fmtstr % (case_hotlink,), partial(_wrap_set_annot_prop, case,
toggle_val)),
]
callback_list += [
('Set Annot Ta&gs', annot_tag_options),
]
callback_list += [
('Remove name', lambda: ibs.set_annot_name_rowids([aid], [-aid]))
]
callback_list += [
('Unset as e&xemplar' if is_exemplar else 'Set as e&xemplar',
toggle_exemplar_func),
]
annot_info = ibs.get_annot_info(
aid, default=True, gname=False, name=False, notes=False,
exemplar=False)
def print_annot_info():
print('[interact_chip] Annotation Info = ' + ut.obj_str(annot_info, nl=4))
print('config2_ = %r' % (config2_,))
if config2_ is not None:
print('config2_.__dict__ = %s' % (ut.repr3(config2_.__dict__),))
callback_list += [
('dev print annot info', print_annot_info),
('dev refresh', pt.update),
]
if ut.is_developer():
def dev_debug():
print('aid = %r' % (aid,))
print('config2_ = %r' % (config2_,))
def dev_embed(ibs=ibs, aid=aid, config2_=config2_):
#import plottool as pt
#pt.plt.ioff()
# TODO need to disable matplotlib callbacks?
# Causes can't re-enter readline error
ut.embed()
#pt.plt.ion()
pass
callback_list += [
('dev chip context embed', dev_embed),
('dev chip context debug', dev_debug),
]
return callback_list
#def custom_chip_click(event):
# ax = event.inaxes
# if ih.clicked_outside_axis(event):
# pass
# else:
# viztype = vh.get_ibsdat(ax, 'viztype')
# print('[ic] viztype=%r' % viztype)
# if viztype == 'chip':
# if event.button == 3: # right-click
# import guitool
# from ibeis.viz.interact import interact_chip
# height = fig.canvas.geometry().height()
# qpoint = guitool.newQPoint(event.x, height - event.y)
# refresh_func = partial(_chip_view, **kwargs)
# interact_chip.show_annot_context_menu(
# ibs, aid, fig.canvas, qpoint, refresh_func=refresh_func,
# with_interact_chip=False, config2_=config2_)
# CHIP INTERACTION 2
[docs]def ishow_chip(ibs, aid, fnum=2, fx=None, dodraw=True, config2_=None,
ischild=False, **kwargs):
r"""
# TODO:
split into two interactions
interact chip and interact chip features
Args:
ibs (IBEISController): ibeis controller object
aid (int): annotation id
fnum (int): figure number
fx (None):
CommandLine:
python -m ibeis.viz.interact.interact_chip --test-ishow_chip --show
python -m ibeis.viz.interact.interact_chip --test-ishow_chip --show --aid 2
Example:
>>> # DISABLE_DOCTEST
>>> from ibeis.viz.interact.interact_chip import * # NOQA
>>> import ibeis
>>> # build test data
>>> ibs = ibeis.opendb('testdb1')
>>> aid = ut.get_argval('--aid', type_=int, default=1)
>>> fnum = 2
>>> fx = None
>>> # execute function
>>> dodraw = ut.show_was_requested()
>>> result = ishow_chip(ibs, aid, fnum, fx, dodraw)
>>> # verify results
>>> pt.show_if_requested()
>>> print(result)
"""
fnum = pt.ensure_fnum(fnum)
vh.ibsfuncs.assert_valid_aids(ibs, (aid,))
# TODO: Reconcile this with interact keypoints.
# Preferably this will call that but it will set some fancy callbacks
if not ischild:
fig = ih.begin_interaction('chip', fnum)
else:
fig = pt.gcf()
#fig = pt.figure(fnum=fnum, pnum=pnum)
# Get chip info (make sure get_chips is called first)
#mode_ptr = [1]
mode_ptr = [0]
def _select_fxth_kpt(fx):
# Get the fx-th keypiont
chip = ibs.get_annot_chips(aid, config2_=config2_)
kp = ibs.get_annot_kpts(aid, config2_=config2_)[fx]
sift = ibs.get_annot_vecs(aid, config2_=config2_)[fx]
# Draw chip + keypoints + highlighted plots
_chip_view(pnum=(2, 1, 1), sel_fx=fx)
#ishow_chip(ibs, aid, fnum=None, fx=fx, config2_=config2_, **kwargs)
# Draw the selected feature plots
nRows, nCols, px = (2, 3, 3)
draw_feat_row(chip, fx, kp, sift, fnum, nRows, nCols, px, None)
def _chip_view(mode=0, pnum=(1, 1, 1), **kwargs):
print('... _chip_view mode=%r' % mode_ptr[0])
kwargs['ell'] = mode_ptr[0] == 1
kwargs['pts'] = mode_ptr[0] == 2
if not ischild:
df2.figure(fnum=fnum, pnum=pnum, docla=True, doclf=True)
# Toggle no keypoints view
viz.show_chip(ibs, aid, fnum=fnum, pnum=pnum, config2_=config2_,
**kwargs)
df2.set_figtitle('Chip View')
def _on_chip_click(event):
print('[inter] clicked chip')
ax, x, y = event.inaxes, event.xdata, event.ydata
if ih.clicked_outside_axis(event):
if not ischild:
print('... out of axis')
mode_ptr[0] = (mode_ptr[0] + 1) % 3
_chip_view(**kwargs)
else:
if event.button == 3: # right-click
import guitool
#from ibeis.viz.interact import interact_chip
height = fig.canvas.geometry().height()
qpoint = guitool.newQPoint(event.x, height - event.y)
refresh_func = partial(_chip_view, **kwargs)
callback_list = build_annot_context_options(
ibs, aid, refresh_func=refresh_func,
with_interact_chip=False,
config2_=config2_)
qwin = fig.canvas
guitool.popup_menu(qwin, qpoint, callback_list)
#interact_chip.show_annot_context_menu(
# ibs, aid, fig.canvas, qpoint, refresh_func=refresh_func,
# with_interact_chip=False, config2_=config2_)
else:
viztype = vh.get_ibsdat(ax, 'viztype')
print('[ic] viztype=%r' % viztype)
if viztype == 'chip' and event.key == 'shift':
_chip_view(**kwargs)
ih.disconnect_callback(fig, 'button_press_event')
elif viztype == 'chip':
kpts = ibs.get_annot_kpts(aid, config2_=config2_)
if len(kpts) > 0:
fx = vt.nearest_point(
x, y, kpts, conflict_mode='next')[0]
print('... clicked fx=%r' % fx)
_select_fxth_kpt(fx)
else:
print('... len(kpts) == 0')
elif viztype in ['warped', 'unwarped']:
fx = vh.get_ibsdat(ax, 'fx')
if fx is not None and viztype == 'warped':
viz.show_keypoint_gradient_orientations(
ibs, aid, fx, fnum=df2.next_fnum())
else:
print('...Unknown viztype: %r' % viztype)
viz.draw()
# Draw without keypoints the first time
if fx is not None:
_select_fxth_kpt(fx)
else:
_chip_view(**kwargs)
if dodraw:
viz.draw()
if not ischild:
ih.connect_callback(fig, 'button_press_event', _on_chip_click)
if __name__ == '__main__':
"""
CommandLine:
python -m ibeis.viz.interact.interact_chip
python -m ibeis.viz.interact.interact_chip --allexamples
"""
import multiprocessing
multiprocessing.freeze_support() # for win32
import utool as ut # NOQA
ut.doctest_funcs()