Example #1
0
 def qt_edge_reviewer(infr, edge=None):
     import guitool_ibeis as gt
     gt.ensure_qapp()
     from ibeis.viz import viz_graph2
     infr.manual_wgt = viz_graph2.AnnotPairDialog(
         edge=edge, infr=infr, standalone=False,
         cfgdict=infr.verifier_params)
     if edge is not None:
         # infr.emit_manual_review(edge, priority=None)
         infr.manual_wgt.seek(0)
         # infr.manual_wgt.show()
     return infr.manual_wgt
Example #2
0
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
    gt.ensure_qapp()
    #backend_callback = back.front.update_tables
    backend_callback = None
    review_cfg = dict(filter_reviewed=filter_reviewed)
    qres_wgt = inspect_gui.QueryResultsWidget(ibs,
                                              cm_list,
                                              callback=backend_callback,
                                              review_cfg=review_cfg)
    if dodraw:
        qres_wgt.show()
        qres_wgt.raise_()
    return qres_wgt
Example #3
0
def make_test_result_custom_api(ibs, testres):
    import guitool_ibeis
    guitool_ibeis.ensure_qapp()
    cfgx = 0
    cfgres_info = testres.cfgx2_cmsinfo[cfgx]
    qaids = testres.qaids
    gt_aids = cfgres_info['qx2_gt_aid']
    gf_aids = cfgres_info['qx2_gf_aid']
    qx2_gt_timedelta = ibs.get_annot_pair_timedelta(qaids, gt_aids)
    qx2_gf_timedelta = ibs.get_annot_pair_timedelta(qaids, gf_aids)
    col_name_list = [
        'qaids',
        'qx2_gt_aid',
        'qx2_gf_aid',
        'qx2_gt_timedelta',
        'qx2_gf_timedelta',
    ]
    col_types_dict = {}
    col_getter_dict = {}
    col_getter_dict.update(**cfgres_info)
    col_getter_dict['qaids'] = testres.qaids
    col_getter_dict['qx2_gt_timedelta'] = qx2_gt_timedelta
    col_getter_dict['qx2_gf_timedelta'] = qx2_gf_timedelta
    col_bgrole_dict = {}
    col_ider_dict = {}
    col_setter_dict = {}
    editable_colnames = []
    sortby = 'qaids'

    def get_thumb_size():
        return 128

    col_width_dict = {}

    custom_api = guitool_ibeis.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)
    #headers = custom_api.make_headers(tblnice='results')
    #print(ut.repr2(headers))
    wgt = guitool_ibeis.APIItemWidget()
    wgt.connect_api(custom_api)
    return wgt
Example #4
0
def setup_dummy_menus():
    r"""
    CommandLine:
        python -m ibeis.gui.guimenus --test-setup_dummy_menus

    Example:
        >>> # DISABLE_DOCTEST
        >>> from ibeis.gui.guimenus import *  # NOQA
        >>> result = setup_dummy_menus()
        >>> print(result)
    """
    #import unittest
    import guitool_ibeis as gt
    gt.ensure_qapp()  # must be ensured before any embeding
    mainwin = gt.QtWidgets.QMainWindow()
    back = DummyBack()
    import mock
    mainwin.expand_names_tree = mock.Mock
    setup_menus(mainwin, back)
    mainwin.show()
    mainwin.resize(600, 100)
    #ut.embed()
    gt.qtapp_loop(mainwin, frequency=100)
Example #5
0
    def demo_classes(pblm):
        r"""
        CommandLine:
            python -m ibeis.algo.verif.vsone demo_classes --saveparts --save=classes.png --clipwhite

            python -m ibeis.algo.verif.vsone demo_classes --saveparts --save=figures/classes.png --clipwhite --dpath=~/latex/crall-iccv-2017

        Example:
            >>> # DISABLE_DOCTEST
            >>> from ibeis.algo.verif.vsone import *  # NOQA
            >>> pblm = OneVsOneProblem.from_empty(defaultdb='PZ_PB_RF_TRAIN')
            >>> pblm.load_features()
            >>> pblm.load_samples()
            >>> pblm.build_feature_subsets()
            >>> pblm.demo_classes()
            >>> ut.show_if_requested()
        """
        task_key = 'match_state'
        labels = pblm.samples.subtasks[task_key]
        pb_labels = pblm.samples.subtasks['photobomb_state']
        classname_offset = {
            POSTV: 0,
            NEGTV: 0,
            INCMP: 0,
        }
        class_name = POSTV
        class_name = NEGTV
        class_name = INCMP

        feats = pblm.samples.X_dict['learn(sum,glob)']

        offset = 0
        class_to_edge = {}
        for class_name in labels.class_names:
            print('Find example of %r' % (class_name, ))
            # Find an example of each class (that is not a photobomb)
            pbflags = pb_labels.indicator_df['notpb']
            flags = labels.indicator_df[class_name]
            assert np.all(pbflags.index == flags.index)
            flags = flags & pbflags
            ratio = feats['sum(ratio)']
            if class_name == INCMP:
                # flags &= feats['global(delta_yaw)'] > 3
                flags &= feats['global(delta_view)'] > 2
                # flags &= feats['sum(ratio)'] > 0
            if class_name == NEGTV:
                low = ratio[flags].max()
                flags &= feats['sum(ratio)'] >= low
            if class_name == POSTV:
                low = ratio[flags].median() / 2
                high = ratio[flags].median()
                flags &= feats['sum(ratio)'] < high
                flags &= feats['sum(ratio)'] > low
            # flags &= pblm.samples.simple_scores[flags]['score_lnbnn_1vM'] > 0
            idxs = np.where(flags)[0]
            print('Found %d candidates' % (len(idxs)))
            offset = classname_offset[class_name]
            idx = idxs[offset]
            series = labels.indicator_df.iloc[idx]
            assert series[class_name]
            edge = series.name
            class_to_edge[class_name] = edge

        import plottool_ibeis as pt
        import guitool_ibeis as gt
        gt.ensure_qapp()
        pt.qtensure()

        fnum = 1
        pt.figure(fnum=fnum, pnum=(1, 3, 1))
        pnum_ = pt.make_pnum_nextgen(1, 3)

        # classname_alias = {
        #     POSTV: 'positive',
        #     NEGTV: 'negative',
        #     INCMP: 'incomparable',
        # }

        ibs = pblm.infr.ibs
        for class_name in class_to_edge.keys():
            edge = class_to_edge[class_name]
            aid1, aid2 = edge
            # alias = classname_alias[class_name]
            print('class_name = %r' % (class_name, ))
            annot1 = ibs.annots([aid1])[0]._make_lazy_dict()
            annot2 = ibs.annots([aid2])[0]._make_lazy_dict()
            vt.matching.ensure_metadata_normxy(annot1)
            vt.matching.ensure_metadata_normxy(annot2)
            match = vt.PairwiseMatch(annot1, annot2)
            cfgdict = pblm.hyper_params.vsone_match.asdict()
            match.apply_all(cfgdict)
            pt.figure(fnum=fnum, pnum=pnum_())
            match.show(show_ell=False, show_ori=False)
Example #6
0
def fix_annotmatch_pzmaster1():
    """
    PZ_Master1 had annotmatch rowids that did not agree with the current name
    labeling. Looking at the inconsistencies in the graph interface was too
    cumbersome, because over 3000 annots were incorrectly grouped together.

    This function deletes any annotmatch rowid that is not consistent with the
    current labeling so we can go forward with using the new AnnotInference
    object
    """
    import ibeis
    ibs = ibeis.opendb('PZ_Master1')
    infr = ibeis.AnnotInference(ibs=ibs, aids=ibs.get_valid_aids(), verbose=5)
    infr.initialize_graph()
    annots = ibs.annots()
    aid_to_nid = ut.dzip(annots.aids, annots.nids)

    if False:
        infr.reset_feedback()
        infr.ensure_mst()
        infr.apply_feedback_edges()
        infr.relabel_using_reviews()
        infr.start_qt_interface()

    # Get annotmatch rowids that agree with current labeling
    if False:
        annotmatch = ibs.db.get_table_as_pandas('annotmatch')
        import pandas as pd
        flags1 = pd.isnull(annotmatch['annotmatch_evidence_decision'])
        flags2 = annotmatch['annotmatch_tag_text'] == ''
        bad_part = annotmatch[flags1 & flags2]
        rowids = bad_part.index.tolist()
        ibs.delete_annotmatch(rowids)

    if False:
        # Delete bidirectional annotmatches
        annotmatch = ibs.db.get_table_as_pandas('annotmatch')
        df = annotmatch.set_index(['annot_rowid1', 'annot_rowid2'])

        # Find entires that have both directions
        pairs1 = annotmatch[['annot_rowid1', 'annot_rowid2']].values
        f_edges = {tuple(p) for p in pairs1}
        b_edges = {tuple(p[::-1]) for p in pairs1}
        isect_edges = {tuple(sorted(p)) for p in b_edges.intersection(f_edges)}
        isect_edges1 = list(isect_edges)
        isect_edges2 = [p[::-1] for p in isect_edges]

        # cols = ['annotmatch_evidence_decision', 'annotmatch_tag_text']
        import pandas as pd

        custom_ = {
            (559, 4909): (False, ['photobomb']),
            (7918, 8041): (False, ['photobomb']),
            (6634, 6754): (False, ['photobomb']),
            (3707, 3727): (False, ['photobomb']),
            (86, 103): (False, ['photobomb']),
        }
        extra_ = {
        }

        fixme_edges = []

        d1 = df.loc[isect_edges1].reset_index(drop=False)
        d2 = df.loc[isect_edges2].reset_index(drop=False)
        flags = d1['annotmatch_evidence_decision'] != d2['annotmatch_evidence_decision']
        from ibeis.tag_funcs import _parse_tags
        for f, r1, r2 in zip(flags, d1.iterrows(), d2.iterrows()):
            v1, v2 = r1[1], r2[1]
            aid1 = v1['annot_rowid1']
            aid2 = v1['annot_rowid2']
            truth_real = (ibs.const.EVIDENCE_DECISION.POSITIVE
                          if aid_to_nid[aid1] == aid_to_nid[aid2] else
                          ibs.const.EVIDENCE_DECISION.NEGATIVE)
            truth1 = v1['annotmatch_evidence_decision']
            truth2 = v2['annotmatch_evidence_decision']
            t1 = _parse_tags(v1['annotmatch_tag_text'])
            t2 = _parse_tags(v2['annotmatch_tag_text'])
            newtag = ut.union_ordered(t1, t2)
            if (aid1, aid2) in custom_:
                continue
            fixme_flag = False
            if not pd.isnull(truth1):
                if truth_real != truth1:
                    fixme_flag = True
            if not pd.isnull(truth2):
                if truth_real != truth2:
                    fixme_flag = True
            if fixme_flag:
                print('newtag = %r' % (newtag,))
                print('truth_real = %r' % (truth_real,))
                print('truth1 = %r' % (truth1,))
                print('truth2 = %r' % (truth2,))
                print('aid1 = %r' % (aid1,))
                print('aid2 = %r' % (aid2,))
                fixme_edges.append((aid1, aid2))
            else:
                extra_[(aid1, aid2)] = (truth_real, newtag)

        extra_.update(custom_)
        new_pairs = extra_.keys()
        new_truths = ut.take_column(ut.dict_take(extra_, new_pairs), 0)
        new_tags = ut.take_column(ut.dict_take(extra_, new_pairs), 1)
        new_tag_texts = [';'.join(t) for t in new_tags]
        aids1, aids2 = ut.listT(new_pairs)

        # Delete the old
        ibs.delete_annotmatch((d1['annotmatch_rowid'].values.tolist() +
                               d2['annotmatch_rowid'].values.tolist()))

        # Add the new
        ams = ibs.add_annotmatch_undirected(aids1, aids2)
        ibs.set_annotmatch_evidence_decision(ams, new_truths)
        ibs.set_annotmatch_tag_text(ams, new_tag_texts)

        if False:
            import guitool_ibeis as gt
            gt.ensure_qapp()
            ut.qtensure()
            from ibeis.gui import inspect_gui
            inspect_gui.show_vsone_tuner(ibs, aid1, aid2)

        # pairs2 = pairs1.T[::-1].T
        # idx1, idx2 = ut.isect_indices(list(map(tuple, pairs1)),
        #                               list(map(tuple, pairs2)))
        # r_edges = list(set(map(tuple, map(sorted, pairs1[idx1]))))
        # unique_pairs = list(set(map(tuple, map(sorted, pairs1[idx1]))))
        # df = annotmatch.set_index(['annot_rowid1', 'annot_rowid2'])

    x = ut.ddict(list)
    annotmatch = ibs.db.get_table_as_pandas('annotmatch')
    import ubelt as ub
    _iter = annotmatch.iterrows()
    prog = ub.ProgIter(_iter, length=len(annotmatch))
    for k, m in prog:
        aid1 = m['annot_rowid1']
        aid2 = m['annot_rowid2']
        if m['annotmatch_evidence_decision'] == ibs.const.EVIDENCE_DECISION.POSITIVE:
            if aid_to_nid[aid1] == aid_to_nid[aid2]:
                x['agree1'].append(k)
            else:
                x['disagree1'].append(k)
        elif m['annotmatch_evidence_decision'] == ibs.const.EVIDENCE_DECISION.NEGATIVE:
            if aid_to_nid[aid1] == aid_to_nid[aid2]:
                x['disagree2'].append(k)
            else:
                x['agree2'].append(k)

    ub.map_vals(len, x)
    ut.dict_hist(annotmatch.loc[x['disagree1']]['annotmatch_tag_text'])

    disagree1 = annotmatch.loc[x['disagree1']]
    pb_disagree1 =  disagree1[disagree1['annotmatch_tag_text'] == 'photobomb']
    aids1 = pb_disagree1['annot_rowid1'].values.tolist()
    aids2 = pb_disagree1['annot_rowid2'].values.tolist()
    aid_pairs = list(zip(aids1, aids2))
    infr = ibeis.AnnotInference.from_pairs(aid_pairs, ibs=ibs, verbose=5)
    if False:
        feedback = infr.read_ibeis_annotmatch_feedback(edges=infr.edges())
        infr.external_feedback = feedback
        infr.apply_feedback_edges()
        infr.start_qt_interface(loop=False)

    # Delete these values
    if False:
        nonpb_disagree1 = disagree1[disagree1['annotmatch_tag_text'] != 'photobomb']
        disagree2 = annotmatch.loc[x['disagree2']]
        ibs.delete_annotmatch(nonpb_disagree1['annotmatch_rowid'])
        ibs.delete_annotmatch(disagree2['annotmatch_rowid'])

    # ut.dict_hist(disagree1['annotmatch_tag_text'])
    import networkx as nx
    graph = nx.Graph()
    graph.add_edges_from(zip(pb_disagree1['annot_rowid1'], pb_disagree1['annot_rowid2']))
    list(nx.connected_components(graph))

    set(annotmatch.loc[x['disagree2']]['annotmatch_tag_text'])
Example #7
0
def fix_bidirectional_annotmatch(ibs):
    import ibeis
    infr = ibeis.AnnotInference(ibs=ibs, aids='all', verbose=5)
    infr.initialize_graph()
    annots = ibs.annots()
    aid_to_nid = ut.dzip(annots.aids, annots.nids)

    # Delete bidirectional annotmatches
    annotmatch = ibs.db.get_table_as_pandas('annotmatch')
    df = annotmatch.set_index(['annot_rowid1', 'annot_rowid2'])

    # Find entires that have both directions
    pairs1 = annotmatch[['annot_rowid1', 'annot_rowid2']].values
    f_edges = {tuple(p) for p in pairs1}
    b_edges = {tuple(p[::-1]) for p in pairs1}
    isect_edges = {tuple(sorted(p)) for p in b_edges.intersection(f_edges)}
    print('Found %d bidirectional edges' % len(isect_edges))
    isect_edges1 = list(isect_edges)
    isect_edges2 = [p[::-1] for p in isect_edges]

    import pandas as pd
    extra_ = {}
    fixme_edges = []
    d1 = df.loc[isect_edges1].reset_index(drop=False)
    d2 = df.loc[isect_edges2].reset_index(drop=False)
    flags = d1['annotmatch_evidence_decision'] != d2['annotmatch_evidence_decision']
    from ibeis.tag_funcs import _parse_tags
    for f, r1, r2 in zip(flags, d1.iterrows(), d2.iterrows()):
        v1, v2 = r1[1], r2[1]
        aid1 = v1['annot_rowid1']
        aid2 = v1['annot_rowid2']
        truth_real = (ibs.const.EVIDENCE_DECISION.POSITIVE
                      if aid_to_nid[aid1] == aid_to_nid[aid2] else
                      ibs.const.EVIDENCE_DECISION.NEGATIVE)
        truth1 = v1['annotmatch_evidence_decision']
        truth2 = v2['annotmatch_evidence_decision']
        t1 = _parse_tags(v1['annotmatch_tag_text'])
        t2 = _parse_tags(v2['annotmatch_tag_text'])
        newtag = ut.union_ordered(t1, t2)
        fixme_flag = False
        if not pd.isnull(truth1):
            if truth_real != truth1:
                fixme_flag = True
        if not pd.isnull(truth2):
            if truth_real != truth2:
                fixme_flag = True
        if fixme_flag:
            print('--')
            print('t1, t2 = %r, %r' % (t1, t2))
            print('newtag = %r' % (newtag,))
            print('truth_real, truth1, truth2 = %r, %r, %r' % (
                truth_real, truth1, truth2,))
            print('aid1, aid2 = %r, %r' % (aid1, aid2))
            fixme_edges.append(tuple(sorted((aid1, aid2))))
        else:
            extra_[(aid1, aid2)] = (truth_real, newtag)

    if len(fixme_edges) > 0:
        # need to manually fix these edges
        fix_infr = ibeis.AnnotInference.from_pairs(fixme_edges, ibs=ibs, verbose=5)
        feedback = fix_infr.read_ibeis_annotmatch_feedback(only_existing_edges=True)
        infr = fix_infr

        fix_infr.external_feedback = feedback
        fix_infr.apply_feedback_edges()
        fix_infr.start_qt_interface(loop=False)
        # DELETE OLD EDGES TWICE
        ams = ibs.get_annotmatch_rowid_from_edges(fixme_edges)
        ibs.delete_annotmatch(ams)
        ams = ibs.get_annotmatch_rowid_from_edges(fixme_edges)
        ibs.delete_annotmatch(ams)

        # MANUALLY CALL THIS ONCE FINISHED
        # TO ONLY CHANGE ANNOTMATCH EDGES
        infr.write_ibeis_staging_feedback()
        infr.write_ibeis_annotmatch_feedback()

    # extra_.update(custom_)
    new_pairs = extra_.keys()
    new_truths = ut.take_column(ut.dict_take(extra_, new_pairs), 0)
    new_tags = ut.take_column(ut.dict_take(extra_, new_pairs), 1)
    new_tag_texts = [';'.join(t) for t in new_tags]
    aids1, aids2 = ut.listT(new_pairs)

    # Delete the old
    ibs.delete_annotmatch((d1['annotmatch_rowid'].values.tolist() +
                           d2['annotmatch_rowid'].values.tolist()))

    # Add the new
    ams = ibs.add_annotmatch_undirected(aids1, aids2)
    ibs.set_annotmatch_evidence_decision(ams, new_truths)
    ibs.set_annotmatch_tag_text(ams, new_tag_texts)

    if False:
        import guitool_ibeis as gt
        gt.ensure_qapp()
        ut.qtensure()
        from ibeis.gui import inspect_gui
        inspect_gui.show_vsone_tuner(ibs, aid1, aid2)
Example #8
0
def make_metadata_custom_api(metadata):
    r"""
    CommandLine:
        python -m ibeis.expt.experiment_drawing --test-make_metadata_custom_api --show

    Example:
        >>> # DISABLE_DOCTEST
        >>> from ibeis.expt.experiment_drawing import *  # NOQA
        >>> import guitool_ibeis
        >>> guitool_ibeis.ensure_qapp()
        >>> metadata_fpath = '/media/raid/work/Elephants_drop1_ears/_ibsdb/figures/result_metadata.shelf'
        >>> metadata = ResultMetadata(metadata_fpath, autoconnect=True)
        >>> wgt = make_metadata_custom_api(metadata)
        >>> ut.quit_if_noshow()
        >>> wgt.show()
        >>> wgt.raise_()
        >>> guitool_ibeis.qtapp_loop(wgt, frequency=100)
    """
    import guitool_ibeis
    from guitool_ibeis.__PYQT__ import QtCore

    class MetadataViewer(guitool_ibeis.APIItemWidget):
        def __init__(wgt,
                     parent=None,
                     tblnice='Result Metadata Viewer',
                     **kwargs):
            guitool_ibeis.APIItemWidget.__init__(wgt,
                                                 parent=parent,
                                                 tblnice=tblnice,
                                                 **kwargs)
            wgt.connect_signals_and_slots()

        @guitool_ibeis.slot_(QtCore.QModelIndex)
        def _on_doubleclick(wgt, qtindex):
            print('[wgt] _on_doubleclick: ')
            col = qtindex.column()
            if wgt.api.col_edit_list[col]:
                print('do nothing special for editable columns')
                return
            model = qtindex.model()
            colname = model.get_header_name(col)
            if colname.endswith('fpath'):
                print('showing fpath')
                fpath = model.get_header_data(colname, qtindex)
                ut.startfile(fpath)

        def connect_signals_and_slots(wgt):
            #wgt.view.clicked.connect(wgt._on_click)
            wgt.view.doubleClicked.connect(wgt._on_doubleclick)
            #wgt.view.pressed.connect(wgt._on_pressed)
            #wgt.view.activated.connect(wgt._on_activated)

    guitool_ibeis.ensure_qapp()
    #cfgstr_list = metadata
    col_name_list, column_list = metadata.get_square_data()

    # Priority of column names
    colname_priority = [
        'qaids', 'qx2_gt_rank', 'qx2_gt_timedelta', 'qx2_gf_timedelta',
        'analysis_fpath', 'qx2_gt_raw_score', 'qx2_gf_raw_score'
    ]
    colname_priority += sorted(
        ut.setdiff_ordered(col_name_list, colname_priority))
    sortx = ut.priority_argsort(col_name_list, colname_priority)
    col_name_list = ut.take(col_name_list, sortx)
    column_list = ut.take(column_list, sortx)

    col_lens = list(map(len, column_list))
    print('col_name_list = %r' % (col_name_list, ))
    print('col_lens = %r' % (col_lens, ))
    assert len(col_lens) > 0, 'no columns'
    assert col_lens[0] > 0, 'no rows'
    assert all([len_ == col_lens[0] for len_ in col_lens]), 'inconsistant data'
    col_types_dict = {}
    col_getter_dict = dict(zip(col_name_list, column_list))
    col_bgrole_dict = {}
    col_ider_dict = {}
    col_setter_dict = {}
    col_nice_dict = {name: name.replace('qx2_', '') for name in col_name_list}
    col_nice_dict.update({
        'qx2_gt_timedelta': 'GT TimeDelta',
        'qx2_gf_timedelta': 'GF TimeDelta',
        'qx2_gt_rank': 'GT Rank',
    })
    editable_colnames = []
    sortby = 'qaids'

    def get_thumb_size():
        return 128

    col_width_dict = {}
    custom_api = guitool_ibeis.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,
                                         sort_reverse=True,
                                         col_width_dict=col_width_dict,
                                         col_nice_dict=col_nice_dict)
    #headers = custom_api.make_headers(tblnice='results')
    #print(ut.repr2(headers))
    wgt = MetadataViewer()
    wgt.connect_api(custom_api)
    return wgt
Example #9
0
def draw_results(ibs, testres):
    r"""
    Draws results from an experiment harness run.
    Rows store different qaids (query annotation ids)
    Cols store different configurations (algorithm parameters)

    Args:
        testres (TestResult):

    CommandLine:
        python dev.py -t custom:rrvsone_on=True,constrained_coeff=0 custom --qaid 12 --db PZ_MTEST --show --va
        python dev.py -t custom:rrvsone_on=True,constrained_coeff=.3 custom --qaid 12 --db PZ_MTEST --show --va --noqcache
        python dev.py -t custom:rrvsone_on=True custom --qaid 4 --db PZ_MTEST --show --va --noqcache
        python dev.py -t custom:rrvsone_on=True,grid_scale_factor=1 custom --qaid 12 --db PZ_MTEST --show --va --noqcache
        python dev.py -t custom:rrvsone_on=True,grid_scale_factor=1,grid_steps=1 custom --qaid 12 --db PZ_MTEST --show --va --noqcache

    CommandLine:
        python dev.py -t best --db seals2 --allgt --vz --fig-dname query_analysis_easy --show
        python dev.py -t best --db seals2 --allgt --vh --fig-dname query_analysis_hard --show

        python dev.py -t pyrscale --db PZ_MTEST --allgt --vn --fig-dname query_analysis_interesting --show
        python dev.py -t pyrscale --db testdb3 --allgt --vn --fig-dname query_analysis_interesting --vf
        python dev.py -t pyrscale --db testdb3 --allgt --vn --fig-dname query_analysis_interesting --vf --quality

        python -m ibeis.expt.experiment_drawing --test-draw_results --show --vn
        python -m ibeis.expt.experiment_drawing --test-draw_results --show --vn --db PZ_MTEST
        python -m ibeis.expt.old_storage --test-draw_results --show --db PZ_MTEST --gv

    Example:
        >>> # DISABLE_DOCTEST
        >>> from ibeis.expt.old_storage import *  # NOQA
        >>> from ibeis.init import main_helpers
        >>> ibs, testres = main_helpers.testdata_expts('PZ_MTEST')
        >>> result = draw_results(ibs, testres)
        >>> # verify results
        >>> print(result)
    """
    print(' --- DRAW RESULTS ---')

    # It is very inefficient to turn off caching when view_all is true

    figdir = ibs.get_fig_dir()
    ut.ensuredir(figdir)

    if ut.get_argflag(('--view-fig-directory', '--vf')):
        ut.view_directory(figdir)

    figdir_suffix = ut.get_argval('--fig-dname', type_=str, default=None)
    from os.path import join
    if figdir_suffix is not None:
        figdir = join(figdir, figdir_suffix)
        ut.ensuredir(figdir)
    #gx2_gt_timedelta
    #    cfgres_info['qx2_gf_timedelta'] = qx2_gf_timedelta

    metadata_fpath = join(figdir, 'result_metadata.shelf')
    metadata = ResultMetadata(metadata_fpath)
    #metadata.rrr()
    metadata.connect()
    metadata.sync_test_results(testres)
    #cfgstr = qreq_.get_cfgstr()
    #cfg_metadata = ensure_item(metadata, cfgstr, {})
    #avuuids = ibs.get_annot_visual_uuids(qaids)
    #avuuid2_ax = ensure_item(cfg_metadata, 'avuuid2_ax', {})
    #cfg_columns = ensure_item(cfg_metadata, 'columns', {})
    #import guitool_ibeis

    # ut.argv_flag_dec(draw_rank_cmc)(ibs, testres)

    # VIZ_INDIVIDUAL_RESULTS = True
    # if VIZ_INDIVIDUAL_RESULTS:
    #     draw_match_cases(ibs, testres, metadata=metadata)

    metadata.write()
    if ut.get_argflag(('--guiview', '--gv')):
        import guitool_ibeis
        guitool_ibeis.ensure_qapp()
        #wgt = make_test_result_custom_api(ibs, testres)
        wgt = make_metadata_custom_api(metadata)
        wgt.show()
        wgt.raise_()
        guitool_ibeis.qtapp_loop(wgt, frequency=100)
    metadata.close()

    if ut.NOT_QUIET:
        print('[DRAW_RESULT] EXIT EXPERIMENT HARNESS')