def dbstr_qindex(qindex_=None): qindex = ut.get_localvar_from_stack('qindex') common_wxs = ut.get_localvar_from_stack('common_wxs') wx2_qaids = ut.get_localvar_from_stack('wx2_qaids') qindex.query_sccw qmaws_list = [qindex.wx2_maws[wx] for wx in common_wxs] qaids_list = [qindex.wx2_qaids[wx] for wx in common_wxs] qfxs_list = [qindex.wx2_qfxs[wx] for wx in common_wxs] qrvecs_list = [qindex.wx2_qrvecs[wx] for wx in common_wxs] qaids_list = [wx2_qaids[wx] for wx in common_wxs] print('-- max --') print('list_depth(qaids_list) = %d' % ut.list_depth(qaids_list, max)) print('list_depth(qmaws_list) = %d' % ut.list_depth(qmaws_list, max)) print('list_depth(qfxs_list) = %d' % ut.list_depth(qfxs_list, max)) print('list_depth(qrvecs_list) = %d' % ut.list_depth(qrvecs_list, max)) print('-- min --') print('list_depth(qaids_list) = %d' % ut.list_depth(qaids_list, min)) print('list_depth(qmaws_list) = %d' % ut.list_depth(qmaws_list, min)) print('list_depth(qfxs_list) = %d' % ut.list_depth(qfxs_list, min)) print('list_depth(qrvecs_list) = %d' % ut.list_depth(qrvecs_list, min)) print('-- sig --') print('list_depth(qaids_list) = %r' % ut.depth_profile(qaids_list)) print('list_depth(qmaws_list) = %r' % ut.depth_profile(qmaws_list)) print('list_depth(qfxs_list) = %r' % ut.depth_profile(qfxs_list)) print('list_depth(qrvecs_list) = %r' % ut.depth_profile(ut.depth_profile(qrvecs_list))) print(qfxs_list[0:3]) print(qaids_list[0:3]) print(qmaws_list[0:3])
def multidb_montage(): r""" CommandLine: python -m ibeis.scripts.specialdraw multidb_montage --save montage.jpg --dpath ~/slides --diskshow --show Example: >>> # DISABLE_DOCTEST >>> from ibeis.scripts.specialdraw import * # NOQA >>> multidb_montage() """ import ibeis import plottool as pt import vtool as vt import numpy as np pt.ensure_pylab_qt4() ibs1 = ibeis.opendb('PZ_MTEST') ibs2 = ibeis.opendb('GZ_ALL') ibs3 = ibeis.opendb('GIRM_Master1') chip_lists = [] aids_list = [] for ibs in [ibs1, ibs2, ibs3]: aids = ibs.sample_annots_general(minqual='good', sample_size=400) aids_list.append(aids) print(ut.depth_profile(aids_list)) for ibs, aids in zip([ibs1, ibs2, ibs3], aids_list): chips = ibs.get_annot_chips(aids) chip_lists.append(chips) chip_list = ut.flatten(chip_lists) np.random.shuffle(chip_list) widescreen_ratio = 16 / 9 ratio = ut.PHI ratio = widescreen_ratio fpath = pt.get_save_directions() #height = 6000 width = 6000 #width = int(height * ratio) height = int(width / ratio) dsize = (width, height) dst = vt.montage(chip_list, dsize) vt.imwrite(fpath, dst) if ut.get_argflag('--show'): pt.imshow(dst)
def get_square_data(metadata, cfgstr=None): # can only support one config at a time right now if cfgstr is None: cfgstr = metadata.get_cfgstr_list()[0] qaid2_cols = metadata.dictstore[cfgstr] qaids = list(qaid2_cols.keys()) col_name_list = ut.unique_keep_order(ut.flatten([cols.keys() for cols in qaid2_cols.values()])) #col_name_list = ['qx2_scoreexpdiff', 'qx2_gt_aid'] #colname2_colvals = [None for colname in col_name_list] column_list = [ [colvals.get(colname, None) for qaid, colvals in six.iteritems(qaid2_cols)] for colname in col_name_list] col_name_list = ['qaids'] + col_name_list column_list = [qaids] + column_list print('depth_profile(column_list) = %r' % (ut.depth_profile(column_list),)) return col_name_list, column_list
def get_square_data(metadata, cfgstr=None): # can only support one config at a time right now if cfgstr is None: cfgstr = metadata.get_cfgstr_list()[0] qaid2_cols = metadata.dictstore[cfgstr] qaids = list(qaid2_cols.keys()) col_name_list = ut.unique_ordered(ut.flatten([cols.keys() for cols in qaid2_cols.values()])) #col_name_list = ['qx2_scoreexpdiff', 'qx2_gt_aid'] #colname2_colvals = [None for colname in col_name_list] column_list = [ [colvals.get(colname, None) for qaid, colvals in six.iteritems(qaid2_cols)] for colname in col_name_list] col_name_list = ['qaids'] + col_name_list column_list = [qaids] + column_list print('depth_profile(column_list) = %r' % (ut.depth_profile(column_list),)) return col_name_list, column_list
def detect_opencv_keypoints(): import cv2 import vtool as vt import numpy as np # NOQA #img_fpath = ut.grab_test_imgpath(ut.get_argval('--fname', default='lena.png')) img_fpath = ut.grab_test_imgpath( ut.get_argval('--fname', default='zebra.png')) imgBGR = vt.imread(img_fpath) imgGray = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2GRAY) def from_cv2_kpts(cv2_kp): kp = (cv2_kp.pt[0], cv2_kp.pt[1], cv2_kp.size, 0, cv2_kp.size, cv2_kp.angle) return kp print('\n'.join(ut.search_module(cv2, 'create', recursive=True))) detect_factory = { #'BLOB': cv2.SimpleBlobDetector_create, #'HARRIS' : HarrisWrapper.create, #'SIFT': cv2.xfeatures2d.SIFT_create, # really DoG 'SURF': cv2.xfeatures2d.SURF_create, # really harris corners 'MSER': cv2.MSER_create, #'StarDetector_create', } extract_factory = { 'SIFT': cv2.xfeatures2d.SIFT_create, 'SURF': cv2.xfeatures2d.SURF_create, #'DAISY': cv2.xfeatures2d.DAISY_create, 'FREAK': cv2.xfeatures2d.FREAK_create, #'LATCH': cv2.xfeatures2d.LATCH_create, #'LUCID': cv2.xfeatures2d.LUCID_create, #'ORB': cv2.ORB_create, } mask = None type_to_kpts = {} type_to_desc = {} key = 'BLOB' key = 'MSER' for key in detect_factory.keys(): factory = detect_factory[key] extractor = factory() # For MSERS need to adapt shape and then convert into a keypoint repr if hasattr(extractor, 'detectRegions'): # bboxes are x,y,w,h regions, bboxes = extractor.detectRegions(imgGray) # ellipse definition from [Fitzgibbon95] # http://www.bmva.org/bmvc/1995/bmvc-95-050.pdf p518 # ell = [c_x, c_y, R_x, R_y, theta] # (cx, cy) = conic center # Rx and Ry = conic radii # theta is the counterclockwise angle fitz_ellipses = [cv2.fitEllipse(mser) for mser in regions] # http://answers.opencv.org/question/19015/how-to-use-mser-in-python/ #hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions] #hull_ells = [cv2.fitEllipse(hull[:, 0]) for hull in hulls] kpts_ = [] for ell in fitz_ellipses: ((cx, cy), (rx, ry), degrees) = ell theta = np.radians(degrees) # opencv lives in radians S = vt.scale_mat3x3(rx, ry) T = vt.translation_mat3x3(cx, cy) R = vt.rotation_mat3x3(theta) #R = np.eye(3) invVR = T.dot(R.dot(S)) kpt = vt.flatten_invV_mats_to_kpts(np.array([invVR]))[0] kpts_.append(kpt) kpts_ = np.array(kpts_) tt = ut.tic('Computing %r keypoints' % (key, )) try: cv2_kpts = extractor.detect(imgGray, mask) except Exception as ex: ut.printex(ex, 'Failed to computed %r keypoints' % (key, ), iswarning=True) pass else: ut.toc(tt) type_to_kpts[key] = cv2_kpts print(list(type_to_kpts.keys())) print(ut.depth_profile(list(type_to_kpts.values()))) print('type_to_kpts = ' + ut.repr3(type_to_kpts, truncate=True)) cv2_kpts = type_to_kpts['MSER'] kp = cv2_kpts[0] # NOQA #cv2.fitEllipse(cv2_kpts[0]) cv2_kpts = type_to_kpts['SURF'] for key in extract_factory.keys(): factory = extract_factory[key] extractor = factory() tt = ut.tic('Computing %r descriptors' % (key, )) try: filtered_cv2_kpts, desc = extractor.compute(imgGray, cv2_kpts) except Exception as ex: ut.printex(ex, 'Failed to computed %r descriptors' % (key, ), iswarning=True) pass else: ut.toc(tt) type_to_desc[key] = desc print(list(type_to_desc.keys())) print(ut.depth_profile(list(type_to_desc.values()))) print('type_to_desc = ' + ut.repr3(type_to_desc, truncate=True))
def detect_opencv_keypoints(): import cv2 import vtool as vt import numpy as np # NOQA #img_fpath = ut.grab_test_imgpath(ut.get_argval('--fname', default='lena.png')) img_fpath = ut.grab_test_imgpath(ut.get_argval('--fname', default='zebra.png')) imgBGR = vt.imread(img_fpath) imgGray = cv2.cvtColor(imgBGR, cv2.COLOR_BGR2GRAY) def from_cv2_kpts(cv2_kp): kp = (cv2_kp.pt[0], cv2_kp.pt[1], cv2_kp.size, 0, cv2_kp.size, cv2_kp.angle) return kp print('\n'.join(ut.search_module(cv2, 'create', recursive=True))) detect_factory = { #'BLOB': cv2.SimpleBlobDetector_create, #'HARRIS' : HarrisWrapper.create, #'SIFT': cv2.xfeatures2d.SIFT_create, # really DoG 'SURF': cv2.xfeatures2d.SURF_create, # really harris corners 'MSER': cv2.MSER_create, #'StarDetector_create', } extract_factory = { 'SIFT': cv2.xfeatures2d.SIFT_create, 'SURF': cv2.xfeatures2d.SURF_create, #'DAISY': cv2.xfeatures2d.DAISY_create, 'FREAK': cv2.xfeatures2d.FREAK_create, #'LATCH': cv2.xfeatures2d.LATCH_create, #'LUCID': cv2.xfeatures2d.LUCID_create, #'ORB': cv2.ORB_create, } mask = None type_to_kpts = {} type_to_desc = {} key = 'BLOB' key = 'MSER' for key in detect_factory.keys(): factory = detect_factory[key] extractor = factory() # For MSERS need to adapt shape and then convert into a keypoint repr if hasattr(extractor, 'detectRegions'): # bboxes are x,y,w,h regions, bboxes = extractor.detectRegions(imgGray) # ellipse definition from [Fitzgibbon95] # http://www.bmva.org/bmvc/1995/bmvc-95-050.pdf p518 # ell = [c_x, c_y, R_x, R_y, theta] # (cx, cy) = conic center # Rx and Ry = conic radii # theta is the counterclockwise angle fitz_ellipses = [cv2.fitEllipse(mser) for mser in regions] # http://answers.opencv.org/question/19015/how-to-use-mser-in-python/ #hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions] #hull_ells = [cv2.fitEllipse(hull[:, 0]) for hull in hulls] kpts_ = [] for ell in fitz_ellipses: ((cx, cy), (rx, ry), degrees) = ell theta = np.radians(degrees) # opencv lives in radians S = vt.scale_mat3x3(rx, ry) T = vt.translation_mat3x3(cx, cy) R = vt.rotation_mat3x3(theta) #R = np.eye(3) invVR = T.dot(R.dot(S)) kpt = vt.flatten_invV_mats_to_kpts(np.array([invVR]))[0] kpts_.append(kpt) kpts_ = np.array(kpts_) tt = ut.tic('Computing %r keypoints' % (key,)) try: cv2_kpts = extractor.detect(imgGray, mask) except Exception as ex: ut.printex(ex, 'Failed to computed %r keypoints' % (key,), iswarning=True) pass else: ut.toc(tt) type_to_kpts[key] = cv2_kpts print(list(type_to_kpts.keys())) print(ut.depth_profile(list(type_to_kpts.values()))) print('type_to_kpts = ' + ut.repr3(type_to_kpts, truncate=True)) cv2_kpts = type_to_kpts['MSER'] kp = cv2_kpts[0] # NOQA #cv2.fitEllipse(cv2_kpts[0]) cv2_kpts = type_to_kpts['SURF'] for key in extract_factory.keys(): factory = extract_factory[key] extractor = factory() tt = ut.tic('Computing %r descriptors' % (key,)) try: filtered_cv2_kpts, desc = extractor.compute(imgGray, cv2_kpts) except Exception as ex: ut.printex(ex, 'Failed to computed %r descriptors' % (key,), iswarning=True) pass else: ut.toc(tt) type_to_desc[key] = desc print(list(type_to_desc.keys())) print(ut.depth_profile(list(type_to_desc.values()))) print('type_to_desc = ' + ut.repr3(type_to_desc, truncate=True))
def make_score_tabular( row_lbls, col_lbls, values, title=None, out_of=None, bold_best=False, flip=False, bigger_is_better=True, multicol_lbls=None, FORCE_INT=False, precision=None, SHORTEN_ROW_LBLS=False, col_align='l', col_sep='|', multicol_sep='|', centerline=True, astable=False, table_position='', AUTOFIX_LATEX=True, **kwargs): r""" makes a LaTeX tabular for displaying scores or errors Args: row_lbls (list of str): col_lbls (list of str): values (ndarray): title (str): (default = None) out_of (None): (default = None) bold_best (bool): (default = True) flip (bool): (default = False) table_position (str) : eg '[h]' Returns: str: tabular_str CommandLine: python -m utool.util_latex --test-make_score_tabular:0 --show python -m utool.util_latex --test-make_score_tabular:1 --show python -m utool.util_latex --test-make_score_tabular:2 --show Example: >>> # DISABLE_DOCTEST >>> from utool.util_latex import * # NOQA >>> import utool as ut >>> row_lbls = ['config1', 'config2'] >>> col_lbls = ['score \leq 1', 'metric2'] >>> values = np.array([[1.2, 2], [3.2, 4]]) >>> title = 'title' >>> out_of = 10 >>> bold_best = True >>> flip = False >>> tabular_str = make_score_tabular(row_lbls, col_lbls, values, title, out_of, bold_best, flip) >>> result = tabular_str >>> print(result) >>> ut.quit_if_noshow() >>> render_latex_text(tabular_str) Example: >>> # DISABLE_DOCTEST >>> from utool.util_latex import * # NOQA >>> import utool as ut >>> row_lbls = ['config1'] >>> col_lbls = ['score \leq 1', 'metric2'] >>> values = np.array([[1.2, 2]]) >>> title = 'title' >>> out_of = 10 >>> bold_best = True >>> flip = False >>> tabular_str = make_score_tabular(row_lbls, col_lbls, values, title, out_of, bold_best, flip) >>> result = tabular_str >>> print(result) >>> ut.quit_if_noshow() >>> render_latex_text(tabular_str) Example: >>> # DISABLE_DOCTEST >>> from utool.util_latex import * # NOQA >>> import utool as ut >>> row_lbls = ['config1', 'config2'] >>> col_lbls = ['score \leq 1', 'metric2', 'foobar'] >>> multicol_lbls = [('spam', 1), ('eggs', 2)] >>> values = np.array([[1.2, 2, -3], [3.2, 4, -2]]) >>> title = 'title' >>> out_of = 10 >>> bold_best = True >>> flip = False >>> tabular_str = make_score_tabular(row_lbls, col_lbls, values, title, out_of, bold_best, flip, multicol_lbls=multicol_lbls) >>> result = tabular_str >>> print(result) >>> ut.quit_if_noshow() >>> render_latex_text(tabular_str) """ import utool as ut if flip: bigger_is_better = not bigger_is_better flip_repltups = [ ('<=', '>'), ('>', '<='), ('\\leq', '\\gt'), ('\\geq', '\\lt'), ('score', 'error') ] col_lbls = [replace_all(lbl, flip_repltups) for lbl in col_lbls] if title is not None: title = replace_all(title, flip_repltups) if out_of is not None: values = out_of - values # Abbreviate based on common substrings common_rowlbl = None if SHORTEN_ROW_LBLS: if isinstance(row_lbls, list): row_lbl_list = row_lbls else: row_lbl_list = row_lbls.flatten().tolist() # Split the rob labels into the alg components #algcomp_list = [lbl.split(')_') for lbl in row_lbl_list] longest = long_substr(row_lbl_list) common_strs = [] while len(longest) > 10: common_strs += [longest] row_lbl_list = [row.replace(longest, '...') for row in row_lbl_list] longest = long_substr(row_lbl_list) common_rowlbl = ('...'.join(common_strs)).replace(')_', ')_\n') row_lbls = row_lbl_list if len(row_lbl_list) == 1: common_rowlbl = row_lbl_list[0] row_lbls = ['0'] # Stack values into a tabular body # TODO: need ability to specify datatypes def ensurelist(row_values): try: return row_values.tolist() except AttributeError: return row_values if False: # Numpy formatting def padvec(shape=(1, 1)): pad = np.array([[' ' for c in range(shape[1])] for r in range(shape[0])]) return pad col_lbls = ensure_rowvec(col_lbls) row_lbls = ensure_colvec(row_lbls) _0 = np.vstack([padvec(), row_lbls]) _1 = np.vstack([col_lbls, values]) body = np.hstack([_0, _1]) body = [[str_ for str_ in row] for row in body] else: assert len(row_lbls) == len(values) body = [[' '] + col_lbls] body += [[row_lbl] + ensurelist(row_values) for row_lbl, row_values in zip(row_lbls, values)] #import utool as ut # Fix things in each body cell DO_PERCENT = True try: for r in range(len(body)): for c in range(len(body[0])): # In data land if r > 0 and c > 0: if precision is not None: # Hack if ut.is_float(body[r][c]): fmtstr = '%.' + str(precision) + 'f' body[r][c] = fmtstr % (float(body[r][c]),) # Force integer if FORCE_INT: body[r][c] = str(int(float(body[r][c]))) body[r][c] = str(body[r][c]) # Remove bad formatting; if AUTOFIX_LATEX: body[r][c] = escape_latex(body[r][c]) except Exception as ex: import utool as ut print('len(row_lbls) = %r' % (len(row_lbls),)) print('len(col_lbls) = %r' % (len(col_lbls),)) print('len(values) = %r' % (values,)) print('ut.depth_profile(values) = %r' % (ut.depth_profile(values),)) util_dbg.printex(ex, keys=['r', 'c']) raise # Bold the best values if bold_best: best_col_scores = values.max(0) if bigger_is_better else values.min(0) rows_to_bold = [np.where(values[:, colx] == best_col_scores[colx])[0] for colx in range(len(values.T))] for colx, rowx_list in enumerate(rows_to_bold): for rowx in rowx_list: body[rowx + 1][colx + 1] = '\\txtbf{' + body[rowx + 1][colx + 1] + '}' # More fixing after the bold is in place for r in range(len(body)): for c in range(len(body[0])): # In data land if r > 0 and c > 0: if out_of is not None: body[r][c] = body[r][c] + '/' + str(out_of) if DO_PERCENT: percent = ' = %.1f%%' % float(100 * values[r - 1, c - 1] / out_of) body[r][c] += escape_latex(percent) # Align columns for pretty printing body = np.array(body) ALIGN_BODY = True if ALIGN_BODY: new_body_cols = [] for col in body.T: colstrs = list(map(str, ensurelist(col))) collens = list(map(len, colstrs)) maxlen = max(collens) newcols = [str_ + (' ' * (maxlen - len(str_))) for str_ in colstrs] new_body_cols += [newcols] body = np.array(new_body_cols).T # Build Body (and row layout) HLINE_SEP = True rowvalsep = '' colvalsep = ' & ' endl = '\\\\\n' hline = r'\hline' #extra_rowsep_pos_list = [1] # rows to insert an extra hline after extra_rowsep_pos_list = [] # rows to insert an extra hline after if HLINE_SEP: rowvalsep = hline + '\n' # rowstr list holds blocks of rows rowstr_list = [colvalsep.join(row) + endl for row in body] #rowstr_list = [row[0] + rowlbl_sep + colvalsep.join(row[1:]) + endl for row in body] #rowstr_list = [( # ('' if len(row) == 0 else row[0]) # if len(row) <= 1 else # row[0] + rowlblcol_sep + colvalsep.join(row[1:]) + endl) # for row in body] rowsep_list = [rowvalsep for row in rowstr_list[0:-1]] # should be len 1 less than rowstr_list # Insert multicolumn names if multicol_lbls is not None: # TODO: label of the row labels multicol_sep multicols = [latex_multicolumn(multicol, size, 'c' + multicol_sep) for multicol, size in multicol_lbls] multicol_str = latex_multirow('', 2) + colvalsep + colvalsep.join(multicols) + endl ncols = sum([tup[1] for tup in multicol_lbls]) mcol_sep = '\\cline{2-%d}\n' % (ncols + 1,) rowstr_list = [multicol_str] + rowstr_list rowsep_list = [mcol_sep] + rowsep_list #extra_rowsep_pos_list += [1] # Insert title if title is not None and not astable: tex_title = latex_multicolumn(title, len(body[0])) + endl rowstr_list = [tex_title] + rowstr_list rowsep_list = [rowvalsep] + rowsep_list #extra_rowsep_pos_list += [2] # Apply an extra hline (for label) #extra_rowsep_pos_list = [] for pos in sorted(extra_rowsep_pos_list)[::-1]: rowstr_list.insert(pos, '') rowsep_list.insert(pos, rowvalsep) #tabular_body = rowvalsep.join(rowstr_list) from six.moves import zip_longest tabular_body = ''.join([row if sep is None else row + sep for row, sep in zip_longest(rowstr_list, rowsep_list)]) # Build Column Layout col_align_list = [col_align] * len(body[0]) #extra_collayoutsep_pos_list = [1] extra_collayoutsep_pos_list = [] for pos in sorted(extra_collayoutsep_pos_list)[::-1]: col_align_list.insert(pos, '') #col_layaout_sep_list = rowlblcol_sep # TODO rowlblcol_sep = '|' # Build build internal seprations between column alignments # Defaults to just the normal col_sep col_align_sep_list = [col_sep] * (len(col_align_list) - 1) # Adjust for the separations between row labels and the actual row data if len(col_align_sep_list) > 0: col_align_sep_list[0] = rowlblcol_sep # Continue multicolumn sepratation if multicol_lbls is not None: multicol_offsets = ut.cumsum(ut.get_list_column(multicol_lbls, 1)) for offset in multicol_offsets: if offset < len(col_align_sep_list): col_align_sep_list[offset] = multicol_sep from six.moves import zip_longest _tmp = [ut.filter_Nones(tup) for tup in zip_longest(col_align_list, col_align_sep_list)] col_layout = ''.join(ut.flatten(_tmp)) #if len(col_align_list) > 1: # col_layout = col_align_list[0] + rowlblcol_sep + col_sep.join(col_align_list[1:]) #else: # col_layout = col_sep.join(col_align_list) tabular_head = (r'\begin{tabular}{|%s|}' % col_layout) + '\n' tabular_tail = r'\end{tabular}' if centerline: tabular_head = r'\centerline{' + '\n' + tabular_head tabular_tail = tabular_tail + '}' if astable: #tabular_head = r'\begin{centering}' + '\n' + tabular_head tabular_head = r'\centering' + '\n' + tabular_head tabular_head = r'\begin{table}' + table_position + '\n' + tabular_head lblstr = latex_sanitize_command_name(kwargs.get('label', title)) caption = title if AUTOFIX_LATEX: caption = escape_latex(caption) caption = '\n% ---\n' + caption + '\n% ---\n' #tabular_head = r'\end{centering}' + '\n' + tabular_head tabular_tail = tabular_tail + '\n\caption[%s]{%s}\n\label{tbl:%s}\n\end{table}' % (lblstr, caption, lblstr) tabular_str = rowvalsep.join([tabular_head, tabular_body, tabular_tail]) topsep = '\\hline\n' if True else '\\toprule\n' botsep = '\\hline\n' if True else '\\bottomrule\n' tabular_str = tabular_head + topsep + tabular_body + botsep + tabular_tail if common_rowlbl is not None: #tabular_str += escape_latex('\n\nThe following parameters were held fixed:\n' + common_rowlbl) pass return tabular_str
def make_score_tabular(row_lbls, col_lbls, values, title=None, out_of=None, bold_best=False, flip=False, bigger_is_better=True, multicol_lbls=None, FORCE_INT=False, precision=None, SHORTEN_ROW_LBLS=False, col_align='l', col_sep='|', multicol_sep='|', centerline=True, astable=False, table_position='', AUTOFIX_LATEX=True, **kwargs): r""" makes a LaTeX tabular for displaying scores or errors Args: row_lbls (list of str): col_lbls (list of str): values (ndarray): title (str): (default = None) out_of (None): (default = None) bold_best (bool): (default = True) flip (bool): (default = False) table_position (str) : eg '[h]' Returns: str: tabular_str CommandLine: python -m utool.util_latex --test-make_score_tabular:0 --show python -m utool.util_latex --test-make_score_tabular:1 --show python -m utool.util_latex --test-make_score_tabular:2 --show Example: >>> # DISABLE_DOCTEST >>> from utool.util_latex import * # NOQA >>> import utool as ut >>> row_lbls = ['config1', 'config2'] >>> col_lbls = ['score \leq 1', 'metric2'] >>> values = np.array([[1.2, 2], [3.2, 4]]) >>> title = 'title' >>> out_of = 10 >>> bold_best = True >>> flip = False >>> tabular_str = make_score_tabular(row_lbls, col_lbls, values, title, out_of, bold_best, flip) >>> result = tabular_str >>> print(result) >>> ut.quit_if_noshow() >>> render_latex_text(tabular_str) Example: >>> # DISABLE_DOCTEST >>> from utool.util_latex import * # NOQA >>> import utool as ut >>> row_lbls = ['config1'] >>> col_lbls = ['score \leq 1', 'metric2'] >>> values = np.array([[1.2, 2]]) >>> title = 'title' >>> out_of = 10 >>> bold_best = True >>> flip = False >>> tabular_str = make_score_tabular(row_lbls, col_lbls, values, title, out_of, bold_best, flip) >>> result = tabular_str >>> print(result) >>> ut.quit_if_noshow() >>> render_latex_text(tabular_str) Example: >>> # DISABLE_DOCTEST >>> from utool.util_latex import * # NOQA >>> import utool as ut >>> row_lbls = ['config1', 'config2'] >>> col_lbls = ['score \leq 1', 'metric2', 'foobar'] >>> multicol_lbls = [('spam', 1), ('eggs', 2)] >>> values = np.array([[1.2, 2, -3], [3.2, 4, -2]]) >>> title = 'title' >>> out_of = 10 >>> bold_best = True >>> flip = False >>> tabular_str = make_score_tabular(row_lbls, col_lbls, values, title, out_of, bold_best, flip, multicol_lbls=multicol_lbls) >>> result = tabular_str >>> print(result) >>> ut.quit_if_noshow() >>> render_latex_text(tabular_str) """ import utool as ut if flip: bigger_is_better = not bigger_is_better flip_repltups = [('<=', '>'), ('>', '<='), ('\\leq', '\\gt'), ('\\geq', '\\lt'), ('score', 'error')] col_lbls = [replace_all(lbl, flip_repltups) for lbl in col_lbls] if title is not None: title = replace_all(title, flip_repltups) if out_of is not None: values = out_of - values # Abbreviate based on common substrings common_rowlbl = None if SHORTEN_ROW_LBLS: if isinstance(row_lbls, list): row_lbl_list = row_lbls else: row_lbl_list = row_lbls.flatten().tolist() # Split the rob labels into the alg components #algcomp_list = [lbl.split(')_') for lbl in row_lbl_list] longest = long_substr(row_lbl_list) common_strs = [] while len(longest) > 10: common_strs += [longest] row_lbl_list = [ row.replace(longest, '...') for row in row_lbl_list ] longest = long_substr(row_lbl_list) common_rowlbl = ('...'.join(common_strs)).replace(')_', ')_\n') row_lbls = row_lbl_list if len(row_lbl_list) == 1: common_rowlbl = row_lbl_list[0] row_lbls = ['0'] # Stack values into a tabular body # TODO: need ability to specify datatypes def ensurelist(row_values): try: return row_values.tolist() except AttributeError: return row_values if False: # Numpy formatting def padvec(shape=(1, 1)): pad = np.array([[' ' for c in range(shape[1])] for r in range(shape[0])]) return pad col_lbls = ensure_rowvec(col_lbls) row_lbls = ensure_colvec(row_lbls) _0 = np.vstack([padvec(), row_lbls]) _1 = np.vstack([col_lbls, values]) body = np.hstack([_0, _1]) body = [[str_ for str_ in row] for row in body] else: assert len(row_lbls) == len(values) body = [[' '] + col_lbls] body += [[row_lbl] + ensurelist(row_values) for row_lbl, row_values in zip(row_lbls, values)] #import utool as ut # Fix things in each body cell DO_PERCENT = True try: for r in range(len(body)): for c in range(len(body[0])): # In data land if r > 0 and c > 0: if precision is not None: # Hack if ut.is_float(body[r][c]): fmtstr = '%.' + str(precision) + 'f' body[r][c] = fmtstr % (float(body[r][c]), ) # Force integer if FORCE_INT: body[r][c] = str(int(float(body[r][c]))) body[r][c] = str(body[r][c]) # Remove bad formatting; if AUTOFIX_LATEX: body[r][c] = escape_latex(body[r][c]) except Exception as ex: import utool as ut print('len(row_lbls) = %r' % (len(row_lbls), )) print('len(col_lbls) = %r' % (len(col_lbls), )) print('len(values) = %r' % (values, )) print('ut.depth_profile(values) = %r' % (ut.depth_profile(values), )) util_dbg.printex(ex, keys=['r', 'c']) raise # Bold the best values if bold_best: best_col_scores = values.max(0) if bigger_is_better else values.min(0) rows_to_bold = [ np.where(values[:, colx] == best_col_scores[colx])[0] for colx in range(len(values.T)) ] for colx, rowx_list in enumerate(rows_to_bold): for rowx in rowx_list: body[rowx + 1][colx + 1] = '\\txtbf{' + body[rowx + 1][colx + 1] + '}' # More fixing after the bold is in place for r in range(len(body)): for c in range(len(body[0])): # In data land if r > 0 and c > 0: if out_of is not None: body[r][c] = body[r][c] + '/' + str(out_of) if DO_PERCENT: percent = ' = %.1f%%' % float( 100 * values[r - 1, c - 1] / out_of) body[r][c] += escape_latex(percent) # Align columns for pretty printing body = np.array(body) ALIGN_BODY = True if ALIGN_BODY: new_body_cols = [] for col in body.T: colstrs = list(map(str, ensurelist(col))) collens = list(map(len, colstrs)) maxlen = max(collens) newcols = [str_ + (' ' * (maxlen - len(str_))) for str_ in colstrs] new_body_cols += [newcols] body = np.array(new_body_cols).T # Build Body (and row layout) HLINE_SEP = True rowvalsep = '' colvalsep = ' & ' endl = '\\\\\n' hline = r'\hline' #extra_rowsep_pos_list = [1] # rows to insert an extra hline after extra_rowsep_pos_list = [] # rows to insert an extra hline after if HLINE_SEP: rowvalsep = hline + '\n' # rowstr list holds blocks of rows rowstr_list = [colvalsep.join(row) + endl for row in body] #rowstr_list = [row[0] + rowlbl_sep + colvalsep.join(row[1:]) + endl for row in body] #rowstr_list = [( # ('' if len(row) == 0 else row[0]) # if len(row) <= 1 else # row[0] + rowlblcol_sep + colvalsep.join(row[1:]) + endl) # for row in body] rowsep_list = [rowvalsep for row in rowstr_list[0:-1] ] # should be len 1 less than rowstr_list # Insert multicolumn names if multicol_lbls is not None: # TODO: label of the row labels multicol_sep multicols = [ latex_multicolumn(multicol, size, 'c' + multicol_sep) for multicol, size in multicol_lbls ] multicol_str = latex_multirow( '', 2) + colvalsep + colvalsep.join(multicols) + endl ncols = sum([tup[1] for tup in multicol_lbls]) mcol_sep = '\\cline{2-%d}\n' % (ncols + 1, ) rowstr_list = [multicol_str] + rowstr_list rowsep_list = [mcol_sep] + rowsep_list #extra_rowsep_pos_list += [1] # Insert title if title is not None and not astable: tex_title = latex_multicolumn(title, len(body[0])) + endl rowstr_list = [tex_title] + rowstr_list rowsep_list = [rowvalsep] + rowsep_list #extra_rowsep_pos_list += [2] # Apply an extra hline (for label) #extra_rowsep_pos_list = [] for pos in sorted(extra_rowsep_pos_list)[::-1]: rowstr_list.insert(pos, '') rowsep_list.insert(pos, rowvalsep) #tabular_body = rowvalsep.join(rowstr_list) from six.moves import zip_longest tabular_body = ''.join([ row if sep is None else row + sep for row, sep in zip_longest(rowstr_list, rowsep_list) ]) # Build Column Layout col_align_list = [col_align] * len(body[0]) #extra_collayoutsep_pos_list = [1] extra_collayoutsep_pos_list = [] for pos in sorted(extra_collayoutsep_pos_list)[::-1]: col_align_list.insert(pos, '') #col_layaout_sep_list = rowlblcol_sep # TODO rowlblcol_sep = '|' # Build build internal seprations between column alignments # Defaults to just the normal col_sep col_align_sep_list = [col_sep] * (len(col_align_list) - 1) # Adjust for the separations between row labels and the actual row data if len(col_align_sep_list) > 0: col_align_sep_list[0] = rowlblcol_sep # Continue multicolumn sepratation if multicol_lbls is not None: multicol_offsets = ut.cumsum(ut.get_list_column(multicol_lbls, 1)) for offset in multicol_offsets: if offset < len(col_align_sep_list): col_align_sep_list[offset] = multicol_sep from six.moves import zip_longest _tmp = [ ut.filter_Nones(tup) for tup in zip_longest(col_align_list, col_align_sep_list) ] col_layout = ''.join(ut.flatten(_tmp)) #if len(col_align_list) > 1: # col_layout = col_align_list[0] + rowlblcol_sep + col_sep.join(col_align_list[1:]) #else: # col_layout = col_sep.join(col_align_list) tabular_head = (r'\begin{tabular}{|%s|}' % col_layout) + '\n' tabular_tail = r'\end{tabular}' if centerline: tabular_head = r'\centerline{' + '\n' + tabular_head tabular_tail = tabular_tail + '}' if astable: #tabular_head = r'\begin{centering}' + '\n' + tabular_head tabular_head = r'\centering' + '\n' + tabular_head tabular_head = r'\begin{table}' + table_position + '\n' + tabular_head lblstr = latex_sanitize_command_name(kwargs.get('label', title)) caption = title if AUTOFIX_LATEX: caption = escape_latex(caption) caption = '\n% ---\n' + caption + '\n% ---\n' #tabular_head = r'\end{centering}' + '\n' + tabular_head tabular_tail = tabular_tail + '\n\caption[%s]{%s}\n\label{tbl:%s}\n\end{table}' % ( lblstr, caption, lblstr) tabular_str = rowvalsep.join([tabular_head, tabular_body, tabular_tail]) topsep = '\\hline\n' if True else '\\toprule\n' botsep = '\\hline\n' if True else '\\bottomrule\n' tabular_str = tabular_head + topsep + tabular_body + botsep + tabular_tail if common_rowlbl is not None: #tabular_str += escape_latex('\n\nThe following parameters were held fixed:\n' + common_rowlbl) pass return tabular_str