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.
"""
from __future__ import absolute_import, division, print_function, unicode_literals
import six
from six.moves import zip, map, range
from wbia import constants as const
import utool as ut
from functools import partial

(print, rrr, profile) = ut.inject2(__name__)

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(six.text_type, 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: print( '[guiheaders] infering getter for tablename=%r, colname=%r' % (tablename, colname,) ) # print('[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