Source code for ibeis.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
from six.moves import zip, map, range
from ibeis import constants as const
import utool as ut
from functools import partial
#from ibeis.control import
(print, rrr, profile) = ut.inject2(__name__, '[headers]')

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 ibeis 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 'yaw_text', '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', #'annot_semantic_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', 'yaw_text', 'quality_text', 'age_min', 'age_max', 'sex_text', 'imagesettext_names', 'datetime', 'max_hourdiff', 'max_speed', 'namenotes', ], IMAGE_GRID : [ 'thumb', ], # TEST TABLE THUMB_TABLE : [ 'img_gname', 'thumb', ], } # dynamicly defined headers if not const.SIMPLIFY_INTERFACE: from ibeis.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', ]) 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, 'yaw_text': 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, }, } # the columns which are editable TABLE_EDITSET = { IMAGE_TABLE : set(['reviewed', 'imgnotes']), ANNOTATION_TABLE : set(['name', 'species', 'annotnotes', 'exemplar', 'yaw', 'yaw_text', 'quality_text', 'age_min', 'age_max', 'sex_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', 'yaw', 'yaw_text', '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_semantic_uuid', (str, 'Annot Semantic UUID')), ('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')), ('yaw', (str, 'Yaws')), ('yaw_text', (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')), ('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')), ('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 #---- # Define the special metadata for annotation #def expand_special_colnames(annot_metadata): # global COL_DEF # for name, nice, valid in annot_metadata: # #TABLE_COLNAMES[ANNOTATION_TABLE] # if isinstance(valid, list): # type_ = str # else: # type_ = valid # COL_DEF[name] = (type_, nice) #expand_special_colnames(const.ROSEMARY_ANNOT_METADATA) #----- #def get_redirects(ibs): # """ # Allows one to specify a column in a particular table to redirect the view # to a different view (like a link in HTML to a different page) # """ # redirects = {} # # Annotation redirects # # redirects[ANNOTATION_TABLE] = { # # 'annot_gname' : (IMAGE_TABLE, ibs.get_annot_gids), # # } # # Return the redirects dictionary # return redirects
[docs]def make_ibeis_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 partial_imap_1to1 = ut.partial_imap_1to1 # # 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 #ibs.cfg.other_cfg.ensure_attr(show_shipped_imagesets, ut.is_developer()) 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, } 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' : lambda gids: gids, 'imgsetid' : ibs.get_image_imgsetids, 'imagesettext' : partial_imap_1to1(ut.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, '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(ut.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, } # +-------------------------- # 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' : lambda aids: aids, 'name' : ibs.get_annot_names, 'species' : ibs.get_annot_species_texts, 'yaw' : ibs.get_annot_yaws, 'yaw_text' : ibs.get_annot_yaw_texts, '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, 'annot_semantic_uuid' : ibs.get_annot_semantic_uuids, 'datetime' : ibs.get_annot_image_datetime, } infer_unspecified_getters(ANNOTATION_TABLE, 'annot') setters[ANNOTATION_TABLE] = { 'name' : ibs.set_annot_names, 'species' : ibs.set_annot_species_and_notify, 'yaw' : ibs.set_annot_yaws, 'yaw_text' : ibs.set_annot_yaw_texts, '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, } # +-------------------------- # Name Iders/Setters/Getters iders[NAME_TABLE] = [ibs.get_valid_nids] getters[NAME_TABLE] = { 'nid' : lambda nids: nids, 'name' : ibs.get_name_texts, 'nAids' : ibs.get_name_num_annotations, 'namenotes' : ibs.get_name_notes, } 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' : lambda nids: nids, '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' : lambda aids: aids, '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, 'yaw_text' : getters[ANNOTATION_TABLE]['yaw_text'], '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'], 'yaw_text' : setters[ANNOTATION_TABLE]['yaw_text'], '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