def build_cmsinfo(cm_list, qreq_):
    "\n    Helper function to report results over multiple queries (chip matches).\n    Basically given a group of queries of the same name, we only care if one of\n    them is correct.  This emulates encounters.\n\n    Runs queries of a specific configuration returns the best rank of each\n    query.\n\n    Args:\n        cm_list (list): list of chip matches\n        qreq_ (QueryRequest): request that computed the chip matches.\n\n    Returns:\n        dict: cmsinfo - info about multiple chip matches cm_list\n\n    CommandLine:\n        python -m wbia get_query_result_info\n        python -m wbia get_query_result_info:0 --db lynx \\\n            -a :qsame_imageset=True,been_adjusted=True,excluderef=True -t :K=1\n        python -m wbia get_query_result_info:0 --db lynx \\\n            -a :qsame_imageset=True,been_adjusted=True,excluderef=True -t :K=1 --cmd\n\n    Example:\n        >>> # ENABLE_DOCTEST\n        >>> from wbia.expt.test_result import *  # NOQA\n        >>> import wbia\n        >>> qreq_ = wbia.main_helpers.testdata_qreq_(a=[':qindex=0:3,dindex=0:5'])\n        >>> cm_list = qreq_.execute()\n        >>> cmsinfo = build_cmsinfo(cm_list, qreq_)\n        >>> print(ut.repr2(cmsinfo))\n\n    Ignore:\n        wbia -e rank_cmc --db humpbacks -a :has_any=hasnotch,mingt=2 \\\n                -t :proot=BC_DTW --show --nocache-big\n\n        wbia -e rank_cmc --db humpbacks -a :is_known=True,mingt=2 \\\n                -t :pipeline_root=BC_DTW\n\n        wbia -e rank_cmc --db humpbacks -a :is_known=True \\\n                -t :pipeline_root=BC_DTW \\\n                --qaid=1,9,15,16,18 --daid-override=1,9,15,16,18,21,22 \\\n                --show --debug-depc\n\n        --clear-all-depcache\n    "
    ibs = qreq_.ibs
    qaids = qreq_.qaids
    daids = qreq_.daids
    qx2_cminfo = []
    for cm in cm_list:
        if hasattr(cm, 'extend_results'):
            cminfo = cm.extend_results(qreq_).summarize(qreq_)
        else:
            cminfo = cm.summarize(qreq_)
        qx2_cminfo.append(cminfo)
    cmsinfo = ut.dict_stack(qx2_cminfo, 'qx2_')
    cmsinfo['qx2_gt_rank'] = ut.replace_nones(cmsinfo['qx2_gt_rank'], (- 1))
    if False:
        qx2_gtaids = ibs.get_annot_groundtruth(qaids, daid_list=daids)
        qx2_avepercision = np.array([cm.get_average_percision(ibs=ibs, gt_aids=gt_aids) for (cm, gt_aids) in zip(cm_list, qx2_gtaids)])
        cmsinfo['qx2_avepercision'] = qx2_avepercision
    qaids = qreq_.qaids
    qnids = ibs.get_annot_nids(qaids)
    unique_dnids = np.unique(ibs.get_annot_nids(qreq_.daids))
    (unique_qnids, groupxs) = ut.group_indices(qnids)
    cm_group_list = ut.apply_grouping(cm_list, groupxs)
    qnid2_aggnamescores = {}
    qnx2_nameres_info = []
    nameres_info_list = []
    for (qnid, cm_group) in zip(unique_qnids, cm_group_list):
        nid2_name_score_group = [dict([(nid, cm.name_score_list[nidx]) for (nid, nidx) in cm.nid2_nidx.items()]) for cm in cm_group]
        aligned_name_scores = np.array([ut.dict_take(nid_to_name_score, unique_dnids.tolist(), (- np.inf)) for nid_to_name_score in nid2_name_score_group]).T
        name_score_list = np.nanmax(aligned_name_scores, axis=1)
        qnid2_aggnamescores[qnid] = name_score_list
        sortx = name_score_list.argsort()[::(- 1)]
        sorted_namescores = name_score_list[sortx]
        sorted_dnids = unique_dnids[sortx]
        success = (sorted_dnids == qnid)
        failure = np.logical_and((~ success), (sorted_dnids > 0))
        gt_name_rank = (None if (not np.any(success)) else np.where(success)[0][0])
        gf_name_rank = (None if (not np.any(failure)) else np.nonzero(failure)[0][0])
        gt_nid = sorted_dnids[gt_name_rank]
        gf_nid = sorted_dnids[gf_name_rank]
        gt_name_score = sorted_namescores[gt_name_rank]
        gf_name_score = sorted_namescores[gf_name_rank]
        if (gt_name_score <= 0):
            if hasattr(qreq_, 'dnids'):
                gt_name_rank = (len(qreq_.dnids) + 1)
            else:
                dnids = list(set(ibs.get_annot_nids(qreq_.daids)))
                gt_name_rank = (len(dnids) + 1)
        qnx2_nameres_info = {}
        qnx2_nameres_info['qnid'] = qnid
        qnx2_nameres_info['gt_nid'] = gt_nid
        qnx2_nameres_info['gf_nid'] = gf_nid
        qnx2_nameres_info['gt_name_rank'] = gt_name_rank
        qnx2_nameres_info['gf_name_rank'] = gf_name_rank
        qnx2_nameres_info['gt_name_score'] = gt_name_score
        qnx2_nameres_info['gf_name_score'] = gf_name_score
        nameres_info_list.append(qnx2_nameres_info)
        nameres_info = ut.dict_stack(nameres_info_list, 'qnx2_')
        cmsinfo.update(nameres_info)
    return cmsinfo
Helper function to report results over multiple queries (chip matches).
Basically given a group of queries of the same name, we only care if one of
them is correct.  This emulates encounters.

Runs queries of a specific configuration returns the best rank of each
query.

Args:
    cm_list (list): list of chip matches
    qreq_ (QueryRequest): request that computed the chip matches.

Returns:
    dict: cmsinfo - info about multiple chip matches cm_list

CommandLine:
    python -m wbia get_query_result_info
    python -m wbia get_query_result_info:0 --db lynx \
        -a :qsame_imageset=True,been_adjusted=True,excluderef=True -t :K=1
    python -m wbia get_query_result_info:0 --db lynx \
        -a :qsame_imageset=True,been_adjusted=True,excluderef=True -t :K=1 --cmd

Example:
    >>> # ENABLE_DOCTEST
    >>> from wbia.expt.test_result import *  # NOQA
    >>> import wbia
    >>> qreq_ = wbia.main_helpers.testdata_qreq_(a=[':qindex=0:3,dindex=0:5'])
    >>> cm_list = qreq_.execute()
    >>> cmsinfo = build_cmsinfo(cm_list, qreq_)
    >>> print(ut.repr2(cmsinfo))

Ignore:
    wbia -e rank_cmc --db humpbacks -a :has_any=hasnotch,mingt=2 \
            -t :proot=BC_DTW --show --nocache-big

    wbia -e rank_cmc --db humpbacks -a :is_known=True,mingt=2 \
            -t :pipeline_root=BC_DTW

    wbia -e rank_cmc --db humpbacks -a :is_known=True \
            -t :pipeline_root=BC_DTW \
            --qaid=1,9,15,16,18 --daid-override=1,9,15,16,18,21,22 \
            --show --debug-depc

    --clear-all-depcache
def build_cmsinfo(cm_list, qreq_):
    "\n    Helper function to report results over multiple queries (chip matches).\n    Basically given a group of queries of the same name, we only care if one of\n    them is correct.  This emulates encounters.\n\n    Runs queries of a specific configuration returns the best rank of each\n    query.\n\n    Args:\n        cm_list (list): list of chip matches\n        qreq_ (QueryRequest): request that computed the chip matches.\n\n    Returns:\n        dict: cmsinfo - info about multiple chip matches cm_list\n\n    CommandLine:\n        python -m wbia get_query_result_info\n        python -m wbia get_query_result_info:0 --db lynx \\\n            -a :qsame_imageset=True,been_adjusted=True,excluderef=True -t :K=1\n        python -m wbia get_query_result_info:0 --db lynx \\\n            -a :qsame_imageset=True,been_adjusted=True,excluderef=True -t :K=1 --cmd\n\n    Example:\n        >>> # ENABLE_DOCTEST\n        >>> from wbia.expt.test_result import *  # NOQA\n        >>> import wbia\n        >>> qreq_ = wbia.main_helpers.testdata_qreq_(a=[':qindex=0:3,dindex=0:5'])\n        >>> cm_list = qreq_.execute()\n        >>> cmsinfo = build_cmsinfo(cm_list, qreq_)\n        >>> print(ut.repr2(cmsinfo))\n\n    Ignore:\n        wbia -e rank_cmc --db humpbacks -a :has_any=hasnotch,mingt=2 \\\n                -t :proot=BC_DTW --show --nocache-big\n\n        wbia -e rank_cmc --db humpbacks -a :is_known=True,mingt=2 \\\n                -t :pipeline_root=BC_DTW\n\n        wbia -e rank_cmc --db humpbacks -a :is_known=True \\\n                -t :pipeline_root=BC_DTW \\\n                --qaid=1,9,15,16,18 --daid-override=1,9,15,16,18,21,22 \\\n                --show --debug-depc\n\n        --clear-all-depcache\n    "
    ibs = qreq_.ibs
    qaids = qreq_.qaids
    daids = qreq_.daids
    qx2_cminfo = []
    for cm in cm_list:
        if hasattr(cm, 'extend_results'):
            cminfo = cm.extend_results(qreq_).summarize(qreq_)
        else:
            cminfo = cm.summarize(qreq_)
        qx2_cminfo.append(cminfo)
    cmsinfo = ut.dict_stack(qx2_cminfo, 'qx2_')
    cmsinfo['qx2_gt_rank'] = ut.replace_nones(cmsinfo['qx2_gt_rank'], (- 1))
    if False:
        qx2_gtaids = ibs.get_annot_groundtruth(qaids, daid_list=daids)
        qx2_avepercision = np.array([cm.get_average_percision(ibs=ibs, gt_aids=gt_aids) for (cm, gt_aids) in zip(cm_list, qx2_gtaids)])
        cmsinfo['qx2_avepercision'] = qx2_avepercision
    qaids = qreq_.qaids
    qnids = ibs.get_annot_nids(qaids)
    unique_dnids = np.unique(ibs.get_annot_nids(qreq_.daids))
    (unique_qnids, groupxs) = ut.group_indices(qnids)
    cm_group_list = ut.apply_grouping(cm_list, groupxs)
    qnid2_aggnamescores = {}
    qnx2_nameres_info = []
    nameres_info_list = []
    for (qnid, cm_group) in zip(unique_qnids, cm_group_list):
        nid2_name_score_group = [dict([(nid, cm.name_score_list[nidx]) for (nid, nidx) in cm.nid2_nidx.items()]) for cm in cm_group]
        aligned_name_scores = np.array([ut.dict_take(nid_to_name_score, unique_dnids.tolist(), (- np.inf)) for nid_to_name_score in nid2_name_score_group]).T
        name_score_list = np.nanmax(aligned_name_scores, axis=1)
        qnid2_aggnamescores[qnid] = name_score_list
        sortx = name_score_list.argsort()[::(- 1)]
        sorted_namescores = name_score_list[sortx]
        sorted_dnids = unique_dnids[sortx]
        success = (sorted_dnids == qnid)
        failure = np.logical_and((~ success), (sorted_dnids > 0))
        gt_name_rank = (None if (not np.any(success)) else np.where(success)[0][0])
        gf_name_rank = (None if (not np.any(failure)) else np.nonzero(failure)[0][0])
        gt_nid = sorted_dnids[gt_name_rank]
        gf_nid = sorted_dnids[gf_name_rank]
        gt_name_score = sorted_namescores[gt_name_rank]
        gf_name_score = sorted_namescores[gf_name_rank]
        if (gt_name_score <= 0):
            if hasattr(qreq_, 'dnids'):
                gt_name_rank = (len(qreq_.dnids) + 1)
            else:
                dnids = list(set(ibs.get_annot_nids(qreq_.daids)))
                gt_name_rank = (len(dnids) + 1)
        qnx2_nameres_info = {}
        qnx2_nameres_info['qnid'] = qnid
        qnx2_nameres_info['gt_nid'] = gt_nid
        qnx2_nameres_info['gf_nid'] = gf_nid
        qnx2_nameres_info['gt_name_rank'] = gt_name_rank
        qnx2_nameres_info['gf_name_rank'] = gf_name_rank
        qnx2_nameres_info['gt_name_score'] = gt_name_score
        qnx2_nameres_info['gf_name_score'] = gf_name_score
        nameres_info_list.append(qnx2_nameres_info)
        nameres_info = ut.dict_stack(nameres_info_list, 'qnx2_')
        cmsinfo.update(nameres_info)
    return cmsinfo