Source code for wbia.gui.guiheaders

# -*- coding: utf-8 -*-
"""
This model provides the declarative interface to all of the api_*_models
in guitool. Each different type of model/view has to register its iders,
getters, and potentially setters (hopefully if guitool ever gets off the
ground the delters as well)

Different columns can be hidden / shown by modifying this file

TODO: need to cache the total number of annotations or something about
imagesets on disk to help startuptime.
"""
import logging
from wbia import constants as const
import utool as ut
from functools import partial

(print, rrr, profile) = ut.inject2(__name__)
logger = logging.getLogger('wbia')

IMAGESET_TABLE = const.IMAGESET_TABLE
IMAGE_TABLE = const.IMAGE_TABLE
ANNOTATION_TABLE = const.ANNOTATION_TABLE
IMAGE_GRID = 'image_grid'
NAME_TABLE = 'names'
NAMES_TREE = 'names_tree'
QRES_TABLE = 'qres'
THUMB_TABLE = 'thumbs'

# -----------------
# Define the tables
# -----------------


[docs]def make_table_declarations(ibs): """ these used to be global variables, hopefully we can make them a little more configurable """ # available tables TABLENAME_LIST = [ IMAGE_TABLE, ANNOTATION_TABLE, # NAME_TABLE, IMAGESET_TABLE, IMAGE_GRID, THUMB_TABLE, NAMES_TREE, ] # table nice names TABLE_NICE = { IMAGE_TABLE: 'Image Table', ANNOTATION_TABLE: 'Annotations Table', NAME_TABLE: 'Name Table', QRES_TABLE: 'Query Results Table', IMAGESET_TABLE: 'ImageSet Table', IMAGE_GRID: 'Thumbnail Grid', THUMB_TABLE: 'Thumbnail Table', NAMES_TREE: 'Tree of Names', } # COLUMN DEFINITIONS # the columns each wbia table has, TABLE_COLNAMES = { IMAGE_TABLE: [ 'gid', 'thumb', # 'nAids', 'img_gname', # 'ext', 'reviewed', # detection reviewed flag is not fullyused 'datetime', 'gps', 'orientation', 'party_tag', 'contributor_tag', # 'gdconf', 'imgnotes', 'image_uuid', ], # debug with # --noannottbl # --nonametree # even just aid seems to be very slow ANNOTATION_TABLE: [ # 'annotation_uuid', 'aid', 'thumb', 'annot_gname', 'name', 'exemplar', 'species', # <put back in 'viewpoint', 'quality_text', 'age_min', 'age_max', 'sex_text', # 'rdconf', # 'nGt', # ## <put back in 'imagesettext_names', 'annotnotes', # ## <put back in 'tag_text', # < Hack should have actual tag structure # 'annot_visual_uuid', # 'nFeats', # 'bbox', # 'theta', # 'verts', # 'num_verts', ], NAME_TABLE: ['nid', 'name', 'nAids', 'namenotes'], QRES_TABLE: ['rank', 'score', 'name', 'aid'], IMAGESET_TABLE: [ 'imagesettext', 'nImgs', # 'num_imgs_reviewed', # 'num_annotmatch_reviewed', # 'imageset_end_datetime', # 'imageset_processed_flag', # 'imageset_shipped_flag', 'imgsetid', ], NAMES_TREE: [ 'name', 'nAids', 'thumb', 'nid', # 'exemplar', # 'nExAids', 'aid', # 'annot_gname', # 'quality_text', # 'age_min', # 'age_max', # 'sex_text', # 'imagesettext_names', # 'datetime', # 'max_hourdiff', # 'max_speed', # 'has_split', # 'namenotes', ], IMAGE_GRID: ['thumb'], # TEST TABLE THUMB_TABLE: ['img_gname', 'thumb'], } # dynamicly defined headers if not const.SIMPLIFY_INTERFACE: from wbia.control import accessor_decors if accessor_decors.API_CACHE: # Too slow without api cache TABLE_COLNAMES[IMAGESET_TABLE].extend( ['percent_annotmatch_reviewed_str', 'percent_names_with_exemplar_str'] ) TABLE_COLNAMES[IMAGESET_TABLE].extend( [ # 'percent_imgs_reviewed_str', 'imageset_start_datetime', # 'imageset_end_datetime', 'imageset_duration', 'imageset_notes', ] ) if ibs.cfg.other_cfg.show_shipped_imagesets: TABLE_COLNAMES[IMAGESET_TABLE].extend( ['imageset_processed_flag', 'imageset_shipped_flag'] ) # THUMB_TABLE : ['thumb' 'thumb' 'thumb' 'thumb'], # NAMES_TREE : {('name' 'nid' 'nAids') : ['aid' 'bbox' 'thumb']} TABLE_TREE_LEVELS = { NAMES_TREE: { 'name': 0, 'namenotes': 0, 'nid': 0, 'nAids': 0, 'nExAids': 0, 'sex_text': 0, 'exemplar': 1, 'thumb': 1, 'viewpoint': 1, 'quality_text': 1, 'age_min': 1, 'age_max': 1, 'imagesettext_names': 1, 'aid': 1, 'annot_gname': 1, 'datetime': 1, 'max_hourdiff': 0, 'max_speed': 0, 'has_split': 0, }, } # the columns which are editable TABLE_EDITSET = { IMAGE_TABLE: set(['reviewed', 'imgnotes', 'gps']), ANNOTATION_TABLE: set( [ 'name', 'species', 'annotnotes', 'exemplar', 'viewpoint', 'quality_text', 'age_min', 'age_max', 'sex_text', 'tag_text', ] ), NAME_TABLE: set(['name', 'namenotes']), QRES_TABLE: set(['name']), IMAGESET_TABLE: set( ['imagesettext', 'imageset_shipped_flag', 'imageset_processed_flag'] ), IMAGE_GRID: set([]), THUMB_TABLE: set([]), NAMES_TREE: set( [ 'exemplar', 'name', 'namenotes', 'viewpoint', 'quality_text', 'age_min', 'age_max', 'sex_text', ] ), } if const.SIMPLIFY_INTERFACE: TABLE_EDITSET[NAMES_TREE].remove('name') TABLE_HIDDEN_LIST = { # IMAGE_TABLE : [False, True, False, False, False, True, False, False, False, False, False], # ANNOTATION_TABLE : [False, False, False, False, False, False, False, True, True, True, True, True, True], # NAMES_TREE : [False, False, False, False, False, False], # NAME_TABLE : [False, False, False, False], } TABLE_STRIPE_LIST = { IMAGE_GRID: 9, } # Define the valid columns a table could have COL_DEF = dict( [ ('annot_visual_uuid', (str, 'Annot Visual UUID')), ('image_uuid', (str, 'Image UUID')), ('gid', (int, 'Image ID')), ('aid', (int, 'Annotation ID')), ('nid', (int, 'Name ID')), ('imgsetid', (int, 'ImageSet ID')), ('nAids', (int, '#Annots')), ('nExAids', (int, '#Exemplars')), ('nGt', (int, '#GT')), ('nImgs', (int, '#Imgs')), ('nFeats', (int, '#Features')), ('quality_text', (str, 'Quality')), ('imagesettext_names', (str, 'ImageSet Names')), ('age_min', (int, 'Age (min)')), ('age_max', (int, 'Age (max)')), ('sex_text', (str, 'Sex')), ('rank', (str, 'Rank')), # needs to be a string for !Query ('unixtime', (float, 'unixtime')), ('species', (str, 'Species')), ('viewpoint', (str, 'Viewpoint')), ('img_gname', (str, 'Image Name')), ('annot_gname', (str, 'Source Image')), ('gdconf', (str, 'Detection Confidence')), ('rdconf', (float, 'Detection Confidence')), ('name', (str, 'Name')), ('annotnotes', (str, 'Annot Notes')), ('namenotes', (str, 'Name Notes')), ('imgnotes', (str, 'Image Notes')), ('match_name', (str, 'Matching Name')), ('bbox', (str, 'BBOX (x, y, w, h))')), # Non editables are safe as strs ('num_verts', (int, 'NumVerts')), ('verts', (str, 'Verts')), ('score', (str, 'Confidence')), ('theta', (str, 'Theta')), ('reviewed', (bool, 'Detection Reviewed')), ('exemplar', (bool, 'Is Exemplar')), ('imagesettext', (str, 'ImageSet')), ('datetime', (str, 'Date / Time')), ('ext', (str, 'EXT')), ('thumb', ('PIXMAP', 'Thumb')), ('gps', (str, 'GPS')), ('orientation', (str, 'Orientation')), ('imageset_processed_flag', (bool, 'Processed')), ('imageset_shipped_flag', (bool, 'Commited')), ('imageset_start_datetime', (str, 'Start Time')), ('imageset_end_datetime', (str, 'End Time')), ('imageset_duration', (str, 'Duration')), ('imageset_notes', (str, 'Notes')), ('party_tag', (str, 'Party')), ('contributor_tag', (str, 'Contributor')), ('percent_imgs_reviewed_str', (str, '%Imgs Reviewed')), ('percent_annotmatch_reviewed_str', (str, '%Queried')), ('num_imgs_reviewed', (str, '#Imgs Reviewed')), ('num_annotmatch_reviewed', (str, '#Matches Reviewed')), ('percent_names_with_exemplar_str', (str, '%Names with Exemplar')), ('max_speed', (float, 'Max Speed km/h')), ('has_split', (float, 'Needs Split')), ('max_hourdiff', (float, 'Max Hour Diff')), ('tag_text', (str, 'Tags')), ] ) declare_tup = ( TABLENAME_LIST, TABLE_NICE, TABLE_COLNAMES, TABLE_TREE_LEVELS, TABLE_EDITSET, TABLE_HIDDEN_LIST, TABLE_STRIPE_LIST, COL_DEF, ) return declare_tup
# ----
[docs]def partial_imap_1to1(func, si_func): import functools @functools.wraps(si_func) def wrapper(input_): if not ut.isiterable(input_): return func(si_func(input_)) else: return list(map(func, si_func(input_))) ut.set_funcname( wrapper, ut.get_callable_name(func) + '_mapper_' + ut.get_funcname(si_func) ) return wrapper
def _tupstr(tuple_): """maps each item in tuple to a string and doesnt include parens""" return ', '.join(list(map(str, tuple_)))
[docs]def make_wbia_headers_dict(ibs): declare_tup = make_table_declarations(ibs) ( TABLENAME_LIST, TABLE_NICE, TABLE_COLNAMES, TABLE_TREE_LEVELS, TABLE_EDITSET, TABLE_HIDDEN_LIST, TABLE_STRIPE_LIST, COL_DEF, ) = declare_tup # # Table Iders/Setters/Getters iders = {} setters = {} getters = {} widths = {} def infer_unspecified_getters(tablename, shortname): for colname in TABLE_COLNAMES[tablename]: if colname not in getters[tablename]: if ut.VERBOSE: logger.info( '[guiheaders] infering getter for tablename=%r, colname=%r' % (tablename, colname) ) # logger.info('[guiheaders] infering %r' % (getters[tablename][colname],)) try: getters[tablename][colname] = getattr( ibs, 'get_' + shortname + '_' + colname ) except AttributeError: # we have inconsistently put in column names # try to "just make things work" getters[tablename][colname] = getattr(ibs, 'get_' + colname) # +-------------------------- # ImageSet Iders/Setters/Getters SHOW_SHIPPED_IMAGESETS = ibs.cfg.other_cfg.show_shipped_imagesets # SHOW_SHIPPED_IMAGESETS = True if SHOW_SHIPPED_IMAGESETS: iders[IMAGESET_TABLE] = [ibs.get_valid_imgsetids] else: iders[IMAGESET_TABLE] = [partial(ibs.get_valid_imgsetids, shipped=False)] getters[IMAGESET_TABLE] = { 'imgsetid': lambda imgsetids: imgsetids, 'nImgs': ibs.get_imageset_num_gids, 'imagesettext': ibs.get_imageset_text, 'imageset_shipped_flag': ibs.get_imageset_shipped_flags, 'imageset_processed_flag': ibs.get_imageset_processed_flags, # 'imageset_start_datetime': partial_imap_1to1( ut.unixtime_to_datetimestr, ibs.get_imageset_start_time_posix ), 'imageset_end_datetime': partial_imap_1to1( ut.unixtime_to_datetimestr, ibs.get_imageset_end_time_posix ), # 'imageset_start_time_posix': ibs.get_imageset_start_time_posix, 'imageset_end_time_posix': ibs.get_imageset_end_time_posix, 'imageset_duration': ibs.get_imageset_duration, 'imageset_notes': ibs.get_imageset_note, } infer_unspecified_getters(IMAGESET_TABLE, 'imageset') setters[IMAGESET_TABLE] = { 'imagesettext': ibs.set_imageset_text, 'imageset_shipped_flag': ibs.set_imageset_shipped_flags, 'imageset_processed_flag': ibs.set_imageset_processed_flags, } widths[IMAGESET_TABLE] = { 'nImgs': 55, } # +-------------------------- # Image Iders/Setters/Getters iders[IMAGE_TABLE] = [ibs.get_valid_gids] getters[IMAGE_TABLE] = { 'gid': ut.identity, 'imgsetid': ibs.get_image_imgsetids, 'imagesettext': partial_imap_1to1(_tupstr, ibs.get_image_imagesettext), 'reviewed': ibs.get_image_reviewed, 'img_gname': ibs.get_image_gnames, 'nAids': ibs.get_image_num_annotations, 'unixtime': ibs.get_image_unixtime, 'datetime': ibs.get_image_datetime_str, 'gdconf': ibs.get_image_detect_confidence, 'imgnotes': ibs.get_image_notes, 'image_uuid': ibs.get_image_uuids, 'ext': ibs.get_image_exts, 'thumb': ibs.get_image_thumbtup, 'gps': partial_imap_1to1(_tupstr, ibs.get_image_gps), 'orientation': ibs.get_image_orientation_str, } infer_unspecified_getters(IMAGE_TABLE, 'image') setters[IMAGE_TABLE] = { 'reviewed': ibs.set_image_reviewed, 'imgnotes': ibs.set_image_notes, 'gps': ibs.set_image_gps_str, } # +-------------------------- # IMAGE GRID iders[IMAGE_GRID] = [ibs.get_valid_gids] getters[IMAGE_GRID] = { 'thumb': ibs.get_image_thumbtup, 'img_gname': ibs.get_image_gnames, 'aid': ibs.get_image_aids, } setters[IMAGE_GRID] = {} # +-------------------------- # ANNOTATION Iders/Setters/Getters iders[ANNOTATION_TABLE] = [ibs.get_valid_aids] getters[ANNOTATION_TABLE] = { 'aid': ut.identity, 'name': ibs.get_annot_names, 'species': ibs.get_annot_species_texts, 'viewpoint': ibs.get_annot_viewpoints, 'quality_text': ibs.get_annot_quality_texts, 'imagesettext_names': ibs.get_annot_image_set_texts, 'age_min': ibs.get_annot_age_months_est_min, 'age_max': ibs.get_annot_age_months_est_max, 'sex_text': ibs.get_annot_sex_texts, 'annot_gname': ibs.get_annot_image_names, 'nGt': ibs.get_annot_num_groundtruth, 'theta': partial_imap_1to1(ut.theta_str, ibs.get_annot_thetas), 'bbox': partial_imap_1to1(ut.bbox_str, ibs.get_annot_bboxes), 'num_verts': ibs.get_annot_num_verts, 'verts': partial_imap_1to1(ut.verts_str, ibs.get_annot_verts), 'nFeats': ibs.get_annot_num_feats, 'rdconf': ibs.get_annot_detect_confidence, 'annotnotes': ibs.get_annot_notes, 'thumb': ibs.get_annot_chip_thumbtup, 'exemplar': ibs.get_annot_exemplar_flags, 'annot_visual_uuid': ibs.get_annot_visual_uuids, 'datetime': ibs.get_annot_image_datetime_str, } infer_unspecified_getters(ANNOTATION_TABLE, 'annot') setters[ANNOTATION_TABLE] = { 'name': ibs.set_annot_names, 'species': ibs.set_annot_species_and_notify, 'viewpoint': ibs.set_annot_viewpoints, 'age_min': ibs.set_annot_age_months_est_min, 'age_max': ibs.set_annot_age_months_est_max, 'sex_text': ibs.set_annot_sex_texts, 'annotnotes': ibs.set_annot_notes, 'exemplar': ibs.set_annot_exemplar_flags, 'quality_text': ibs.set_annot_quality_texts, 'tag_text': ibs.set_annot_tag_text, } # +-------------------------- # Name Iders/Setters/Getters iders[NAME_TABLE] = [ibs.get_valid_nids] getters[NAME_TABLE] = { 'nid': ut.identity, 'name': ibs.get_name_texts, 'nAids': ibs.get_name_num_annotations, 'namenotes': ibs.get_name_notes, # 'has_split' : ibs.get_name_has_split, } setters[NAME_TABLE] = { 'name': ibs.set_name_texts, 'namenotes': ibs.set_name_notes, } # +-------------------------- # NAMES TREE iders[NAMES_TREE] = [ibs.get_valid_nids, ibs.get_name_aids] getters[NAMES_TREE] = { # level 0 'nid': ut.identity, 'name': ibs.get_name_texts, 'nAids': ibs.get_name_num_annotations, 'nExAids': ibs.get_name_num_exemplar_annotations, 'namenotes': ibs.get_name_notes, 'sex_text': ibs.get_name_sex_text, # level 1 'aid': ut.identity, 'exemplar': ibs.get_annot_exemplar_flags, 'thumb': ibs.get_annot_chip_thumbtup, 'annot_gname': ibs.get_annot_image_names, 'age_min': ibs.get_annot_age_months_est_min, 'age_max': ibs.get_annot_age_months_est_max, 'imagesettext_names': ibs.get_annot_image_set_texts, 'viewpoint': getters[ANNOTATION_TABLE]['viewpoint'], 'quality_text': getters[ANNOTATION_TABLE]['quality_text'], 'datetime': getters[ANNOTATION_TABLE]['datetime'], } setters[NAMES_TREE] = { 'name': ibs.set_name_texts, 'namenotes': ibs.set_name_notes, 'sex_text': ibs.set_name_sex_text, 'age_min': ibs.set_annot_age_months_est_min, 'age_max': ibs.set_annot_age_months_est_max, 'exemplar': setters[ANNOTATION_TABLE]['exemplar'], 'viewpoint': setters[ANNOTATION_TABLE]['viewpoint'], 'quality_text': setters[ANNOTATION_TABLE]['quality_text'], } widths[NAMES_TREE] = { 'thumb': lambda: ibs.cfg.other_cfg.thumb_size, 'nAids': 65, 'nid': 50, } infer_unspecified_getters(NAMES_TREE, 'name') # +-------------------------- # THUMB TABLE iders[THUMB_TABLE] = [ibs.get_valid_gids] getters[THUMB_TABLE] = { 'thumb': ibs.get_image_thumbtup, 'img_gname': ibs.get_image_gnames, 'aid': ibs.get_image_aids, } setters[THUMB_TABLE] = {} # L________________________ def make_header(tblname): """ Args: table_name - the internal table name """ tblnice = TABLE_NICE[tblname] colnames = TABLE_COLNAMES[tblname] editset = TABLE_EDITSET[tblname] tblgetters = getters[tblname] tblsetters = setters[tblname] # if levels aren't found, we're not dealing with a tree, so everything is at level 0 collevel_dict = TABLE_TREE_LEVELS.get(tblname, ut.ddict(lambda: 0)) collevels = [collevel_dict[colname] for colname in colnames] hiddencols = TABLE_HIDDEN_LIST.get(tblname, [False for _ in range(len(colnames))]) numstripes = TABLE_STRIPE_LIST.get(tblname, 1) colwidths_dict = widths.get(tblname, {}) colwidths = [colwidths_dict.get(colname, 100) for colname in colnames] def get_column_data(colname): try: coldef_tup = COL_DEF[colname] coltype, colnice = coldef_tup except KeyError as ex: strict = False ut.printex( ex, 'Need to add type info for colname=%r to COL_DEF' % colname, iswarning=not strict, ) if strict: raise else: # default coldef to give a string type and nice=colname coltype, colnice = (str, colname) coledit = colname in editset colgetter = tblgetters[colname] colsetter = None if not coledit else tblsetters.get(colname, None) return (coltype, colnice, coledit, colgetter, colsetter) try: _tuplist = list(zip(*list(map(get_column_data, colnames)))) (coltypes, colnices, coledits, colgetters, colsetters) = _tuplist except KeyError as ex: ut.printex(ex, key_list=['tblname', 'colnames']) raise header = { 'name': tblname, 'nice': tblnice, 'iders': iders[tblname], 'col_name_list': colnames, 'col_type_list': coltypes, 'col_nice_list': colnices, 'col_edit_list': coledits, 'col_getter_list': colgetters, 'col_setter_list': colsetters, 'col_level_list': collevels, 'col_hidden_list': hiddencols, 'num_duplicates': numstripes, 'get_thumb_size': lambda: ibs.cfg.other_cfg.thumb_size, 'col_width_list': colwidths, # TODO } return header header_dict = {tblname: make_header(tblname) for tblname in TABLENAME_LIST} return header_dict, declare_tup