# ref: https://raw.githubusercontent.com/DLR-RM/AugmentedAutoencoder/c717cc7c7e7c468d9603d072f971fed9cb333dbe/auto_pose/eval/eval_plots.py
import os.path as osp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib2tikz import save as tikz_save
import cv2
import os
import time
import numpy as np

# import tensorflow as tf
# from auto_pose.ae.utils import tiles
from sklearn.decomposition import PCA
import glob
import pickle as pl

from lib.pysixd import inout, pose_error, pose_error_more
from lib.pysixd import dataset_params
from lib.utils import logger
from lib.utils.fs import mkdir_p

view_idx = 0


def tiles(batch, rows, cols, spacing_x=0, spacing_y=0, scale=1.0):
    if batch.ndim == 4:
        N, H, W, C = batch.shape
    elif batch.ndim == 3:
        N, H, W = batch.shape
        C = 1
    else:
        raise ValueError("Invalid batch shape: {}".format(batch.shape))

    H = int(H * scale)
    W = int(W * scale)
    img = np.ones((rows * H + (rows - 1) * spacing_y, cols * W + (cols - 1) * spacing_x, C))
    i = 0
    for row in range(rows):
        for col in range(cols):
            start_y = row * (H + spacing_y)
            end_y = start_y + H
            start_x = col * (W + spacing_x)
            end_x = start_x + W
            if i < N:
                if C > 1:
                    img[start_y:end_y, start_x:end_x, :] = cv2.resize(batch[i], (W, H))
                else:
                    img[start_y:end_y, start_x:end_x, 0] = cv2.resize(batch[i], (W, H))
            i += 1
    return img


def plot_reconstruction_test(sess, encoder, decoder, x):
    if x.dtype == "uint8":
        x = x / 255.0
        print("converted uint8 to float type")

    if x.ndim == 3:
        x = np.expand_dims(x, 0)

    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    cv2.imshow("reconst_test", cv2.resize(reconst[0], (256, 256)))


def plot_reconstruction_test_batch(sess, codebook, decoder, test_img_crops, noof_scene_views, obj_id, eval_dir=None):

    encoder = codebook._encoder
    dataset = codebook._dataset

    sample_views = np.random.choice(noof_scene_views, np.min([100, noof_scene_views]), replace=False)

    sample_batch = []
    i = 0
    j = 0
    while i < 16:
        if test_img_crops[sample_views[j]].has_key(obj_id):
            sample_batch.append(test_img_crops[sample_views[j]][obj_id][0])
            i += 1
        j += 1

    x = np.array(sample_batch).squeeze()

    if x.dtype == "uint8":
        x = x / 255.0
        print("converted uint8 to float type")

    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    nearest_neighbors = []
    for xi in x:
        Rs_est = codebook.nearest_rotation(sess, xi, top_n=8)
        pred_views = []
        pred_views.append(xi * 255)
        for R_est in Rs_est:
            pred_views.append(dataset.render_rot(R_est, downSample=1))
        nearest_neighbors.append(tiles(np.array(pred_views), 1, len(pred_views), 10, 10))

    all_nns_img = tiles(np.array(nearest_neighbors), len(nearest_neighbors), 1, 10, 10)

    reconstruction_imgs = np.hstack((tiles(x, 4, 4), tiles(reconst, 4, 4)))
    cv2.imwrite(os.path.join(eval_dir, "figures", "reconstruction_imgs.png"), reconstruction_imgs * 255)
    cv2.imwrite(os.path.join(eval_dir, "figures", "nearest_neighbors_imgs.png"), all_nns_img)


def plot_reconstruction_train(sess, decoder, train_code):
    if train_code.ndim == 1:
        train_code = np.expand_dims(train_code, 0)
    reconst = sess.run(decoder.x, feed_dict={decoder._latent_code: train_code})
    cv2.imshow("reconst_train", cv2.resize(reconst[0], (256, 256)))


def show_nearest_rotation(pred_views, test_crop, view):
    print(np.array(pred_views).shape)
    nearest_views = tiles(np.array(pred_views), 1, len(pred_views), 10, 10)
    cv2.imshow("nearest_views", cv2.resize(nearest_views / 255.0, (len(pred_views) * 256, 256)))
    cv2.imshow("test_crop", cv2.resize(test_crop, (256, 256)))

    # cv2.imwrite('/home_local2/sund_ma/autoencoder_ws/aae_imgs/nearest_views_%s.png' % view,nearest_views)


def plot_scene_with_3DBoxes(scene_res_dirs, dataset_name="tless", scene_id=1, save=False):

    # sixd_img_path = '/home_local/sund_ma/data/linemod_dataset/test'
    # model_path = '/home_local/sund_ma/data/linemod_dataset/models'

    # inout.save_results_sixd17(res_path, preds, run_time=run_time)

    # obj_gts = []
    # obj_infos = []
    # for object_id in range(1,noofobjects+1):
    #     obj_gts.append(inout.load_gt(os.path.join(sixd_img_path,'{:02d}'.format(object_id),'gt.yml')))
    #     obj_infos.append(inout.load_info(os.path.join(sixd_img_path,'{:02d}'.format(object_id),'info.yml')))
    #     print( len(obj_gts))

    # dataset_name = eval_args.get('DATA','DATASET')
    # cam_type = eval_args.get('DATA','CAM_TYPE')

    # data_params = dataset_params.get_dataset_params(dataset_name, model_type='', train_type='', test_type='primesense', cam_type='primesense')
    data_params = dataset_params.get_dataset_params(dataset_name, model_type="", train_type="")

    models_cad_files = sorted(glob.glob(os.path.join(os.path.dirname(data_params["model_mpath"]), "*.ply")))
    W, H = data_params["test_im_size"]

    from lib.meshrenderer import box3d_renderer

    renderer_line = box3d_renderer.Renderer(models_cad_files, 1, W, H)

    scene_result_dirs = sorted(glob.glob(scene_res_dirs))
    print(data_params["test_rgb_mpath"])
    print(data_params["scene_gt_mpath"])

    # for scene_id in range(1,21):
    # sixd_img_path = data_params['test_rgb_mpath'].format(scene_id)
    scene_gts = inout.load_gt(data_params["scene_gt_mpath"].format(scene_id))
    scene_infos = inout.load_info(data_params["scene_info_mpath"].format(scene_id))

    scene_dirs = [d for d in scene_result_dirs if "%02d" % scene_id == d.split("/")[-1]]
    print(scene_dirs)

    for view in range(len(scene_infos)):
        sixd_img_path = data_params["test_rgb_mpath"].format(scene_id, view)
        img = cv2.imread(sixd_img_path)
        box_img = img.copy()
        # cv2.imshow('',img)
        # cv2.waitKey(0)
        K = scene_infos[view]["cam_K"]

        for bb in scene_gts[view]:

            xmin = int(bb["obj_bb"][0])
            ymin = int(bb["obj_bb"][1])
            xmax = int(bb["obj_bb"][0] + bb["obj_bb"][2])
            ymax = int(bb["obj_bb"][1] + bb["obj_bb"][3])

            cv2.rectangle(box_img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
            cv2.putText(box_img, "%s" % (bb["obj_id"]), (xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
        # for gt in scene_gts[view]:
        # if gt['obj_id'] not in [1,8,9]:
        #     lines_gt = renderer_line.render(gt['obj_id']-1,K,gt['cam_R_m2c'],gt['cam_t_m2c'],10,5000)
        #     lines_gt_mask = (np.sum(lines_gt,axis=2) < 20)[:,:,None]
        #     print( lines_gt.shape)
        #     lines_gt = lines_gt[:,:,[1,0,2]]
        #     img = lines_gt_mask*img + lines_gt

        for scene_dir in scene_dirs:
            try:
                res_path = glob.glob(os.path.join(scene_dir, "%04d_*.yml" % view))
                print(res_path)
                res_path = res_path[0]
                # print( 'here', res_path)
                obj_id = int(res_path.split("_")[-1].split(".")[0])
                results = inout.load_results_sixd17(res_path)
                print(results)
                e = results["ests"][0]
                R_est = e["R"]
                t_est = e["t"]
                K = scene_infos[view]["cam_K"]
                lines = renderer_line.render(obj_id - 1, K, R_est, t_est, 10, 5000)
                lines_mask = (np.sum(lines, axis=2) < 20)[:, :, None]
                # img[lines>0] = lines[lines>0]
                if obj_id % 7 == 1:
                    lines[:, :, 0] = lines[:, :, 1]
                elif obj_id % 7 == 2:
                    lines[:, :, 2] = lines[:, :, 1]
                elif obj_id % 7 == 3:
                    lines[:, :, 0] = lines[:, :, 1]
                    lines[:, :, 1] = lines[:, :, 2]

                img = lines_mask * img + lines
            except:
                print("undeteceted obj: ", scene_dir)
        cv2.imshow("", img)
        if cv2.waitKey(1) == 32:
            cv2.waitKey(0)
        if save:
            if "icp" in scene_res_dirs:
                if not os.path.exists("%02d" % scene_id):
                    os.makedirs("%02d" % scene_id)
                cv2.imwrite(os.path.join("%02d" % scene_id, "%04d.png" % view), img)
            else:

                if not os.path.exists("%02d_rgb" % scene_id):
                    os.makedirs("%02d_rgb" % scene_id)
                cv2.imwrite(os.path.join("%02d_rgb" % scene_id, "%04d.png" % view), img)
            # cv2.imwrite(os.path.join('%02d' % scene_id,'%04d_boxes.png' % view), box_img)


def plot_scene_with_estimate(
    test_img,
    renderer,
    K_test,
    R_est_old,
    t_est_old,
    R_est_ref,
    t_est_ref,
    test_bb,
    test_score,
    obj_id,
    gts=[],
    bb_pred=None,
):
    global view_idx
    if bb_pred is not None:
        scene_detect = test_img.copy()
        for bb in bb_pred:
            try:
                xmin = int(bb["obj_bb"][0])
                ymin = int(bb["obj_bb"][1])
                xmax = int(bb["obj_bb"][0] + bb["obj_bb"][2])
                ymax = int(bb["obj_bb"][1] + bb["obj_bb"][3])
                if obj_id == bb["obj_id"]:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
                    cv2.putText(
                        scene_detect,
                        "%s: %1.3f" % (bb["obj_id"], bb["score"]),
                        (xmin, ymax + 20),
                        cv2.FONT_ITALIC,
                        0.5,
                        (0, 255, 0),
                        2,
                    )
                else:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax), (0, 0, 255), 2)
                    # cv2.putText(scene_detect, '%s: %1.3f' % (bb['obj_id'],bb['score']), (xmin, ymax+20), cv2.FONT_ITALIC, .5, (0,0,255), 2)
            except:
                pass
            # cv2.putText(scene_detect, '%s: %1.3f' % (obj_id,test_score), (xmin, ymax+20), cv2.FONT_ITALIC, .5, (0,255,0), 2)
        cv2.imshow("scene_detect", scene_detect)

    xmin = int(test_bb[0])
    ymin = int(test_bb[1])
    xmax = int(test_bb[0] + test_bb[2])
    ymax = int(test_bb[1] + test_bb[3])

    print("here")
    obj_in_scene, _ = renderer.render(
        obj_id=0,
        W=test_img.shape[1],
        H=test_img.shape[0],
        K=K_test.copy(),
        R=R_est_old,
        t=np.array(t_est_old),
        near=10,
        far=10000,
        random_light=False,
    )
    scene_view = test_img.copy()
    scene_view[obj_in_scene > 0] = obj_in_scene[obj_in_scene > 0]
    cv2.rectangle(scene_view, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
    cv2.putText(scene_view, "%s: %1.3f" % (obj_id, test_score), (xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
    cv2.imshow("scene_estimation", scene_view)

    obj_in_scene_ref, _ = renderer.render(
        obj_id=0,
        W=test_img.shape[1],
        H=test_img.shape[0],
        K=K_test.copy(),
        R=R_est_ref,
        t=np.array(t_est_ref),
        near=10,
        far=10000,
        random_light=False,
    )
    scene_view_refined = test_img.copy()

    g_y = np.zeros_like(obj_in_scene_ref)
    g_y[:, :, 1] = obj_in_scene_ref[:, :, 1]
    scene_view_refined[obj_in_scene_ref > 0] = (
        g_y[obj_in_scene_ref > 0] * 2.0 / 3.0 + scene_view_refined[obj_in_scene_ref > 0] * 1.0 / 3.0
    )
    # scene_view_refined[obj_in_scene_ref > 0] = obj_in_scene_ref[obj_in_scene_ref > 0]
    cv2.rectangle(scene_view_refined, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
    cv2.putText(
        scene_view_refined, "%s: %1.3f" % (obj_id, test_score), (xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2
    )
    cv2.imshow("scene_estimation_refined", scene_view_refined)
    cv2.waitKey(0)
    # cv2.imwrite('/net/rmc-lx0314/home_local/sund_ma/autoencoder_ws/bosch/thr_sc2_obj7/%s.png'% view_idx,scene_view_refined)
    view_idx += 1

    # for gt in gts:
    #     if gt['obj_id'] == obj_id:
    #         obj_in_scene, _ = renderer.render( obj_id=0, W=test_img.shape[1],H=test_img.shape[0], K=K_test.copy(), R=gt['cam_R_m2c'], t=np.array(gt['cam_t_m2c']),near=10,far=10000,random_light=False)
    #         scene_view = test_img.copy()
    #         scene_view[obj_in_scene > 0] = obj_in_scene[obj_in_scene > 0]
    #         cv2.imshow('ground truth scene_estimation',scene_view)


def compute_pca_plot_embedding(eval_dir, z_train, z_test=None, save=True):
    sklearn_pca = PCA(n_components=3)
    full_z_pca = sklearn_pca.fit_transform(z_train)
    if z_test is not None:
        full_z_pca_test = sklearn_pca.transform(z_test)

    fig = plt.figure()
    ax = Axes3D(fig)

    c = np.linspace(0, 1, len(full_z_pca))
    ax.scatter(full_z_pca[:, 0], full_z_pca[:, 1], full_z_pca[:, 2], c=c, marker=".", label="PCs of train viewsphere")
    if z_test is not None:
        ax.scatter(
            full_z_pca_test[:, 0], full_z_pca_test[:, 1], full_z_pca_test[:, 2], c="red", marker=".", label="test_z"
        )

    plt.title("Embedding Principal Components")
    ax.set_xlabel("pc1")
    ax.set_ylabel("pc2")
    ax.set_zlabel("pc3")

    plt.legend()
    pl.dump(fig, file(os.path.join(eval_dir, "figures", "pca_embedding.pickle"), "wb"))
    if save:
        plt.savefig(os.path.join(eval_dir, "figures", "pca_embedding.pdf"))


def plot_viewsphere_for_embedding(Rs_viewpoints, eval_dir):
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(Rs_viewpoints))
    ax.scatter(
        Rs_viewpoints[:, 2, 0],
        Rs_viewpoints[:, 2, 1],
        Rs_viewpoints[:, 2, 2],
        c=c,
        marker=".",
        label="embed viewpoints",
    )
    plt.title("Embedding Viewpoints")
    plt.legend()
    plt.savefig(os.path.join(eval_dir, "figures", "embedding_viewpoints.pdf"))


def plot_t_err_hist(t_errors, eval_dir):

    x = np.sort(np.abs(t_errors[:, 0]))
    y = np.sort(np.abs(t_errors[:, 1]))
    z = np.sort(np.abs(t_errors[:, 2]))

    recall = (np.arange(len(t_errors)) + 1.0) / len(t_errors)

    fig = plt.figure()
    plt.title("Recall vs Translation Error")
    plt.grid()
    plt.plot(x, recall)
    plt.plot(y, recall)
    plt.plot(z, recall)
    plt.xlabel("translation err [mm]")
    plt.ylabel("recall")
    plt.legend(["cum x error", "cum y error", "cum z error"])
    tikz_save(
        os.path.join(eval_dir, "latex", "t_err_hist.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def plot_t_err_hist2(t_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title("Translation Error Histogram")
    plt.xlabel("translation err [mm]")
    plt.ylabel("views")
    bounds = np.linspace(0, 100, bins + 1)
    bin_count = []
    eucl_terr = np.linalg.norm(t_errors, axis=1)
    for idx in range(bins):
        bin_idcs = np.where((eucl_terr > bounds[idx]) & (eucl_terr < bounds[idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 100 * 0.5 / bins)
    tikz_save(
        os.path.join(eval_dir, "latex", "t_err_hist2.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def plot_R_err_hist2(R_errors, eval_dir, bins=15):

    fig = plt.figure()
    plt.title("Rotation Error Histogram")
    plt.xlabel("Rotation err [deg]")
    plt.ylabel("views")
    bounds = np.linspace(0, 180, bins + 1)
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((R_errors > bounds[idx]) & (R_errors < bounds[idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 180 * 0.5 / bins)
    tikz_save(
        os.path.join(eval_dir, "latex", "R_err_hist2.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def plot_R_err_hist(eval_args, eval_dir, scene_ids):

    top_n_eval = eval_args.getint("EVALUATION", "TOP_N_EVAL")
    top_n = eval_args.getint("METRIC", "TOP_N")
    cam_type = eval_args.get("DATA", "cam_type")
    dataset_name = eval_args.get("DATA", "dataset")
    obj_id = eval_args.getint("DATA", "obj_id")

    if top_n_eval < 1:
        return

    data_params = dataset_params.get_dataset_params(
        dataset_name, model_type="", train_type="", test_type=cam_type, cam_type=cam_type
    )

    angle_errs = []
    for scene_id in scene_ids:
        error_file_path = os.path.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))
        if not os.path.exists(error_file_path):
            print("WARNING: " + error_file_path + " not found")
            continue
        # angle_errs_dict = inout.load_yaml(error_file_path)
        # angle_errs += [list(angle_e['errors'].values())[0] for angle_e in angle_errs_dict]

        gts = inout.load_gt(data_params["scene_gt_mpath"].format(scene_id))
        visib_gts = inout.load_yaml(data_params["scene_gt_stats_mpath"].format(scene_id, 15))
        re_dict = inout.load_yaml(error_file_path)

        for view in range(len(gts)):
            res = re_dict[view * top_n : (view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt["obj_id"] == obj_id:
                    if visib_gt["visib_fract"] > 0.1:
                        for re_e in res:
                            angle_errs += [list(re_e["errors"].values())[0]]

    if len(angle_errs) == 0:
        return

    angle_errs = np.array(angle_errs)

    fig = plt.figure()  # noqa
    plt.grid()
    plt.xlabel("angle err [deg]")
    plt.ylabel("recall")
    plt.title("Angle Error vs Recall")
    legend = []

    for n in np.unique(np.array([top_n, 1])):

        total_views = len(angle_errs) / top_n
        min_angle_errs = np.empty((total_views,))
        min_angle_errs_rect = np.empty((total_views,))

        for view in range(total_views):
            top_n_errors = angle_errs[view * top_n : (view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_angle_errs[view] = np.min(top_n_errors)
            min_angle_errs_rect[view] = np.min(np.hstack((top_n_errors, 180 - top_n_errors)))

        min_angle_errs_sorted = np.sort(min_angle_errs)
        min_angle_errs_rect_sorted = np.sort(min_angle_errs_rect)
        recall = (np.arange(total_views) + 1.0) / total_views

        # fill curve
        min_angle_errs_sorted = np.hstack((min_angle_errs_sorted, np.array([180.0])))
        min_angle_errs_rect_sorted = np.hstack((min_angle_errs_rect_sorted, np.array([90.0])))
        recall = np.hstack((recall, np.array([1.0])))

        AUC_angle = np.trapz(recall, min_angle_errs_sorted / 180.0)
        AUC_angle_rect = np.trapz(recall, min_angle_errs_rect_sorted / 90.0)

        plt.plot(min_angle_errs_sorted, recall)
        plt.plot(min_angle_errs_rect_sorted, recall)

        legend += [
            "top {0} angle err, AUC = {1:.4f}".format(n, AUC_angle),
            "top {0} rectified angle err, AUC = {1:.4f}".format(n, AUC_angle_rect),
        ]
    plt.legend(legend)
    tikz_save(
        osp.join(eval_dir, "latex", "R_err_hist.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def print_trans_rot_errors(gts, obj_id, ts_est, ts_est_old, Rs_est, Rs_est_old):

    t_errs = []
    obj_gts = []

    for gt in gts:
        if gt["obj_id"] == obj_id:
            t_errs.append(ts_est[0] - gt["cam_t_m2c"].squeeze())
            obj_gts.append(gt)

    min_t_err_idx = np.argmin(np.linalg.norm(np.array(t_errs), axis=1))
    print(min_t_err_idx)
    print(np.array(t_errs).shape)
    print(len(obj_gts))
    gt = obj_gts[min_t_err_idx].copy()

    try:
        print("Translation Error before refinement")
        print(ts_est_old[0] - gt["cam_t_m2c"].squeeze())
        print("Translation Error after refinement")
        print(t_errs[min_t_err_idx])
        print("Rotation Error before refinement")
        print(pose_error.re(Rs_est_old[0], gt["cam_R_m2c"]))
        print("Rotation Error after refinement")
        R_err = pose_error.re(Rs_est[0], gt["cam_R_m2c"])
        print(R_err)
    except:
        pass

    return (t_errs[min_t_err_idx], R_err)


# def plot_vsd_err_hist(eval_args, eval_dir, scene_ids):
def plot_vsd_err_hist(
    eval_dir, scene_ids, obj_id, dataset_name="linemod", top_n=1, delta=15, tau=20, cost="step", cam_type="primesense"
):
    # top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    # top_n = eval_args.getint('METRIC', 'TOP_N')
    # delta = eval_args.getint('METRIC', 'VSD_DELTA')
    # tau = eval_args.getint('METRIC', 'VSD_TAU')
    # cost = eval_args.get('METRIC', 'VSD_COST')
    # cam_type = eval_args.get('DATA', 'cam_type')
    # dataset_name = eval_args.get('DATA', 'dataset')
    # obj_id = eval_args.getint('DATA', 'obj_id')
    # if top_n_eval < 1:
    #     return

    data_params = dataset_params.get_dataset_params(
        dataset_name, model_type="", train_type="", test_type=cam_type, cam_type=cam_type
    )

    vsd_errs = []
    for scene_id in scene_ids:
        if dataset_name in ["linemod", "hinterstoisser"]:
            # NOTE: linemod scene_id == obj_id
            if obj_id != scene_id:
                continue

        error_file_path = osp.join(
            eval_dir,
            "error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s" % (top_n, delta, tau, cost),
            "errors_{:02d}.yml".format(scene_id),
        )

        if not osp.exists(error_file_path):
            print("WARNING: " + error_file_path + " not found")
            continue
        gts = inout.load_gt(data_params["scene_gt_mpath"].format(scene_id))
        visib_gts = inout.load_yaml(data_params["scene_gt_stats_mpath"].format(scene_id, 15))  # delta=15
        vsd_dict = inout.load_yaml(error_file_path)
        for view, vsd_e in enumerate(vsd_dict):
            vsds = vsd_dict[view * top_n : (view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt["obj_id"] == obj_id:
                    if visib_gt["visib_fract"] > 0.1:
                        for vsd_e in vsds:
                            vsd_errs += [list(vsd_e["errors"].values())[0]]

    if len(vsd_errs) == 0:
        return
    vsd_errs = np.array(vsd_errs)
    logger.info("vsd errs: {}".format(len(vsd_errs)))

    fig = plt.figure()  # noqa
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.xlabel("vsd err")
    plt.ylabel("recall")
    plt.title("obj: {}, VSD Error vs Recall".format(obj_id))
    legend = []

    for n in np.unique(np.array([top_n, 1])):

        total_views = int(len(vsd_errs) / top_n)
        min_vsd_errs = np.empty((total_views,))

        for view in range(total_views):
            top_n_errors = vsd_errs[view * top_n : (view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_vsd_errs[view] = np.min(top_n_errors)

        min_vsd_errs_sorted = np.sort(min_vsd_errs)
        recall = np.float32(np.arange(total_views) + 1.0) / total_views

        # fill curve
        min_vsd_errs_sorted = np.hstack((min_vsd_errs_sorted, np.array([1.0])))
        recall = np.hstack((recall, np.array([1.0])))

        AUC_vsd = np.trapz(recall, min_vsd_errs_sorted)
        plt.plot(min_vsd_errs_sorted, recall)

        legend += ["top {0} vsd err, AUC = {1:.4f}".format(n, AUC_vsd)]
        logger.info("obj:{} top {} vsd err, AUC = {:.4f}".format(obj_id, n, AUC_vsd))
    plt.legend(legend)
    out_file = osp.join(eval_dir, "latex", "vsd_err_hist_obj_{:02d}.tex".format(obj_id))
    mkdir_p(osp.dirname(out_file))
    logger.info(osp.basename(out_file))
    tikz_save(out_file, figurewidth="0.45\\textheight", figureheight="0.45\\textheight", show_info=False)


# def plot_vsd_occlusion(eval_args, eval_dir, scene_ids, all_test_visibs, bins=10):
def plot_vsd_occlusion(eval_dir, scene_ids, all_test_visibs, top_n=1, delta=15, tau=20, cost="step", bins=10):

    # top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    # top_n = eval_args.getint('METRIC', 'TOP_N')
    # delta = eval_args.getint('METRIC', 'VSD_DELTA')
    # tau = eval_args.getint('METRIC', 'VSD_TAU')
    # cost = eval_args.get('METRIC', 'VSD_COST')

    # if top_n_eval < 1:
    #     return

    all_vsd_errs = []
    for scene_id in scene_ids:
        error_file_path = osp.join(
            eval_dir,
            "error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s" % (top_n, delta, tau, cost),
            "errors_{:02d}.yml".format(scene_id),
        )

        if not osp.exists(error_file_path):
            print("WARNING: " + error_file_path + " not found")
            continue

        vsd_dict = inout.load_yaml(error_file_path)
        all_vsd_errs += [list(vsd_e["errors"].values())[0] for vsd_e in vsd_dict]

    if len(all_vsd_errs) == 0:
        return
    all_vsd_errs = np.array(all_vsd_errs)

    # print( all_vsd_errs)

    fig = plt.figure()  # noqa
    # ax = plt.axes()
    # ax.set_xlim((0.0,1.0))
    # ax.set_ylim((0.0,1.0))
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.ylabel("vsd err")
    plt.xlabel("visibility [percent]")
    # plt.xlim((0.0, 1.0))
    # plt.ylim((0.0, 1.0))

    total_views = len(all_vsd_errs) / top_n
    vsd_errs = np.empty((total_views,))

    for view in range(total_views):
        top_n_errors = all_vsd_errs[view * top_n : (view + 1) * top_n]
        vsd_errs[view] = top_n_errors[0]

    bounds = np.linspace(0, 1, bins + 1)
    bin_vsd_errs = []
    bin_count = []

    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (all_test_visibs < bounds[idx + 1]))
        bin_vsd_errs.append(vsd_errs[bin_idcs])
        bin_count.append(len(bin_idcs[0]))

    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    # plt.bar(middle_bin_vis,mean_vsd_err,0.5/bins)

    plt.boxplot(bin_vsd_errs, positions=middle_bin_vis, widths=0.5 / bins, sym="+")

    # count_str = 'bin count ' + bins * '%s '
    # count_str = count_str % tuple(bin_count)
    plt.title("Visibility vs Mean VSD Error" + str(bin_count))
    tikz_save(
        os.path.join(eval_dir, "latex", "vsd_occlusion.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


# def plot_re_rect_occlusion(eval_args, eval_dir, scene_ids, all_test_visibs, bins=10):
def plot_re_rect_occlusion(eval_dir, scene_ids, all_test_visibs, bins=10, top_n=1):
    # top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    # top_n = eval_args.getint('METRIC', 'TOP_N')
    # if top_n_eval < 1:
    #     return

    all_angle_errs = []
    for scene_id in scene_ids:

        if not os.path.exists(os.path.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))):
            print(
                "WARNING: "
                + osp.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))
                + " not found"
            )
            continue

        angle_errs_dict = inout.load_yaml(
            os.path.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))
        )
        all_angle_errs += [list(angle_e["errors"].values())[0] for angle_e in angle_errs_dict]

    if len(all_angle_errs) == 0:
        return
    all_angle_errs = np.array(all_angle_errs)
    # print( all_vsd_errs)

    fig = plt.figure()  # noqa
    plt.grid()
    plt.ylabel("rot err [deg]")
    plt.xlabel("visibility [percent]")
    # plt.axis((-0.1, 1.1, -0.1, 1.1))
    # plt.xlim((0.0, 1.0))
    # plt.ylim((0.0, 1.0))

    total_views = len(all_angle_errs) / top_n
    angle_errs_rect = np.empty((total_views,))

    for view in range(total_views):
        top_n_errors = all_angle_errs[view * top_n : (view + 1) * top_n]
        angle_errs_rect[view] = np.min([top_n_errors[0], 180 - top_n_errors[0]])

    bounds = np.linspace(0, 1, bins + 1)
    bin_angle_errs = []
    bin_count = []

    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (all_test_visibs < bounds[idx + 1]))
        # median_angle_err[idx] = np.median(angle_errs_rect[bin_idcs])
        bin_angle_errs.append(angle_errs_rect[bin_idcs])
        bin_count.append(len(bin_idcs[0]))

    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    # plt.bar(middle_bin_vis,median_angle_err,0.5/bins)
    plt.boxplot(bin_angle_errs, positions=middle_bin_vis, widths=0.5 / bins, sym="+")

    # count_str = 'bin count ' + bins * '%s '
    # count_str = count_str % tuple(bin_count)
    plt.title("Visibility vs Median Rectified Rotation Error" + str(bin_count))
    tikz_save(
        os.path.join(eval_dir, "latex", "R_err_occlusion.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def animate_embedding_path(z_test):
    pass

44f91f070c3ec97f93fcdea6d96109c6ca687f3c
<mask token>


def plot_reconstruction_test_batch(sess, codebook, decoder, test_img_crops,
    noof_scene_views, obj_id, eval_dir=None):
    encoder = codebook._encoder
    dataset = codebook._dataset
    sample_views = np.random.choice(noof_scene_views, np.min([100,
        noof_scene_views]), replace=False)
    sample_batch = []
    i = 0
    j = 0
    while i < 16:
        if test_img_crops[sample_views[j]].has_key(obj_id):
            sample_batch.append(test_img_crops[sample_views[j]][obj_id][0])
            i += 1
        j += 1
    x = np.array(sample_batch).squeeze()
    if x.dtype == 'uint8':
        x = x / 255.0
        print('converted uint8 to float type')
    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    nearest_neighbors = []
    for xi in x:
        Rs_est = codebook.nearest_rotation(sess, xi, top_n=8)
        pred_views = []
        pred_views.append(xi * 255)
        for R_est in Rs_est:
            pred_views.append(dataset.render_rot(R_est, downSample=1))
        nearest_neighbors.append(tiles(np.array(pred_views), 1, len(
            pred_views), 10, 10))
    all_nns_img = tiles(np.array(nearest_neighbors), len(nearest_neighbors),
        1, 10, 10)
    reconstruction_imgs = np.hstack((tiles(x, 4, 4), tiles(reconst, 4, 4)))
    cv2.imwrite(os.path.join(eval_dir, 'figures', 'reconstruction_imgs.png'
        ), reconstruction_imgs * 255)
    cv2.imwrite(os.path.join(eval_dir, 'figures',
        'nearest_neighbors_imgs.png'), all_nns_img)


def plot_reconstruction_train(sess, decoder, train_code):
    if train_code.ndim == 1:
        train_code = np.expand_dims(train_code, 0)
    reconst = sess.run(decoder.x, feed_dict={decoder._latent_code: train_code})
    cv2.imshow('reconst_train', cv2.resize(reconst[0], (256, 256)))


def show_nearest_rotation(pred_views, test_crop, view):
    print(np.array(pred_views).shape)
    nearest_views = tiles(np.array(pred_views), 1, len(pred_views), 10, 10)
    cv2.imshow('nearest_views', cv2.resize(nearest_views / 255.0, (len(
        pred_views) * 256, 256)))
    cv2.imshow('test_crop', cv2.resize(test_crop, (256, 256)))


def plot_scene_with_3DBoxes(scene_res_dirs, dataset_name='tless', scene_id=
    1, save=False):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='')
    models_cad_files = sorted(glob.glob(os.path.join(os.path.dirname(
        data_params['model_mpath']), '*.ply')))
    W, H = data_params['test_im_size']
    from lib.meshrenderer import box3d_renderer
    renderer_line = box3d_renderer.Renderer(models_cad_files, 1, W, H)
    scene_result_dirs = sorted(glob.glob(scene_res_dirs))
    print(data_params['test_rgb_mpath'])
    print(data_params['scene_gt_mpath'])
    scene_gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
    scene_infos = inout.load_info(data_params['scene_info_mpath'].format(
        scene_id))
    scene_dirs = [d for d in scene_result_dirs if '%02d' % scene_id == d.
        split('/')[-1]]
    print(scene_dirs)
    for view in range(len(scene_infos)):
        sixd_img_path = data_params['test_rgb_mpath'].format(scene_id, view)
        img = cv2.imread(sixd_img_path)
        box_img = img.copy()
        K = scene_infos[view]['cam_K']
        for bb in scene_gts[view]:
            xmin = int(bb['obj_bb'][0])
            ymin = int(bb['obj_bb'][1])
            xmax = int(bb['obj_bb'][0] + bb['obj_bb'][2])
            ymax = int(bb['obj_bb'][1] + bb['obj_bb'][3])
            cv2.rectangle(box_img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
            cv2.putText(box_img, '%s' % bb['obj_id'], (xmin, ymax + 20),
                cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
        for scene_dir in scene_dirs:
            try:
                res_path = glob.glob(os.path.join(scene_dir, '%04d_*.yml' %
                    view))
                print(res_path)
                res_path = res_path[0]
                obj_id = int(res_path.split('_')[-1].split('.')[0])
                results = inout.load_results_sixd17(res_path)
                print(results)
                e = results['ests'][0]
                R_est = e['R']
                t_est = e['t']
                K = scene_infos[view]['cam_K']
                lines = renderer_line.render(obj_id - 1, K, R_est, t_est, 
                    10, 5000)
                lines_mask = (np.sum(lines, axis=2) < 20)[:, :, None]
                if obj_id % 7 == 1:
                    lines[:, :, 0] = lines[:, :, 1]
                elif obj_id % 7 == 2:
                    lines[:, :, 2] = lines[:, :, 1]
                elif obj_id % 7 == 3:
                    lines[:, :, 0] = lines[:, :, 1]
                    lines[:, :, 1] = lines[:, :, 2]
                img = lines_mask * img + lines
            except:
                print('undeteceted obj: ', scene_dir)
        cv2.imshow('', img)
        if cv2.waitKey(1) == 32:
            cv2.waitKey(0)
        if save:
            if 'icp' in scene_res_dirs:
                if not os.path.exists('%02d' % scene_id):
                    os.makedirs('%02d' % scene_id)
                cv2.imwrite(os.path.join('%02d' % scene_id, '%04d.png' %
                    view), img)
            else:
                if not os.path.exists('%02d_rgb' % scene_id):
                    os.makedirs('%02d_rgb' % scene_id)
                cv2.imwrite(os.path.join('%02d_rgb' % scene_id, '%04d.png' %
                    view), img)


<mask token>


def compute_pca_plot_embedding(eval_dir, z_train, z_test=None, save=True):
    sklearn_pca = PCA(n_components=3)
    full_z_pca = sklearn_pca.fit_transform(z_train)
    if z_test is not None:
        full_z_pca_test = sklearn_pca.transform(z_test)
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(full_z_pca))
    ax.scatter(full_z_pca[:, 0], full_z_pca[:, 1], full_z_pca[:, 2], c=c,
        marker='.', label='PCs of train viewsphere')
    if z_test is not None:
        ax.scatter(full_z_pca_test[:, 0], full_z_pca_test[:, 1],
            full_z_pca_test[:, 2], c='red', marker='.', label='test_z')
    plt.title('Embedding Principal Components')
    ax.set_xlabel('pc1')
    ax.set_ylabel('pc2')
    ax.set_zlabel('pc3')
    plt.legend()
    pl.dump(fig, file(os.path.join(eval_dir, 'figures',
        'pca_embedding.pickle'), 'wb'))
    if save:
        plt.savefig(os.path.join(eval_dir, 'figures', 'pca_embedding.pdf'))


def plot_viewsphere_for_embedding(Rs_viewpoints, eval_dir):
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(Rs_viewpoints))
    ax.scatter(Rs_viewpoints[:, 2, 0], Rs_viewpoints[:, 2, 1],
        Rs_viewpoints[:, 2, 2], c=c, marker='.', label='embed viewpoints')
    plt.title('Embedding Viewpoints')
    plt.legend()
    plt.savefig(os.path.join(eval_dir, 'figures', 'embedding_viewpoints.pdf'))


<mask token>


def plot_t_err_hist2(t_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title('Translation Error Histogram')
    plt.xlabel('translation err [mm]')
    plt.ylabel('views')
    bounds = np.linspace(0, 100, bins + 1)
    bin_count = []
    eucl_terr = np.linalg.norm(t_errors, axis=1)
    for idx in range(bins):
        bin_idcs = np.where((eucl_terr > bounds[idx]) & (eucl_terr < bounds
            [idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 100 * 0.5 / bins)
    tikz_save(os.path.join(eval_dir, 'latex', 't_err_hist2.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


<mask token>


def plot_R_err_hist(eval_args, eval_dir, scene_ids):
    top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    top_n = eval_args.getint('METRIC', 'TOP_N')
    cam_type = eval_args.get('DATA', 'cam_type')
    dataset_name = eval_args.get('DATA', 'dataset')
    obj_id = eval_args.getint('DATA', 'obj_id')
    if top_n_eval < 1:
        return
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    angle_errs = []
    for scene_id in scene_ids:
        error_file_path = os.path.join(eval_dir, 'error=re_ntop=%s' % top_n,
            'errors_{:02d}.yml'.format(scene_id))
        if not os.path.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        re_dict = inout.load_yaml(error_file_path)
        for view in range(len(gts)):
            res = re_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for re_e in res:
                            angle_errs += [list(re_e['errors'].values())[0]]
    if len(angle_errs) == 0:
        return
    angle_errs = np.array(angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.xlabel('angle err [deg]')
    plt.ylabel('recall')
    plt.title('Angle Error vs Recall')
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = len(angle_errs) / top_n
        min_angle_errs = np.empty((total_views,))
        min_angle_errs_rect = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = angle_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_angle_errs[view] = np.min(top_n_errors)
            min_angle_errs_rect[view] = np.min(np.hstack((top_n_errors, 180 -
                top_n_errors)))
        min_angle_errs_sorted = np.sort(min_angle_errs)
        min_angle_errs_rect_sorted = np.sort(min_angle_errs_rect)
        recall = (np.arange(total_views) + 1.0) / total_views
        min_angle_errs_sorted = np.hstack((min_angle_errs_sorted, np.array(
            [180.0])))
        min_angle_errs_rect_sorted = np.hstack((min_angle_errs_rect_sorted,
            np.array([90.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_angle = np.trapz(recall, min_angle_errs_sorted / 180.0)
        AUC_angle_rect = np.trapz(recall, min_angle_errs_rect_sorted / 90.0)
        plt.plot(min_angle_errs_sorted, recall)
        plt.plot(min_angle_errs_rect_sorted, recall)
        legend += ['top {0} angle err, AUC = {1:.4f}'.format(n, AUC_angle),
            'top {0} rectified angle err, AUC = {1:.4f}'.format(n,
            AUC_angle_rect)]
    plt.legend(legend)
    tikz_save(osp.join(eval_dir, 'latex', 'R_err_hist.tex'), figurewidth=
        '0.45\\textheight', figureheight='0.45\\textheight', show_info=False)


def print_trans_rot_errors(gts, obj_id, ts_est, ts_est_old, Rs_est, Rs_est_old
    ):
    t_errs = []
    obj_gts = []
    for gt in gts:
        if gt['obj_id'] == obj_id:
            t_errs.append(ts_est[0] - gt['cam_t_m2c'].squeeze())
            obj_gts.append(gt)
    min_t_err_idx = np.argmin(np.linalg.norm(np.array(t_errs), axis=1))
    print(min_t_err_idx)
    print(np.array(t_errs).shape)
    print(len(obj_gts))
    gt = obj_gts[min_t_err_idx].copy()
    try:
        print('Translation Error before refinement')
        print(ts_est_old[0] - gt['cam_t_m2c'].squeeze())
        print('Translation Error after refinement')
        print(t_errs[min_t_err_idx])
        print('Rotation Error before refinement')
        print(pose_error.re(Rs_est_old[0], gt['cam_R_m2c']))
        print('Rotation Error after refinement')
        R_err = pose_error.re(Rs_est[0], gt['cam_R_m2c'])
        print(R_err)
    except:
        pass
    return t_errs[min_t_err_idx], R_err


def plot_vsd_err_hist(eval_dir, scene_ids, obj_id, dataset_name='linemod',
    top_n=1, delta=15, tau=20, cost='step', cam_type='primesense'):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    vsd_errs = []
    for scene_id in scene_ids:
        if dataset_name in ['linemod', 'hinterstoisser']:
            if obj_id != scene_id:
                continue
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        vsd_dict = inout.load_yaml(error_file_path)
        for view, vsd_e in enumerate(vsd_dict):
            vsds = vsd_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for vsd_e in vsds:
                            vsd_errs += [list(vsd_e['errors'].values())[0]]
    if len(vsd_errs) == 0:
        return
    vsd_errs = np.array(vsd_errs)
    logger.info('vsd errs: {}'.format(len(vsd_errs)))
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.xlabel('vsd err')
    plt.ylabel('recall')
    plt.title('obj: {}, VSD Error vs Recall'.format(obj_id))
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = int(len(vsd_errs) / top_n)
        min_vsd_errs = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = vsd_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_vsd_errs[view] = np.min(top_n_errors)
        min_vsd_errs_sorted = np.sort(min_vsd_errs)
        recall = np.float32(np.arange(total_views) + 1.0) / total_views
        min_vsd_errs_sorted = np.hstack((min_vsd_errs_sorted, np.array([1.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_vsd = np.trapz(recall, min_vsd_errs_sorted)
        plt.plot(min_vsd_errs_sorted, recall)
        legend += ['top {0} vsd err, AUC = {1:.4f}'.format(n, AUC_vsd)]
        logger.info('obj:{} top {} vsd err, AUC = {:.4f}'.format(obj_id, n,
            AUC_vsd))
    plt.legend(legend)
    out_file = osp.join(eval_dir, 'latex', 'vsd_err_hist_obj_{:02d}.tex'.
        format(obj_id))
    mkdir_p(osp.dirname(out_file))
    logger.info(osp.basename(out_file))
    tikz_save(out_file, figurewidth='0.45\\textheight', figureheight=
        '0.45\\textheight', show_info=False)


def plot_vsd_occlusion(eval_dir, scene_ids, all_test_visibs, top_n=1, delta
    =15, tau=20, cost='step', bins=10):
    all_vsd_errs = []
    for scene_id in scene_ids:
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        vsd_dict = inout.load_yaml(error_file_path)
        all_vsd_errs += [list(vsd_e['errors'].values())[0] for vsd_e in
            vsd_dict]
    if len(all_vsd_errs) == 0:
        return
    all_vsd_errs = np.array(all_vsd_errs)
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.ylabel('vsd err')
    plt.xlabel('visibility [percent]')
    total_views = len(all_vsd_errs) / top_n
    vsd_errs = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_vsd_errs[view * top_n:(view + 1) * top_n]
        vsd_errs[view] = top_n_errors[0]
    bounds = np.linspace(0, 1, bins + 1)
    bin_vsd_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_vsd_errs.append(vsd_errs[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_vsd_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Mean VSD Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'vsd_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_re_rect_occlusion(eval_dir, scene_ids, all_test_visibs, bins=10,
    top_n=1):
    all_angle_errs = []
    for scene_id in scene_ids:
        if not os.path.exists(os.path.join(eval_dir, 'error=re_ntop=%s' %
            top_n, 'errors_{:02d}.yml'.format(scene_id))):
            print('WARNING: ' + osp.join(eval_dir, 'error=re_ntop=%s' %
                top_n, 'errors_{:02d}.yml'.format(scene_id)) + ' not found')
            continue
        angle_errs_dict = inout.load_yaml(os.path.join(eval_dir, 
            'error=re_ntop=%s' % top_n, 'errors_{:02d}.yml'.format(scene_id)))
        all_angle_errs += [list(angle_e['errors'].values())[0] for angle_e in
            angle_errs_dict]
    if len(all_angle_errs) == 0:
        return
    all_angle_errs = np.array(all_angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.ylabel('rot err [deg]')
    plt.xlabel('visibility [percent]')
    total_views = len(all_angle_errs) / top_n
    angle_errs_rect = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_angle_errs[view * top_n:(view + 1) * top_n]
        angle_errs_rect[view] = np.min([top_n_errors[0], 180 - top_n_errors[0]]
            )
    bounds = np.linspace(0, 1, bins + 1)
    bin_angle_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_angle_errs.append(angle_errs_rect[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_angle_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Median Rectified Rotation Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'R_err_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


<mask token>

<mask token>


def tiles(batch, rows, cols, spacing_x=0, spacing_y=0, scale=1.0):
    if batch.ndim == 4:
        N, H, W, C = batch.shape
    elif batch.ndim == 3:
        N, H, W = batch.shape
        C = 1
    else:
        raise ValueError('Invalid batch shape: {}'.format(batch.shape))
    H = int(H * scale)
    W = int(W * scale)
    img = np.ones((rows * H + (rows - 1) * spacing_y, cols * W + (cols - 1) *
        spacing_x, C))
    i = 0
    for row in range(rows):
        for col in range(cols):
            start_y = row * (H + spacing_y)
            end_y = start_y + H
            start_x = col * (W + spacing_x)
            end_x = start_x + W
            if i < N:
                if C > 1:
                    img[start_y:end_y, start_x:end_x, :] = cv2.resize(batch
                        [i], (W, H))
                else:
                    img[start_y:end_y, start_x:end_x, 0] = cv2.resize(batch
                        [i], (W, H))
            i += 1
    return img


<mask token>


def plot_reconstruction_test_batch(sess, codebook, decoder, test_img_crops,
    noof_scene_views, obj_id, eval_dir=None):
    encoder = codebook._encoder
    dataset = codebook._dataset
    sample_views = np.random.choice(noof_scene_views, np.min([100,
        noof_scene_views]), replace=False)
    sample_batch = []
    i = 0
    j = 0
    while i < 16:
        if test_img_crops[sample_views[j]].has_key(obj_id):
            sample_batch.append(test_img_crops[sample_views[j]][obj_id][0])
            i += 1
        j += 1
    x = np.array(sample_batch).squeeze()
    if x.dtype == 'uint8':
        x = x / 255.0
        print('converted uint8 to float type')
    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    nearest_neighbors = []
    for xi in x:
        Rs_est = codebook.nearest_rotation(sess, xi, top_n=8)
        pred_views = []
        pred_views.append(xi * 255)
        for R_est in Rs_est:
            pred_views.append(dataset.render_rot(R_est, downSample=1))
        nearest_neighbors.append(tiles(np.array(pred_views), 1, len(
            pred_views), 10, 10))
    all_nns_img = tiles(np.array(nearest_neighbors), len(nearest_neighbors),
        1, 10, 10)
    reconstruction_imgs = np.hstack((tiles(x, 4, 4), tiles(reconst, 4, 4)))
    cv2.imwrite(os.path.join(eval_dir, 'figures', 'reconstruction_imgs.png'
        ), reconstruction_imgs * 255)
    cv2.imwrite(os.path.join(eval_dir, 'figures',
        'nearest_neighbors_imgs.png'), all_nns_img)


def plot_reconstruction_train(sess, decoder, train_code):
    if train_code.ndim == 1:
        train_code = np.expand_dims(train_code, 0)
    reconst = sess.run(decoder.x, feed_dict={decoder._latent_code: train_code})
    cv2.imshow('reconst_train', cv2.resize(reconst[0], (256, 256)))


def show_nearest_rotation(pred_views, test_crop, view):
    print(np.array(pred_views).shape)
    nearest_views = tiles(np.array(pred_views), 1, len(pred_views), 10, 10)
    cv2.imshow('nearest_views', cv2.resize(nearest_views / 255.0, (len(
        pred_views) * 256, 256)))
    cv2.imshow('test_crop', cv2.resize(test_crop, (256, 256)))


def plot_scene_with_3DBoxes(scene_res_dirs, dataset_name='tless', scene_id=
    1, save=False):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='')
    models_cad_files = sorted(glob.glob(os.path.join(os.path.dirname(
        data_params['model_mpath']), '*.ply')))
    W, H = data_params['test_im_size']
    from lib.meshrenderer import box3d_renderer
    renderer_line = box3d_renderer.Renderer(models_cad_files, 1, W, H)
    scene_result_dirs = sorted(glob.glob(scene_res_dirs))
    print(data_params['test_rgb_mpath'])
    print(data_params['scene_gt_mpath'])
    scene_gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
    scene_infos = inout.load_info(data_params['scene_info_mpath'].format(
        scene_id))
    scene_dirs = [d for d in scene_result_dirs if '%02d' % scene_id == d.
        split('/')[-1]]
    print(scene_dirs)
    for view in range(len(scene_infos)):
        sixd_img_path = data_params['test_rgb_mpath'].format(scene_id, view)
        img = cv2.imread(sixd_img_path)
        box_img = img.copy()
        K = scene_infos[view]['cam_K']
        for bb in scene_gts[view]:
            xmin = int(bb['obj_bb'][0])
            ymin = int(bb['obj_bb'][1])
            xmax = int(bb['obj_bb'][0] + bb['obj_bb'][2])
            ymax = int(bb['obj_bb'][1] + bb['obj_bb'][3])
            cv2.rectangle(box_img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
            cv2.putText(box_img, '%s' % bb['obj_id'], (xmin, ymax + 20),
                cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
        for scene_dir in scene_dirs:
            try:
                res_path = glob.glob(os.path.join(scene_dir, '%04d_*.yml' %
                    view))
                print(res_path)
                res_path = res_path[0]
                obj_id = int(res_path.split('_')[-1].split('.')[0])
                results = inout.load_results_sixd17(res_path)
                print(results)
                e = results['ests'][0]
                R_est = e['R']
                t_est = e['t']
                K = scene_infos[view]['cam_K']
                lines = renderer_line.render(obj_id - 1, K, R_est, t_est, 
                    10, 5000)
                lines_mask = (np.sum(lines, axis=2) < 20)[:, :, None]
                if obj_id % 7 == 1:
                    lines[:, :, 0] = lines[:, :, 1]
                elif obj_id % 7 == 2:
                    lines[:, :, 2] = lines[:, :, 1]
                elif obj_id % 7 == 3:
                    lines[:, :, 0] = lines[:, :, 1]
                    lines[:, :, 1] = lines[:, :, 2]
                img = lines_mask * img + lines
            except:
                print('undeteceted obj: ', scene_dir)
        cv2.imshow('', img)
        if cv2.waitKey(1) == 32:
            cv2.waitKey(0)
        if save:
            if 'icp' in scene_res_dirs:
                if not os.path.exists('%02d' % scene_id):
                    os.makedirs('%02d' % scene_id)
                cv2.imwrite(os.path.join('%02d' % scene_id, '%04d.png' %
                    view), img)
            else:
                if not os.path.exists('%02d_rgb' % scene_id):
                    os.makedirs('%02d_rgb' % scene_id)
                cv2.imwrite(os.path.join('%02d_rgb' % scene_id, '%04d.png' %
                    view), img)


<mask token>


def compute_pca_plot_embedding(eval_dir, z_train, z_test=None, save=True):
    sklearn_pca = PCA(n_components=3)
    full_z_pca = sklearn_pca.fit_transform(z_train)
    if z_test is not None:
        full_z_pca_test = sklearn_pca.transform(z_test)
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(full_z_pca))
    ax.scatter(full_z_pca[:, 0], full_z_pca[:, 1], full_z_pca[:, 2], c=c,
        marker='.', label='PCs of train viewsphere')
    if z_test is not None:
        ax.scatter(full_z_pca_test[:, 0], full_z_pca_test[:, 1],
            full_z_pca_test[:, 2], c='red', marker='.', label='test_z')
    plt.title('Embedding Principal Components')
    ax.set_xlabel('pc1')
    ax.set_ylabel('pc2')
    ax.set_zlabel('pc3')
    plt.legend()
    pl.dump(fig, file(os.path.join(eval_dir, 'figures',
        'pca_embedding.pickle'), 'wb'))
    if save:
        plt.savefig(os.path.join(eval_dir, 'figures', 'pca_embedding.pdf'))


def plot_viewsphere_for_embedding(Rs_viewpoints, eval_dir):
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(Rs_viewpoints))
    ax.scatter(Rs_viewpoints[:, 2, 0], Rs_viewpoints[:, 2, 1],
        Rs_viewpoints[:, 2, 2], c=c, marker='.', label='embed viewpoints')
    plt.title('Embedding Viewpoints')
    plt.legend()
    plt.savefig(os.path.join(eval_dir, 'figures', 'embedding_viewpoints.pdf'))


def plot_t_err_hist(t_errors, eval_dir):
    x = np.sort(np.abs(t_errors[:, 0]))
    y = np.sort(np.abs(t_errors[:, 1]))
    z = np.sort(np.abs(t_errors[:, 2]))
    recall = (np.arange(len(t_errors)) + 1.0) / len(t_errors)
    fig = plt.figure()
    plt.title('Recall vs Translation Error')
    plt.grid()
    plt.plot(x, recall)
    plt.plot(y, recall)
    plt.plot(z, recall)
    plt.xlabel('translation err [mm]')
    plt.ylabel('recall')
    plt.legend(['cum x error', 'cum y error', 'cum z error'])
    tikz_save(os.path.join(eval_dir, 'latex', 't_err_hist.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_t_err_hist2(t_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title('Translation Error Histogram')
    plt.xlabel('translation err [mm]')
    plt.ylabel('views')
    bounds = np.linspace(0, 100, bins + 1)
    bin_count = []
    eucl_terr = np.linalg.norm(t_errors, axis=1)
    for idx in range(bins):
        bin_idcs = np.where((eucl_terr > bounds[idx]) & (eucl_terr < bounds
            [idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 100 * 0.5 / bins)
    tikz_save(os.path.join(eval_dir, 'latex', 't_err_hist2.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


<mask token>


def plot_R_err_hist(eval_args, eval_dir, scene_ids):
    top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    top_n = eval_args.getint('METRIC', 'TOP_N')
    cam_type = eval_args.get('DATA', 'cam_type')
    dataset_name = eval_args.get('DATA', 'dataset')
    obj_id = eval_args.getint('DATA', 'obj_id')
    if top_n_eval < 1:
        return
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    angle_errs = []
    for scene_id in scene_ids:
        error_file_path = os.path.join(eval_dir, 'error=re_ntop=%s' % top_n,
            'errors_{:02d}.yml'.format(scene_id))
        if not os.path.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        re_dict = inout.load_yaml(error_file_path)
        for view in range(len(gts)):
            res = re_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for re_e in res:
                            angle_errs += [list(re_e['errors'].values())[0]]
    if len(angle_errs) == 0:
        return
    angle_errs = np.array(angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.xlabel('angle err [deg]')
    plt.ylabel('recall')
    plt.title('Angle Error vs Recall')
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = len(angle_errs) / top_n
        min_angle_errs = np.empty((total_views,))
        min_angle_errs_rect = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = angle_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_angle_errs[view] = np.min(top_n_errors)
            min_angle_errs_rect[view] = np.min(np.hstack((top_n_errors, 180 -
                top_n_errors)))
        min_angle_errs_sorted = np.sort(min_angle_errs)
        min_angle_errs_rect_sorted = np.sort(min_angle_errs_rect)
        recall = (np.arange(total_views) + 1.0) / total_views
        min_angle_errs_sorted = np.hstack((min_angle_errs_sorted, np.array(
            [180.0])))
        min_angle_errs_rect_sorted = np.hstack((min_angle_errs_rect_sorted,
            np.array([90.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_angle = np.trapz(recall, min_angle_errs_sorted / 180.0)
        AUC_angle_rect = np.trapz(recall, min_angle_errs_rect_sorted / 90.0)
        plt.plot(min_angle_errs_sorted, recall)
        plt.plot(min_angle_errs_rect_sorted, recall)
        legend += ['top {0} angle err, AUC = {1:.4f}'.format(n, AUC_angle),
            'top {0} rectified angle err, AUC = {1:.4f}'.format(n,
            AUC_angle_rect)]
    plt.legend(legend)
    tikz_save(osp.join(eval_dir, 'latex', 'R_err_hist.tex'), figurewidth=
        '0.45\\textheight', figureheight='0.45\\textheight', show_info=False)


def print_trans_rot_errors(gts, obj_id, ts_est, ts_est_old, Rs_est, Rs_est_old
    ):
    t_errs = []
    obj_gts = []
    for gt in gts:
        if gt['obj_id'] == obj_id:
            t_errs.append(ts_est[0] - gt['cam_t_m2c'].squeeze())
            obj_gts.append(gt)
    min_t_err_idx = np.argmin(np.linalg.norm(np.array(t_errs), axis=1))
    print(min_t_err_idx)
    print(np.array(t_errs).shape)
    print(len(obj_gts))
    gt = obj_gts[min_t_err_idx].copy()
    try:
        print('Translation Error before refinement')
        print(ts_est_old[0] - gt['cam_t_m2c'].squeeze())
        print('Translation Error after refinement')
        print(t_errs[min_t_err_idx])
        print('Rotation Error before refinement')
        print(pose_error.re(Rs_est_old[0], gt['cam_R_m2c']))
        print('Rotation Error after refinement')
        R_err = pose_error.re(Rs_est[0], gt['cam_R_m2c'])
        print(R_err)
    except:
        pass
    return t_errs[min_t_err_idx], R_err


def plot_vsd_err_hist(eval_dir, scene_ids, obj_id, dataset_name='linemod',
    top_n=1, delta=15, tau=20, cost='step', cam_type='primesense'):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    vsd_errs = []
    for scene_id in scene_ids:
        if dataset_name in ['linemod', 'hinterstoisser']:
            if obj_id != scene_id:
                continue
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        vsd_dict = inout.load_yaml(error_file_path)
        for view, vsd_e in enumerate(vsd_dict):
            vsds = vsd_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for vsd_e in vsds:
                            vsd_errs += [list(vsd_e['errors'].values())[0]]
    if len(vsd_errs) == 0:
        return
    vsd_errs = np.array(vsd_errs)
    logger.info('vsd errs: {}'.format(len(vsd_errs)))
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.xlabel('vsd err')
    plt.ylabel('recall')
    plt.title('obj: {}, VSD Error vs Recall'.format(obj_id))
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = int(len(vsd_errs) / top_n)
        min_vsd_errs = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = vsd_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_vsd_errs[view] = np.min(top_n_errors)
        min_vsd_errs_sorted = np.sort(min_vsd_errs)
        recall = np.float32(np.arange(total_views) + 1.0) / total_views
        min_vsd_errs_sorted = np.hstack((min_vsd_errs_sorted, np.array([1.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_vsd = np.trapz(recall, min_vsd_errs_sorted)
        plt.plot(min_vsd_errs_sorted, recall)
        legend += ['top {0} vsd err, AUC = {1:.4f}'.format(n, AUC_vsd)]
        logger.info('obj:{} top {} vsd err, AUC = {:.4f}'.format(obj_id, n,
            AUC_vsd))
    plt.legend(legend)
    out_file = osp.join(eval_dir, 'latex', 'vsd_err_hist_obj_{:02d}.tex'.
        format(obj_id))
    mkdir_p(osp.dirname(out_file))
    logger.info(osp.basename(out_file))
    tikz_save(out_file, figurewidth='0.45\\textheight', figureheight=
        '0.45\\textheight', show_info=False)


def plot_vsd_occlusion(eval_dir, scene_ids, all_test_visibs, top_n=1, delta
    =15, tau=20, cost='step', bins=10):
    all_vsd_errs = []
    for scene_id in scene_ids:
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        vsd_dict = inout.load_yaml(error_file_path)
        all_vsd_errs += [list(vsd_e['errors'].values())[0] for vsd_e in
            vsd_dict]
    if len(all_vsd_errs) == 0:
        return
    all_vsd_errs = np.array(all_vsd_errs)
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.ylabel('vsd err')
    plt.xlabel('visibility [percent]')
    total_views = len(all_vsd_errs) / top_n
    vsd_errs = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_vsd_errs[view * top_n:(view + 1) * top_n]
        vsd_errs[view] = top_n_errors[0]
    bounds = np.linspace(0, 1, bins + 1)
    bin_vsd_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_vsd_errs.append(vsd_errs[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_vsd_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Mean VSD Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'vsd_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_re_rect_occlusion(eval_dir, scene_ids, all_test_visibs, bins=10,
    top_n=1):
    all_angle_errs = []
    for scene_id in scene_ids:
        if not os.path.exists(os.path.join(eval_dir, 'error=re_ntop=%s' %
            top_n, 'errors_{:02d}.yml'.format(scene_id))):
            print('WARNING: ' + osp.join(eval_dir, 'error=re_ntop=%s' %
                top_n, 'errors_{:02d}.yml'.format(scene_id)) + ' not found')
            continue
        angle_errs_dict = inout.load_yaml(os.path.join(eval_dir, 
            'error=re_ntop=%s' % top_n, 'errors_{:02d}.yml'.format(scene_id)))
        all_angle_errs += [list(angle_e['errors'].values())[0] for angle_e in
            angle_errs_dict]
    if len(all_angle_errs) == 0:
        return
    all_angle_errs = np.array(all_angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.ylabel('rot err [deg]')
    plt.xlabel('visibility [percent]')
    total_views = len(all_angle_errs) / top_n
    angle_errs_rect = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_angle_errs[view * top_n:(view + 1) * top_n]
        angle_errs_rect[view] = np.min([top_n_errors[0], 180 - top_n_errors[0]]
            )
    bounds = np.linspace(0, 1, bins + 1)
    bin_angle_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_angle_errs.append(angle_errs_rect[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_angle_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Median Rectified Rotation Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'R_err_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


<mask token>

<mask token>


def tiles(batch, rows, cols, spacing_x=0, spacing_y=0, scale=1.0):
    if batch.ndim == 4:
        N, H, W, C = batch.shape
    elif batch.ndim == 3:
        N, H, W = batch.shape
        C = 1
    else:
        raise ValueError('Invalid batch shape: {}'.format(batch.shape))
    H = int(H * scale)
    W = int(W * scale)
    img = np.ones((rows * H + (rows - 1) * spacing_y, cols * W + (cols - 1) *
        spacing_x, C))
    i = 0
    for row in range(rows):
        for col in range(cols):
            start_y = row * (H + spacing_y)
            end_y = start_y + H
            start_x = col * (W + spacing_x)
            end_x = start_x + W
            if i < N:
                if C > 1:
                    img[start_y:end_y, start_x:end_x, :] = cv2.resize(batch
                        [i], (W, H))
                else:
                    img[start_y:end_y, start_x:end_x, 0] = cv2.resize(batch
                        [i], (W, H))
            i += 1
    return img


def plot_reconstruction_test(sess, encoder, decoder, x):
    if x.dtype == 'uint8':
        x = x / 255.0
        print('converted uint8 to float type')
    if x.ndim == 3:
        x = np.expand_dims(x, 0)
    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    cv2.imshow('reconst_test', cv2.resize(reconst[0], (256, 256)))


def plot_reconstruction_test_batch(sess, codebook, decoder, test_img_crops,
    noof_scene_views, obj_id, eval_dir=None):
    encoder = codebook._encoder
    dataset = codebook._dataset
    sample_views = np.random.choice(noof_scene_views, np.min([100,
        noof_scene_views]), replace=False)
    sample_batch = []
    i = 0
    j = 0
    while i < 16:
        if test_img_crops[sample_views[j]].has_key(obj_id):
            sample_batch.append(test_img_crops[sample_views[j]][obj_id][0])
            i += 1
        j += 1
    x = np.array(sample_batch).squeeze()
    if x.dtype == 'uint8':
        x = x / 255.0
        print('converted uint8 to float type')
    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    nearest_neighbors = []
    for xi in x:
        Rs_est = codebook.nearest_rotation(sess, xi, top_n=8)
        pred_views = []
        pred_views.append(xi * 255)
        for R_est in Rs_est:
            pred_views.append(dataset.render_rot(R_est, downSample=1))
        nearest_neighbors.append(tiles(np.array(pred_views), 1, len(
            pred_views), 10, 10))
    all_nns_img = tiles(np.array(nearest_neighbors), len(nearest_neighbors),
        1, 10, 10)
    reconstruction_imgs = np.hstack((tiles(x, 4, 4), tiles(reconst, 4, 4)))
    cv2.imwrite(os.path.join(eval_dir, 'figures', 'reconstruction_imgs.png'
        ), reconstruction_imgs * 255)
    cv2.imwrite(os.path.join(eval_dir, 'figures',
        'nearest_neighbors_imgs.png'), all_nns_img)


def plot_reconstruction_train(sess, decoder, train_code):
    if train_code.ndim == 1:
        train_code = np.expand_dims(train_code, 0)
    reconst = sess.run(decoder.x, feed_dict={decoder._latent_code: train_code})
    cv2.imshow('reconst_train', cv2.resize(reconst[0], (256, 256)))


def show_nearest_rotation(pred_views, test_crop, view):
    print(np.array(pred_views).shape)
    nearest_views = tiles(np.array(pred_views), 1, len(pred_views), 10, 10)
    cv2.imshow('nearest_views', cv2.resize(nearest_views / 255.0, (len(
        pred_views) * 256, 256)))
    cv2.imshow('test_crop', cv2.resize(test_crop, (256, 256)))


def plot_scene_with_3DBoxes(scene_res_dirs, dataset_name='tless', scene_id=
    1, save=False):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='')
    models_cad_files = sorted(glob.glob(os.path.join(os.path.dirname(
        data_params['model_mpath']), '*.ply')))
    W, H = data_params['test_im_size']
    from lib.meshrenderer import box3d_renderer
    renderer_line = box3d_renderer.Renderer(models_cad_files, 1, W, H)
    scene_result_dirs = sorted(glob.glob(scene_res_dirs))
    print(data_params['test_rgb_mpath'])
    print(data_params['scene_gt_mpath'])
    scene_gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
    scene_infos = inout.load_info(data_params['scene_info_mpath'].format(
        scene_id))
    scene_dirs = [d for d in scene_result_dirs if '%02d' % scene_id == d.
        split('/')[-1]]
    print(scene_dirs)
    for view in range(len(scene_infos)):
        sixd_img_path = data_params['test_rgb_mpath'].format(scene_id, view)
        img = cv2.imread(sixd_img_path)
        box_img = img.copy()
        K = scene_infos[view]['cam_K']
        for bb in scene_gts[view]:
            xmin = int(bb['obj_bb'][0])
            ymin = int(bb['obj_bb'][1])
            xmax = int(bb['obj_bb'][0] + bb['obj_bb'][2])
            ymax = int(bb['obj_bb'][1] + bb['obj_bb'][3])
            cv2.rectangle(box_img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
            cv2.putText(box_img, '%s' % bb['obj_id'], (xmin, ymax + 20),
                cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
        for scene_dir in scene_dirs:
            try:
                res_path = glob.glob(os.path.join(scene_dir, '%04d_*.yml' %
                    view))
                print(res_path)
                res_path = res_path[0]
                obj_id = int(res_path.split('_')[-1].split('.')[0])
                results = inout.load_results_sixd17(res_path)
                print(results)
                e = results['ests'][0]
                R_est = e['R']
                t_est = e['t']
                K = scene_infos[view]['cam_K']
                lines = renderer_line.render(obj_id - 1, K, R_est, t_est, 
                    10, 5000)
                lines_mask = (np.sum(lines, axis=2) < 20)[:, :, None]
                if obj_id % 7 == 1:
                    lines[:, :, 0] = lines[:, :, 1]
                elif obj_id % 7 == 2:
                    lines[:, :, 2] = lines[:, :, 1]
                elif obj_id % 7 == 3:
                    lines[:, :, 0] = lines[:, :, 1]
                    lines[:, :, 1] = lines[:, :, 2]
                img = lines_mask * img + lines
            except:
                print('undeteceted obj: ', scene_dir)
        cv2.imshow('', img)
        if cv2.waitKey(1) == 32:
            cv2.waitKey(0)
        if save:
            if 'icp' in scene_res_dirs:
                if not os.path.exists('%02d' % scene_id):
                    os.makedirs('%02d' % scene_id)
                cv2.imwrite(os.path.join('%02d' % scene_id, '%04d.png' %
                    view), img)
            else:
                if not os.path.exists('%02d_rgb' % scene_id):
                    os.makedirs('%02d_rgb' % scene_id)
                cv2.imwrite(os.path.join('%02d_rgb' % scene_id, '%04d.png' %
                    view), img)


def plot_scene_with_estimate(test_img, renderer, K_test, R_est_old,
    t_est_old, R_est_ref, t_est_ref, test_bb, test_score, obj_id, gts=[],
    bb_pred=None):
    global view_idx
    if bb_pred is not None:
        scene_detect = test_img.copy()
        for bb in bb_pred:
            try:
                xmin = int(bb['obj_bb'][0])
                ymin = int(bb['obj_bb'][1])
                xmax = int(bb['obj_bb'][0] + bb['obj_bb'][2])
                ymax = int(bb['obj_bb'][1] + bb['obj_bb'][3])
                if obj_id == bb['obj_id']:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax),
                        (0, 255, 0), 2)
                    cv2.putText(scene_detect, '%s: %1.3f' % (bb['obj_id'],
                        bb['score']), (xmin, ymax + 20), cv2.FONT_ITALIC, 
                        0.5, (0, 255, 0), 2)
                else:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax),
                        (0, 0, 255), 2)
            except:
                pass
        cv2.imshow('scene_detect', scene_detect)
    xmin = int(test_bb[0])
    ymin = int(test_bb[1])
    xmax = int(test_bb[0] + test_bb[2])
    ymax = int(test_bb[1] + test_bb[3])
    print('here')
    obj_in_scene, _ = renderer.render(obj_id=0, W=test_img.shape[1], H=
        test_img.shape[0], K=K_test.copy(), R=R_est_old, t=np.array(
        t_est_old), near=10, far=10000, random_light=False)
    scene_view = test_img.copy()
    scene_view[obj_in_scene > 0] = obj_in_scene[obj_in_scene > 0]
    cv2.rectangle(scene_view, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
    cv2.putText(scene_view, '%s: %1.3f' % (obj_id, test_score), (xmin, ymax +
        20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
    cv2.imshow('scene_estimation', scene_view)
    obj_in_scene_ref, _ = renderer.render(obj_id=0, W=test_img.shape[1], H=
        test_img.shape[0], K=K_test.copy(), R=R_est_ref, t=np.array(
        t_est_ref), near=10, far=10000, random_light=False)
    scene_view_refined = test_img.copy()
    g_y = np.zeros_like(obj_in_scene_ref)
    g_y[:, :, 1] = obj_in_scene_ref[:, :, 1]
    scene_view_refined[obj_in_scene_ref > 0] = g_y[obj_in_scene_ref > 0
        ] * 2.0 / 3.0 + scene_view_refined[obj_in_scene_ref > 0] * 1.0 / 3.0
    cv2.rectangle(scene_view_refined, (xmin, ymin), (xmax, ymax), (0, 255, 
        0), 2)
    cv2.putText(scene_view_refined, '%s: %1.3f' % (obj_id, test_score), (
        xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
    cv2.imshow('scene_estimation_refined', scene_view_refined)
    cv2.waitKey(0)
    view_idx += 1


def compute_pca_plot_embedding(eval_dir, z_train, z_test=None, save=True):
    sklearn_pca = PCA(n_components=3)
    full_z_pca = sklearn_pca.fit_transform(z_train)
    if z_test is not None:
        full_z_pca_test = sklearn_pca.transform(z_test)
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(full_z_pca))
    ax.scatter(full_z_pca[:, 0], full_z_pca[:, 1], full_z_pca[:, 2], c=c,
        marker='.', label='PCs of train viewsphere')
    if z_test is not None:
        ax.scatter(full_z_pca_test[:, 0], full_z_pca_test[:, 1],
            full_z_pca_test[:, 2], c='red', marker='.', label='test_z')
    plt.title('Embedding Principal Components')
    ax.set_xlabel('pc1')
    ax.set_ylabel('pc2')
    ax.set_zlabel('pc3')
    plt.legend()
    pl.dump(fig, file(os.path.join(eval_dir, 'figures',
        'pca_embedding.pickle'), 'wb'))
    if save:
        plt.savefig(os.path.join(eval_dir, 'figures', 'pca_embedding.pdf'))


def plot_viewsphere_for_embedding(Rs_viewpoints, eval_dir):
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(Rs_viewpoints))
    ax.scatter(Rs_viewpoints[:, 2, 0], Rs_viewpoints[:, 2, 1],
        Rs_viewpoints[:, 2, 2], c=c, marker='.', label='embed viewpoints')
    plt.title('Embedding Viewpoints')
    plt.legend()
    plt.savefig(os.path.join(eval_dir, 'figures', 'embedding_viewpoints.pdf'))


def plot_t_err_hist(t_errors, eval_dir):
    x = np.sort(np.abs(t_errors[:, 0]))
    y = np.sort(np.abs(t_errors[:, 1]))
    z = np.sort(np.abs(t_errors[:, 2]))
    recall = (np.arange(len(t_errors)) + 1.0) / len(t_errors)
    fig = plt.figure()
    plt.title('Recall vs Translation Error')
    plt.grid()
    plt.plot(x, recall)
    plt.plot(y, recall)
    plt.plot(z, recall)
    plt.xlabel('translation err [mm]')
    plt.ylabel('recall')
    plt.legend(['cum x error', 'cum y error', 'cum z error'])
    tikz_save(os.path.join(eval_dir, 'latex', 't_err_hist.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_t_err_hist2(t_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title('Translation Error Histogram')
    plt.xlabel('translation err [mm]')
    plt.ylabel('views')
    bounds = np.linspace(0, 100, bins + 1)
    bin_count = []
    eucl_terr = np.linalg.norm(t_errors, axis=1)
    for idx in range(bins):
        bin_idcs = np.where((eucl_terr > bounds[idx]) & (eucl_terr < bounds
            [idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 100 * 0.5 / bins)
    tikz_save(os.path.join(eval_dir, 'latex', 't_err_hist2.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_R_err_hist2(R_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title('Rotation Error Histogram')
    plt.xlabel('Rotation err [deg]')
    plt.ylabel('views')
    bounds = np.linspace(0, 180, bins + 1)
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((R_errors > bounds[idx]) & (R_errors < bounds[
            idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 180 * 0.5 / bins)
    tikz_save(os.path.join(eval_dir, 'latex', 'R_err_hist2.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_R_err_hist(eval_args, eval_dir, scene_ids):
    top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    top_n = eval_args.getint('METRIC', 'TOP_N')
    cam_type = eval_args.get('DATA', 'cam_type')
    dataset_name = eval_args.get('DATA', 'dataset')
    obj_id = eval_args.getint('DATA', 'obj_id')
    if top_n_eval < 1:
        return
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    angle_errs = []
    for scene_id in scene_ids:
        error_file_path = os.path.join(eval_dir, 'error=re_ntop=%s' % top_n,
            'errors_{:02d}.yml'.format(scene_id))
        if not os.path.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        re_dict = inout.load_yaml(error_file_path)
        for view in range(len(gts)):
            res = re_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for re_e in res:
                            angle_errs += [list(re_e['errors'].values())[0]]
    if len(angle_errs) == 0:
        return
    angle_errs = np.array(angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.xlabel('angle err [deg]')
    plt.ylabel('recall')
    plt.title('Angle Error vs Recall')
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = len(angle_errs) / top_n
        min_angle_errs = np.empty((total_views,))
        min_angle_errs_rect = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = angle_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_angle_errs[view] = np.min(top_n_errors)
            min_angle_errs_rect[view] = np.min(np.hstack((top_n_errors, 180 -
                top_n_errors)))
        min_angle_errs_sorted = np.sort(min_angle_errs)
        min_angle_errs_rect_sorted = np.sort(min_angle_errs_rect)
        recall = (np.arange(total_views) + 1.0) / total_views
        min_angle_errs_sorted = np.hstack((min_angle_errs_sorted, np.array(
            [180.0])))
        min_angle_errs_rect_sorted = np.hstack((min_angle_errs_rect_sorted,
            np.array([90.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_angle = np.trapz(recall, min_angle_errs_sorted / 180.0)
        AUC_angle_rect = np.trapz(recall, min_angle_errs_rect_sorted / 90.0)
        plt.plot(min_angle_errs_sorted, recall)
        plt.plot(min_angle_errs_rect_sorted, recall)
        legend += ['top {0} angle err, AUC = {1:.4f}'.format(n, AUC_angle),
            'top {0} rectified angle err, AUC = {1:.4f}'.format(n,
            AUC_angle_rect)]
    plt.legend(legend)
    tikz_save(osp.join(eval_dir, 'latex', 'R_err_hist.tex'), figurewidth=
        '0.45\\textheight', figureheight='0.45\\textheight', show_info=False)


def print_trans_rot_errors(gts, obj_id, ts_est, ts_est_old, Rs_est, Rs_est_old
    ):
    t_errs = []
    obj_gts = []
    for gt in gts:
        if gt['obj_id'] == obj_id:
            t_errs.append(ts_est[0] - gt['cam_t_m2c'].squeeze())
            obj_gts.append(gt)
    min_t_err_idx = np.argmin(np.linalg.norm(np.array(t_errs), axis=1))
    print(min_t_err_idx)
    print(np.array(t_errs).shape)
    print(len(obj_gts))
    gt = obj_gts[min_t_err_idx].copy()
    try:
        print('Translation Error before refinement')
        print(ts_est_old[0] - gt['cam_t_m2c'].squeeze())
        print('Translation Error after refinement')
        print(t_errs[min_t_err_idx])
        print('Rotation Error before refinement')
        print(pose_error.re(Rs_est_old[0], gt['cam_R_m2c']))
        print('Rotation Error after refinement')
        R_err = pose_error.re(Rs_est[0], gt['cam_R_m2c'])
        print(R_err)
    except:
        pass
    return t_errs[min_t_err_idx], R_err


def plot_vsd_err_hist(eval_dir, scene_ids, obj_id, dataset_name='linemod',
    top_n=1, delta=15, tau=20, cost='step', cam_type='primesense'):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    vsd_errs = []
    for scene_id in scene_ids:
        if dataset_name in ['linemod', 'hinterstoisser']:
            if obj_id != scene_id:
                continue
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        vsd_dict = inout.load_yaml(error_file_path)
        for view, vsd_e in enumerate(vsd_dict):
            vsds = vsd_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for vsd_e in vsds:
                            vsd_errs += [list(vsd_e['errors'].values())[0]]
    if len(vsd_errs) == 0:
        return
    vsd_errs = np.array(vsd_errs)
    logger.info('vsd errs: {}'.format(len(vsd_errs)))
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.xlabel('vsd err')
    plt.ylabel('recall')
    plt.title('obj: {}, VSD Error vs Recall'.format(obj_id))
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = int(len(vsd_errs) / top_n)
        min_vsd_errs = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = vsd_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_vsd_errs[view] = np.min(top_n_errors)
        min_vsd_errs_sorted = np.sort(min_vsd_errs)
        recall = np.float32(np.arange(total_views) + 1.0) / total_views
        min_vsd_errs_sorted = np.hstack((min_vsd_errs_sorted, np.array([1.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_vsd = np.trapz(recall, min_vsd_errs_sorted)
        plt.plot(min_vsd_errs_sorted, recall)
        legend += ['top {0} vsd err, AUC = {1:.4f}'.format(n, AUC_vsd)]
        logger.info('obj:{} top {} vsd err, AUC = {:.4f}'.format(obj_id, n,
            AUC_vsd))
    plt.legend(legend)
    out_file = osp.join(eval_dir, 'latex', 'vsd_err_hist_obj_{:02d}.tex'.
        format(obj_id))
    mkdir_p(osp.dirname(out_file))
    logger.info(osp.basename(out_file))
    tikz_save(out_file, figurewidth='0.45\\textheight', figureheight=
        '0.45\\textheight', show_info=False)


def plot_vsd_occlusion(eval_dir, scene_ids, all_test_visibs, top_n=1, delta
    =15, tau=20, cost='step', bins=10):
    all_vsd_errs = []
    for scene_id in scene_ids:
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        vsd_dict = inout.load_yaml(error_file_path)
        all_vsd_errs += [list(vsd_e['errors'].values())[0] for vsd_e in
            vsd_dict]
    if len(all_vsd_errs) == 0:
        return
    all_vsd_errs = np.array(all_vsd_errs)
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.ylabel('vsd err')
    plt.xlabel('visibility [percent]')
    total_views = len(all_vsd_errs) / top_n
    vsd_errs = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_vsd_errs[view * top_n:(view + 1) * top_n]
        vsd_errs[view] = top_n_errors[0]
    bounds = np.linspace(0, 1, bins + 1)
    bin_vsd_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_vsd_errs.append(vsd_errs[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_vsd_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Mean VSD Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'vsd_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_re_rect_occlusion(eval_dir, scene_ids, all_test_visibs, bins=10,
    top_n=1):
    all_angle_errs = []
    for scene_id in scene_ids:
        if not os.path.exists(os.path.join(eval_dir, 'error=re_ntop=%s' %
            top_n, 'errors_{:02d}.yml'.format(scene_id))):
            print('WARNING: ' + osp.join(eval_dir, 'error=re_ntop=%s' %
                top_n, 'errors_{:02d}.yml'.format(scene_id)) + ' not found')
            continue
        angle_errs_dict = inout.load_yaml(os.path.join(eval_dir, 
            'error=re_ntop=%s' % top_n, 'errors_{:02d}.yml'.format(scene_id)))
        all_angle_errs += [list(angle_e['errors'].values())[0] for angle_e in
            angle_errs_dict]
    if len(all_angle_errs) == 0:
        return
    all_angle_errs = np.array(all_angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.ylabel('rot err [deg]')
    plt.xlabel('visibility [percent]')
    total_views = len(all_angle_errs) / top_n
    angle_errs_rect = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_angle_errs[view * top_n:(view + 1) * top_n]
        angle_errs_rect[view] = np.min([top_n_errors[0], 180 - top_n_errors[0]]
            )
    bounds = np.linspace(0, 1, bins + 1)
    bin_angle_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_angle_errs.append(angle_errs_rect[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_angle_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Median Rectified Rotation Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'R_err_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


<mask token>

<mask token>


def tiles(batch, rows, cols, spacing_x=0, spacing_y=0, scale=1.0):
    if batch.ndim == 4:
        N, H, W, C = batch.shape
    elif batch.ndim == 3:
        N, H, W = batch.shape
        C = 1
    else:
        raise ValueError('Invalid batch shape: {}'.format(batch.shape))
    H = int(H * scale)
    W = int(W * scale)
    img = np.ones((rows * H + (rows - 1) * spacing_y, cols * W + (cols - 1) *
        spacing_x, C))
    i = 0
    for row in range(rows):
        for col in range(cols):
            start_y = row * (H + spacing_y)
            end_y = start_y + H
            start_x = col * (W + spacing_x)
            end_x = start_x + W
            if i < N:
                if C > 1:
                    img[start_y:end_y, start_x:end_x, :] = cv2.resize(batch
                        [i], (W, H))
                else:
                    img[start_y:end_y, start_x:end_x, 0] = cv2.resize(batch
                        [i], (W, H))
            i += 1
    return img


def plot_reconstruction_test(sess, encoder, decoder, x):
    if x.dtype == 'uint8':
        x = x / 255.0
        print('converted uint8 to float type')
    if x.ndim == 3:
        x = np.expand_dims(x, 0)
    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    cv2.imshow('reconst_test', cv2.resize(reconst[0], (256, 256)))


def plot_reconstruction_test_batch(sess, codebook, decoder, test_img_crops,
    noof_scene_views, obj_id, eval_dir=None):
    encoder = codebook._encoder
    dataset = codebook._dataset
    sample_views = np.random.choice(noof_scene_views, np.min([100,
        noof_scene_views]), replace=False)
    sample_batch = []
    i = 0
    j = 0
    while i < 16:
        if test_img_crops[sample_views[j]].has_key(obj_id):
            sample_batch.append(test_img_crops[sample_views[j]][obj_id][0])
            i += 1
        j += 1
    x = np.array(sample_batch).squeeze()
    if x.dtype == 'uint8':
        x = x / 255.0
        print('converted uint8 to float type')
    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    nearest_neighbors = []
    for xi in x:
        Rs_est = codebook.nearest_rotation(sess, xi, top_n=8)
        pred_views = []
        pred_views.append(xi * 255)
        for R_est in Rs_est:
            pred_views.append(dataset.render_rot(R_est, downSample=1))
        nearest_neighbors.append(tiles(np.array(pred_views), 1, len(
            pred_views), 10, 10))
    all_nns_img = tiles(np.array(nearest_neighbors), len(nearest_neighbors),
        1, 10, 10)
    reconstruction_imgs = np.hstack((tiles(x, 4, 4), tiles(reconst, 4, 4)))
    cv2.imwrite(os.path.join(eval_dir, 'figures', 'reconstruction_imgs.png'
        ), reconstruction_imgs * 255)
    cv2.imwrite(os.path.join(eval_dir, 'figures',
        'nearest_neighbors_imgs.png'), all_nns_img)


def plot_reconstruction_train(sess, decoder, train_code):
    if train_code.ndim == 1:
        train_code = np.expand_dims(train_code, 0)
    reconst = sess.run(decoder.x, feed_dict={decoder._latent_code: train_code})
    cv2.imshow('reconst_train', cv2.resize(reconst[0], (256, 256)))


def show_nearest_rotation(pred_views, test_crop, view):
    print(np.array(pred_views).shape)
    nearest_views = tiles(np.array(pred_views), 1, len(pred_views), 10, 10)
    cv2.imshow('nearest_views', cv2.resize(nearest_views / 255.0, (len(
        pred_views) * 256, 256)))
    cv2.imshow('test_crop', cv2.resize(test_crop, (256, 256)))


def plot_scene_with_3DBoxes(scene_res_dirs, dataset_name='tless', scene_id=
    1, save=False):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='')
    models_cad_files = sorted(glob.glob(os.path.join(os.path.dirname(
        data_params['model_mpath']), '*.ply')))
    W, H = data_params['test_im_size']
    from lib.meshrenderer import box3d_renderer
    renderer_line = box3d_renderer.Renderer(models_cad_files, 1, W, H)
    scene_result_dirs = sorted(glob.glob(scene_res_dirs))
    print(data_params['test_rgb_mpath'])
    print(data_params['scene_gt_mpath'])
    scene_gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
    scene_infos = inout.load_info(data_params['scene_info_mpath'].format(
        scene_id))
    scene_dirs = [d for d in scene_result_dirs if '%02d' % scene_id == d.
        split('/')[-1]]
    print(scene_dirs)
    for view in range(len(scene_infos)):
        sixd_img_path = data_params['test_rgb_mpath'].format(scene_id, view)
        img = cv2.imread(sixd_img_path)
        box_img = img.copy()
        K = scene_infos[view]['cam_K']
        for bb in scene_gts[view]:
            xmin = int(bb['obj_bb'][0])
            ymin = int(bb['obj_bb'][1])
            xmax = int(bb['obj_bb'][0] + bb['obj_bb'][2])
            ymax = int(bb['obj_bb'][1] + bb['obj_bb'][3])
            cv2.rectangle(box_img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
            cv2.putText(box_img, '%s' % bb['obj_id'], (xmin, ymax + 20),
                cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
        for scene_dir in scene_dirs:
            try:
                res_path = glob.glob(os.path.join(scene_dir, '%04d_*.yml' %
                    view))
                print(res_path)
                res_path = res_path[0]
                obj_id = int(res_path.split('_')[-1].split('.')[0])
                results = inout.load_results_sixd17(res_path)
                print(results)
                e = results['ests'][0]
                R_est = e['R']
                t_est = e['t']
                K = scene_infos[view]['cam_K']
                lines = renderer_line.render(obj_id - 1, K, R_est, t_est, 
                    10, 5000)
                lines_mask = (np.sum(lines, axis=2) < 20)[:, :, None]
                if obj_id % 7 == 1:
                    lines[:, :, 0] = lines[:, :, 1]
                elif obj_id % 7 == 2:
                    lines[:, :, 2] = lines[:, :, 1]
                elif obj_id % 7 == 3:
                    lines[:, :, 0] = lines[:, :, 1]
                    lines[:, :, 1] = lines[:, :, 2]
                img = lines_mask * img + lines
            except:
                print('undeteceted obj: ', scene_dir)
        cv2.imshow('', img)
        if cv2.waitKey(1) == 32:
            cv2.waitKey(0)
        if save:
            if 'icp' in scene_res_dirs:
                if not os.path.exists('%02d' % scene_id):
                    os.makedirs('%02d' % scene_id)
                cv2.imwrite(os.path.join('%02d' % scene_id, '%04d.png' %
                    view), img)
            else:
                if not os.path.exists('%02d_rgb' % scene_id):
                    os.makedirs('%02d_rgb' % scene_id)
                cv2.imwrite(os.path.join('%02d_rgb' % scene_id, '%04d.png' %
                    view), img)


def plot_scene_with_estimate(test_img, renderer, K_test, R_est_old,
    t_est_old, R_est_ref, t_est_ref, test_bb, test_score, obj_id, gts=[],
    bb_pred=None):
    global view_idx
    if bb_pred is not None:
        scene_detect = test_img.copy()
        for bb in bb_pred:
            try:
                xmin = int(bb['obj_bb'][0])
                ymin = int(bb['obj_bb'][1])
                xmax = int(bb['obj_bb'][0] + bb['obj_bb'][2])
                ymax = int(bb['obj_bb'][1] + bb['obj_bb'][3])
                if obj_id == bb['obj_id']:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax),
                        (0, 255, 0), 2)
                    cv2.putText(scene_detect, '%s: %1.3f' % (bb['obj_id'],
                        bb['score']), (xmin, ymax + 20), cv2.FONT_ITALIC, 
                        0.5, (0, 255, 0), 2)
                else:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax),
                        (0, 0, 255), 2)
            except:
                pass
        cv2.imshow('scene_detect', scene_detect)
    xmin = int(test_bb[0])
    ymin = int(test_bb[1])
    xmax = int(test_bb[0] + test_bb[2])
    ymax = int(test_bb[1] + test_bb[3])
    print('here')
    obj_in_scene, _ = renderer.render(obj_id=0, W=test_img.shape[1], H=
        test_img.shape[0], K=K_test.copy(), R=R_est_old, t=np.array(
        t_est_old), near=10, far=10000, random_light=False)
    scene_view = test_img.copy()
    scene_view[obj_in_scene > 0] = obj_in_scene[obj_in_scene > 0]
    cv2.rectangle(scene_view, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
    cv2.putText(scene_view, '%s: %1.3f' % (obj_id, test_score), (xmin, ymax +
        20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
    cv2.imshow('scene_estimation', scene_view)
    obj_in_scene_ref, _ = renderer.render(obj_id=0, W=test_img.shape[1], H=
        test_img.shape[0], K=K_test.copy(), R=R_est_ref, t=np.array(
        t_est_ref), near=10, far=10000, random_light=False)
    scene_view_refined = test_img.copy()
    g_y = np.zeros_like(obj_in_scene_ref)
    g_y[:, :, 1] = obj_in_scene_ref[:, :, 1]
    scene_view_refined[obj_in_scene_ref > 0] = g_y[obj_in_scene_ref > 0
        ] * 2.0 / 3.0 + scene_view_refined[obj_in_scene_ref > 0] * 1.0 / 3.0
    cv2.rectangle(scene_view_refined, (xmin, ymin), (xmax, ymax), (0, 255, 
        0), 2)
    cv2.putText(scene_view_refined, '%s: %1.3f' % (obj_id, test_score), (
        xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
    cv2.imshow('scene_estimation_refined', scene_view_refined)
    cv2.waitKey(0)
    view_idx += 1


def compute_pca_plot_embedding(eval_dir, z_train, z_test=None, save=True):
    sklearn_pca = PCA(n_components=3)
    full_z_pca = sklearn_pca.fit_transform(z_train)
    if z_test is not None:
        full_z_pca_test = sklearn_pca.transform(z_test)
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(full_z_pca))
    ax.scatter(full_z_pca[:, 0], full_z_pca[:, 1], full_z_pca[:, 2], c=c,
        marker='.', label='PCs of train viewsphere')
    if z_test is not None:
        ax.scatter(full_z_pca_test[:, 0], full_z_pca_test[:, 1],
            full_z_pca_test[:, 2], c='red', marker='.', label='test_z')
    plt.title('Embedding Principal Components')
    ax.set_xlabel('pc1')
    ax.set_ylabel('pc2')
    ax.set_zlabel('pc3')
    plt.legend()
    pl.dump(fig, file(os.path.join(eval_dir, 'figures',
        'pca_embedding.pickle'), 'wb'))
    if save:
        plt.savefig(os.path.join(eval_dir, 'figures', 'pca_embedding.pdf'))


def plot_viewsphere_for_embedding(Rs_viewpoints, eval_dir):
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(Rs_viewpoints))
    ax.scatter(Rs_viewpoints[:, 2, 0], Rs_viewpoints[:, 2, 1],
        Rs_viewpoints[:, 2, 2], c=c, marker='.', label='embed viewpoints')
    plt.title('Embedding Viewpoints')
    plt.legend()
    plt.savefig(os.path.join(eval_dir, 'figures', 'embedding_viewpoints.pdf'))


def plot_t_err_hist(t_errors, eval_dir):
    x = np.sort(np.abs(t_errors[:, 0]))
    y = np.sort(np.abs(t_errors[:, 1]))
    z = np.sort(np.abs(t_errors[:, 2]))
    recall = (np.arange(len(t_errors)) + 1.0) / len(t_errors)
    fig = plt.figure()
    plt.title('Recall vs Translation Error')
    plt.grid()
    plt.plot(x, recall)
    plt.plot(y, recall)
    plt.plot(z, recall)
    plt.xlabel('translation err [mm]')
    plt.ylabel('recall')
    plt.legend(['cum x error', 'cum y error', 'cum z error'])
    tikz_save(os.path.join(eval_dir, 'latex', 't_err_hist.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_t_err_hist2(t_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title('Translation Error Histogram')
    plt.xlabel('translation err [mm]')
    plt.ylabel('views')
    bounds = np.linspace(0, 100, bins + 1)
    bin_count = []
    eucl_terr = np.linalg.norm(t_errors, axis=1)
    for idx in range(bins):
        bin_idcs = np.where((eucl_terr > bounds[idx]) & (eucl_terr < bounds
            [idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 100 * 0.5 / bins)
    tikz_save(os.path.join(eval_dir, 'latex', 't_err_hist2.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_R_err_hist2(R_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title('Rotation Error Histogram')
    plt.xlabel('Rotation err [deg]')
    plt.ylabel('views')
    bounds = np.linspace(0, 180, bins + 1)
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((R_errors > bounds[idx]) & (R_errors < bounds[
            idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 180 * 0.5 / bins)
    tikz_save(os.path.join(eval_dir, 'latex', 'R_err_hist2.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_R_err_hist(eval_args, eval_dir, scene_ids):
    top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    top_n = eval_args.getint('METRIC', 'TOP_N')
    cam_type = eval_args.get('DATA', 'cam_type')
    dataset_name = eval_args.get('DATA', 'dataset')
    obj_id = eval_args.getint('DATA', 'obj_id')
    if top_n_eval < 1:
        return
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    angle_errs = []
    for scene_id in scene_ids:
        error_file_path = os.path.join(eval_dir, 'error=re_ntop=%s' % top_n,
            'errors_{:02d}.yml'.format(scene_id))
        if not os.path.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        re_dict = inout.load_yaml(error_file_path)
        for view in range(len(gts)):
            res = re_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for re_e in res:
                            angle_errs += [list(re_e['errors'].values())[0]]
    if len(angle_errs) == 0:
        return
    angle_errs = np.array(angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.xlabel('angle err [deg]')
    plt.ylabel('recall')
    plt.title('Angle Error vs Recall')
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = len(angle_errs) / top_n
        min_angle_errs = np.empty((total_views,))
        min_angle_errs_rect = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = angle_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_angle_errs[view] = np.min(top_n_errors)
            min_angle_errs_rect[view] = np.min(np.hstack((top_n_errors, 180 -
                top_n_errors)))
        min_angle_errs_sorted = np.sort(min_angle_errs)
        min_angle_errs_rect_sorted = np.sort(min_angle_errs_rect)
        recall = (np.arange(total_views) + 1.0) / total_views
        min_angle_errs_sorted = np.hstack((min_angle_errs_sorted, np.array(
            [180.0])))
        min_angle_errs_rect_sorted = np.hstack((min_angle_errs_rect_sorted,
            np.array([90.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_angle = np.trapz(recall, min_angle_errs_sorted / 180.0)
        AUC_angle_rect = np.trapz(recall, min_angle_errs_rect_sorted / 90.0)
        plt.plot(min_angle_errs_sorted, recall)
        plt.plot(min_angle_errs_rect_sorted, recall)
        legend += ['top {0} angle err, AUC = {1:.4f}'.format(n, AUC_angle),
            'top {0} rectified angle err, AUC = {1:.4f}'.format(n,
            AUC_angle_rect)]
    plt.legend(legend)
    tikz_save(osp.join(eval_dir, 'latex', 'R_err_hist.tex'), figurewidth=
        '0.45\\textheight', figureheight='0.45\\textheight', show_info=False)


def print_trans_rot_errors(gts, obj_id, ts_est, ts_est_old, Rs_est, Rs_est_old
    ):
    t_errs = []
    obj_gts = []
    for gt in gts:
        if gt['obj_id'] == obj_id:
            t_errs.append(ts_est[0] - gt['cam_t_m2c'].squeeze())
            obj_gts.append(gt)
    min_t_err_idx = np.argmin(np.linalg.norm(np.array(t_errs), axis=1))
    print(min_t_err_idx)
    print(np.array(t_errs).shape)
    print(len(obj_gts))
    gt = obj_gts[min_t_err_idx].copy()
    try:
        print('Translation Error before refinement')
        print(ts_est_old[0] - gt['cam_t_m2c'].squeeze())
        print('Translation Error after refinement')
        print(t_errs[min_t_err_idx])
        print('Rotation Error before refinement')
        print(pose_error.re(Rs_est_old[0], gt['cam_R_m2c']))
        print('Rotation Error after refinement')
        R_err = pose_error.re(Rs_est[0], gt['cam_R_m2c'])
        print(R_err)
    except:
        pass
    return t_errs[min_t_err_idx], R_err


def plot_vsd_err_hist(eval_dir, scene_ids, obj_id, dataset_name='linemod',
    top_n=1, delta=15, tau=20, cost='step', cam_type='primesense'):
    data_params = dataset_params.get_dataset_params(dataset_name,
        model_type='', train_type='', test_type=cam_type, cam_type=cam_type)
    vsd_errs = []
    for scene_id in scene_ids:
        if dataset_name in ['linemod', 'hinterstoisser']:
            if obj_id != scene_id:
                continue
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        gts = inout.load_gt(data_params['scene_gt_mpath'].format(scene_id))
        visib_gts = inout.load_yaml(data_params['scene_gt_stats_mpath'].
            format(scene_id, 15))
        vsd_dict = inout.load_yaml(error_file_path)
        for view, vsd_e in enumerate(vsd_dict):
            vsds = vsd_dict[view * top_n:(view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt['obj_id'] == obj_id:
                    if visib_gt['visib_fract'] > 0.1:
                        for vsd_e in vsds:
                            vsd_errs += [list(vsd_e['errors'].values())[0]]
    if len(vsd_errs) == 0:
        return
    vsd_errs = np.array(vsd_errs)
    logger.info('vsd errs: {}'.format(len(vsd_errs)))
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.xlabel('vsd err')
    plt.ylabel('recall')
    plt.title('obj: {}, VSD Error vs Recall'.format(obj_id))
    legend = []
    for n in np.unique(np.array([top_n, 1])):
        total_views = int(len(vsd_errs) / top_n)
        min_vsd_errs = np.empty((total_views,))
        for view in range(total_views):
            top_n_errors = vsd_errs[view * top_n:(view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_vsd_errs[view] = np.min(top_n_errors)
        min_vsd_errs_sorted = np.sort(min_vsd_errs)
        recall = np.float32(np.arange(total_views) + 1.0) / total_views
        min_vsd_errs_sorted = np.hstack((min_vsd_errs_sorted, np.array([1.0])))
        recall = np.hstack((recall, np.array([1.0])))
        AUC_vsd = np.trapz(recall, min_vsd_errs_sorted)
        plt.plot(min_vsd_errs_sorted, recall)
        legend += ['top {0} vsd err, AUC = {1:.4f}'.format(n, AUC_vsd)]
        logger.info('obj:{} top {} vsd err, AUC = {:.4f}'.format(obj_id, n,
            AUC_vsd))
    plt.legend(legend)
    out_file = osp.join(eval_dir, 'latex', 'vsd_err_hist_obj_{:02d}.tex'.
        format(obj_id))
    mkdir_p(osp.dirname(out_file))
    logger.info(osp.basename(out_file))
    tikz_save(out_file, figurewidth='0.45\\textheight', figureheight=
        '0.45\\textheight', show_info=False)


def plot_vsd_occlusion(eval_dir, scene_ids, all_test_visibs, top_n=1, delta
    =15, tau=20, cost='step', bins=10):
    all_vsd_errs = []
    for scene_id in scene_ids:
        error_file_path = osp.join(eval_dir, 
            'error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s' % (top_n, delta,
            tau, cost), 'errors_{:02d}.yml'.format(scene_id))
        if not osp.exists(error_file_path):
            print('WARNING: ' + error_file_path + ' not found')
            continue
        vsd_dict = inout.load_yaml(error_file_path)
        all_vsd_errs += [list(vsd_e['errors'].values())[0] for vsd_e in
            vsd_dict]
    if len(all_vsd_errs) == 0:
        return
    all_vsd_errs = np.array(all_vsd_errs)
    fig = plt.figure()
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.ylabel('vsd err')
    plt.xlabel('visibility [percent]')
    total_views = len(all_vsd_errs) / top_n
    vsd_errs = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_vsd_errs[view * top_n:(view + 1) * top_n]
        vsd_errs[view] = top_n_errors[0]
    bounds = np.linspace(0, 1, bins + 1)
    bin_vsd_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_vsd_errs.append(vsd_errs[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_vsd_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Mean VSD Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'vsd_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def plot_re_rect_occlusion(eval_dir, scene_ids, all_test_visibs, bins=10,
    top_n=1):
    all_angle_errs = []
    for scene_id in scene_ids:
        if not os.path.exists(os.path.join(eval_dir, 'error=re_ntop=%s' %
            top_n, 'errors_{:02d}.yml'.format(scene_id))):
            print('WARNING: ' + osp.join(eval_dir, 'error=re_ntop=%s' %
                top_n, 'errors_{:02d}.yml'.format(scene_id)) + ' not found')
            continue
        angle_errs_dict = inout.load_yaml(os.path.join(eval_dir, 
            'error=re_ntop=%s' % top_n, 'errors_{:02d}.yml'.format(scene_id)))
        all_angle_errs += [list(angle_e['errors'].values())[0] for angle_e in
            angle_errs_dict]
    if len(all_angle_errs) == 0:
        return
    all_angle_errs = np.array(all_angle_errs)
    fig = plt.figure()
    plt.grid()
    plt.ylabel('rot err [deg]')
    plt.xlabel('visibility [percent]')
    total_views = len(all_angle_errs) / top_n
    angle_errs_rect = np.empty((total_views,))
    for view in range(total_views):
        top_n_errors = all_angle_errs[view * top_n:(view + 1) * top_n]
        angle_errs_rect[view] = np.min([top_n_errors[0], 180 - top_n_errors[0]]
            )
    bounds = np.linspace(0, 1, bins + 1)
    bin_angle_errs = []
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (
            all_test_visibs < bounds[idx + 1]))
        bin_angle_errs.append(angle_errs_rect[bin_idcs])
        bin_count.append(len(bin_idcs[0]))
    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.boxplot(bin_angle_errs, positions=middle_bin_vis, widths=0.5 / bins,
        sym='+')
    plt.title('Visibility vs Median Rectified Rotation Error' + str(bin_count))
    tikz_save(os.path.join(eval_dir, 'latex', 'R_err_occlusion.tex'),
        figurewidth='0.45\\textheight', figureheight='0.45\\textheight',
        show_info=False)


def animate_embedding_path(z_test):
    pass

# ref: https://raw.githubusercontent.com/DLR-RM/AugmentedAutoencoder/c717cc7c7e7c468d9603d072f971fed9cb333dbe/auto_pose/eval/eval_plots.py
import os.path as osp
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib2tikz import save as tikz_save
import cv2
import os
import time
import numpy as np

# import tensorflow as tf
# from auto_pose.ae.utils import tiles
from sklearn.decomposition import PCA
import glob
import pickle as pl

from lib.pysixd import inout, pose_error, pose_error_more
from lib.pysixd import dataset_params
from lib.utils import logger
from lib.utils.fs import mkdir_p

view_idx = 0


def tiles(batch, rows, cols, spacing_x=0, spacing_y=0, scale=1.0):
    if batch.ndim == 4:
        N, H, W, C = batch.shape
    elif batch.ndim == 3:
        N, H, W = batch.shape
        C = 1
    else:
        raise ValueError("Invalid batch shape: {}".format(batch.shape))

    H = int(H * scale)
    W = int(W * scale)
    img = np.ones((rows * H + (rows - 1) * spacing_y, cols * W + (cols - 1) * spacing_x, C))
    i = 0
    for row in range(rows):
        for col in range(cols):
            start_y = row * (H + spacing_y)
            end_y = start_y + H
            start_x = col * (W + spacing_x)
            end_x = start_x + W
            if i < N:
                if C > 1:
                    img[start_y:end_y, start_x:end_x, :] = cv2.resize(batch[i], (W, H))
                else:
                    img[start_y:end_y, start_x:end_x, 0] = cv2.resize(batch[i], (W, H))
            i += 1
    return img


def plot_reconstruction_test(sess, encoder, decoder, x):
    if x.dtype == "uint8":
        x = x / 255.0
        print("converted uint8 to float type")

    if x.ndim == 3:
        x = np.expand_dims(x, 0)

    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    cv2.imshow("reconst_test", cv2.resize(reconst[0], (256, 256)))


def plot_reconstruction_test_batch(sess, codebook, decoder, test_img_crops, noof_scene_views, obj_id, eval_dir=None):

    encoder = codebook._encoder
    dataset = codebook._dataset

    sample_views = np.random.choice(noof_scene_views, np.min([100, noof_scene_views]), replace=False)

    sample_batch = []
    i = 0
    j = 0
    while i < 16:
        if test_img_crops[sample_views[j]].has_key(obj_id):
            sample_batch.append(test_img_crops[sample_views[j]][obj_id][0])
            i += 1
        j += 1

    x = np.array(sample_batch).squeeze()

    if x.dtype == "uint8":
        x = x / 255.0
        print("converted uint8 to float type")

    reconst = sess.run(decoder.x, feed_dict={encoder.x: x})
    nearest_neighbors = []
    for xi in x:
        Rs_est = codebook.nearest_rotation(sess, xi, top_n=8)
        pred_views = []
        pred_views.append(xi * 255)
        for R_est in Rs_est:
            pred_views.append(dataset.render_rot(R_est, downSample=1))
        nearest_neighbors.append(tiles(np.array(pred_views), 1, len(pred_views), 10, 10))

    all_nns_img = tiles(np.array(nearest_neighbors), len(nearest_neighbors), 1, 10, 10)

    reconstruction_imgs = np.hstack((tiles(x, 4, 4), tiles(reconst, 4, 4)))
    cv2.imwrite(os.path.join(eval_dir, "figures", "reconstruction_imgs.png"), reconstruction_imgs * 255)
    cv2.imwrite(os.path.join(eval_dir, "figures", "nearest_neighbors_imgs.png"), all_nns_img)


def plot_reconstruction_train(sess, decoder, train_code):
    if train_code.ndim == 1:
        train_code = np.expand_dims(train_code, 0)
    reconst = sess.run(decoder.x, feed_dict={decoder._latent_code: train_code})
    cv2.imshow("reconst_train", cv2.resize(reconst[0], (256, 256)))


def show_nearest_rotation(pred_views, test_crop, view):
    print(np.array(pred_views).shape)
    nearest_views = tiles(np.array(pred_views), 1, len(pred_views), 10, 10)
    cv2.imshow("nearest_views", cv2.resize(nearest_views / 255.0, (len(pred_views) * 256, 256)))
    cv2.imshow("test_crop", cv2.resize(test_crop, (256, 256)))

    # cv2.imwrite('/home_local2/sund_ma/autoencoder_ws/aae_imgs/nearest_views_%s.png' % view,nearest_views)


def plot_scene_with_3DBoxes(scene_res_dirs, dataset_name="tless", scene_id=1, save=False):

    # sixd_img_path = '/home_local/sund_ma/data/linemod_dataset/test'
    # model_path = '/home_local/sund_ma/data/linemod_dataset/models'

    # inout.save_results_sixd17(res_path, preds, run_time=run_time)

    # obj_gts = []
    # obj_infos = []
    # for object_id in range(1,noofobjects+1):
    #     obj_gts.append(inout.load_gt(os.path.join(sixd_img_path,'{:02d}'.format(object_id),'gt.yml')))
    #     obj_infos.append(inout.load_info(os.path.join(sixd_img_path,'{:02d}'.format(object_id),'info.yml')))
    #     print( len(obj_gts))

    # dataset_name = eval_args.get('DATA','DATASET')
    # cam_type = eval_args.get('DATA','CAM_TYPE')

    # data_params = dataset_params.get_dataset_params(dataset_name, model_type='', train_type='', test_type='primesense', cam_type='primesense')
    data_params = dataset_params.get_dataset_params(dataset_name, model_type="", train_type="")

    models_cad_files = sorted(glob.glob(os.path.join(os.path.dirname(data_params["model_mpath"]), "*.ply")))
    W, H = data_params["test_im_size"]

    from lib.meshrenderer import box3d_renderer

    renderer_line = box3d_renderer.Renderer(models_cad_files, 1, W, H)

    scene_result_dirs = sorted(glob.glob(scene_res_dirs))
    print(data_params["test_rgb_mpath"])
    print(data_params["scene_gt_mpath"])

    # for scene_id in range(1,21):
    # sixd_img_path = data_params['test_rgb_mpath'].format(scene_id)
    scene_gts = inout.load_gt(data_params["scene_gt_mpath"].format(scene_id))
    scene_infos = inout.load_info(data_params["scene_info_mpath"].format(scene_id))

    scene_dirs = [d for d in scene_result_dirs if "%02d" % scene_id == d.split("/")[-1]]
    print(scene_dirs)

    for view in range(len(scene_infos)):
        sixd_img_path = data_params["test_rgb_mpath"].format(scene_id, view)
        img = cv2.imread(sixd_img_path)
        box_img = img.copy()
        # cv2.imshow('',img)
        # cv2.waitKey(0)
        K = scene_infos[view]["cam_K"]

        for bb in scene_gts[view]:

            xmin = int(bb["obj_bb"][0])
            ymin = int(bb["obj_bb"][1])
            xmax = int(bb["obj_bb"][0] + bb["obj_bb"][2])
            ymax = int(bb["obj_bb"][1] + bb["obj_bb"][3])

            cv2.rectangle(box_img, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
            cv2.putText(box_img, "%s" % (bb["obj_id"]), (xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
        # for gt in scene_gts[view]:
        # if gt['obj_id'] not in [1,8,9]:
        #     lines_gt = renderer_line.render(gt['obj_id']-1,K,gt['cam_R_m2c'],gt['cam_t_m2c'],10,5000)
        #     lines_gt_mask = (np.sum(lines_gt,axis=2) < 20)[:,:,None]
        #     print( lines_gt.shape)
        #     lines_gt = lines_gt[:,:,[1,0,2]]
        #     img = lines_gt_mask*img + lines_gt

        for scene_dir in scene_dirs:
            try:
                res_path = glob.glob(os.path.join(scene_dir, "%04d_*.yml" % view))
                print(res_path)
                res_path = res_path[0]
                # print( 'here', res_path)
                obj_id = int(res_path.split("_")[-1].split(".")[0])
                results = inout.load_results_sixd17(res_path)
                print(results)
                e = results["ests"][0]
                R_est = e["R"]
                t_est = e["t"]
                K = scene_infos[view]["cam_K"]
                lines = renderer_line.render(obj_id - 1, K, R_est, t_est, 10, 5000)
                lines_mask = (np.sum(lines, axis=2) < 20)[:, :, None]
                # img[lines>0] = lines[lines>0]
                if obj_id % 7 == 1:
                    lines[:, :, 0] = lines[:, :, 1]
                elif obj_id % 7 == 2:
                    lines[:, :, 2] = lines[:, :, 1]
                elif obj_id % 7 == 3:
                    lines[:, :, 0] = lines[:, :, 1]
                    lines[:, :, 1] = lines[:, :, 2]

                img = lines_mask * img + lines
            except:
                print("undeteceted obj: ", scene_dir)
        cv2.imshow("", img)
        if cv2.waitKey(1) == 32:
            cv2.waitKey(0)
        if save:
            if "icp" in scene_res_dirs:
                if not os.path.exists("%02d" % scene_id):
                    os.makedirs("%02d" % scene_id)
                cv2.imwrite(os.path.join("%02d" % scene_id, "%04d.png" % view), img)
            else:

                if not os.path.exists("%02d_rgb" % scene_id):
                    os.makedirs("%02d_rgb" % scene_id)
                cv2.imwrite(os.path.join("%02d_rgb" % scene_id, "%04d.png" % view), img)
            # cv2.imwrite(os.path.join('%02d' % scene_id,'%04d_boxes.png' % view), box_img)


def plot_scene_with_estimate(
    test_img,
    renderer,
    K_test,
    R_est_old,
    t_est_old,
    R_est_ref,
    t_est_ref,
    test_bb,
    test_score,
    obj_id,
    gts=[],
    bb_pred=None,
):
    global view_idx
    if bb_pred is not None:
        scene_detect = test_img.copy()
        for bb in bb_pred:
            try:
                xmin = int(bb["obj_bb"][0])
                ymin = int(bb["obj_bb"][1])
                xmax = int(bb["obj_bb"][0] + bb["obj_bb"][2])
                ymax = int(bb["obj_bb"][1] + bb["obj_bb"][3])
                if obj_id == bb["obj_id"]:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
                    cv2.putText(
                        scene_detect,
                        "%s: %1.3f" % (bb["obj_id"], bb["score"]),
                        (xmin, ymax + 20),
                        cv2.FONT_ITALIC,
                        0.5,
                        (0, 255, 0),
                        2,
                    )
                else:
                    cv2.rectangle(scene_detect, (xmin, ymin), (xmax, ymax), (0, 0, 255), 2)
                    # cv2.putText(scene_detect, '%s: %1.3f' % (bb['obj_id'],bb['score']), (xmin, ymax+20), cv2.FONT_ITALIC, .5, (0,0,255), 2)
            except:
                pass
            # cv2.putText(scene_detect, '%s: %1.3f' % (obj_id,test_score), (xmin, ymax+20), cv2.FONT_ITALIC, .5, (0,255,0), 2)
        cv2.imshow("scene_detect", scene_detect)

    xmin = int(test_bb[0])
    ymin = int(test_bb[1])
    xmax = int(test_bb[0] + test_bb[2])
    ymax = int(test_bb[1] + test_bb[3])

    print("here")
    obj_in_scene, _ = renderer.render(
        obj_id=0,
        W=test_img.shape[1],
        H=test_img.shape[0],
        K=K_test.copy(),
        R=R_est_old,
        t=np.array(t_est_old),
        near=10,
        far=10000,
        random_light=False,
    )
    scene_view = test_img.copy()
    scene_view[obj_in_scene > 0] = obj_in_scene[obj_in_scene > 0]
    cv2.rectangle(scene_view, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
    cv2.putText(scene_view, "%s: %1.3f" % (obj_id, test_score), (xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2)
    cv2.imshow("scene_estimation", scene_view)

    obj_in_scene_ref, _ = renderer.render(
        obj_id=0,
        W=test_img.shape[1],
        H=test_img.shape[0],
        K=K_test.copy(),
        R=R_est_ref,
        t=np.array(t_est_ref),
        near=10,
        far=10000,
        random_light=False,
    )
    scene_view_refined = test_img.copy()

    g_y = np.zeros_like(obj_in_scene_ref)
    g_y[:, :, 1] = obj_in_scene_ref[:, :, 1]
    scene_view_refined[obj_in_scene_ref > 0] = (
        g_y[obj_in_scene_ref > 0] * 2.0 / 3.0 + scene_view_refined[obj_in_scene_ref > 0] * 1.0 / 3.0
    )
    # scene_view_refined[obj_in_scene_ref > 0] = obj_in_scene_ref[obj_in_scene_ref > 0]
    cv2.rectangle(scene_view_refined, (xmin, ymin), (xmax, ymax), (0, 255, 0), 2)
    cv2.putText(
        scene_view_refined, "%s: %1.3f" % (obj_id, test_score), (xmin, ymax + 20), cv2.FONT_ITALIC, 0.5, (0, 255, 0), 2
    )
    cv2.imshow("scene_estimation_refined", scene_view_refined)
    cv2.waitKey(0)
    # cv2.imwrite('/net/rmc-lx0314/home_local/sund_ma/autoencoder_ws/bosch/thr_sc2_obj7/%s.png'% view_idx,scene_view_refined)
    view_idx += 1

    # for gt in gts:
    #     if gt['obj_id'] == obj_id:
    #         obj_in_scene, _ = renderer.render( obj_id=0, W=test_img.shape[1],H=test_img.shape[0], K=K_test.copy(), R=gt['cam_R_m2c'], t=np.array(gt['cam_t_m2c']),near=10,far=10000,random_light=False)
    #         scene_view = test_img.copy()
    #         scene_view[obj_in_scene > 0] = obj_in_scene[obj_in_scene > 0]
    #         cv2.imshow('ground truth scene_estimation',scene_view)


def compute_pca_plot_embedding(eval_dir, z_train, z_test=None, save=True):
    sklearn_pca = PCA(n_components=3)
    full_z_pca = sklearn_pca.fit_transform(z_train)
    if z_test is not None:
        full_z_pca_test = sklearn_pca.transform(z_test)

    fig = plt.figure()
    ax = Axes3D(fig)

    c = np.linspace(0, 1, len(full_z_pca))
    ax.scatter(full_z_pca[:, 0], full_z_pca[:, 1], full_z_pca[:, 2], c=c, marker=".", label="PCs of train viewsphere")
    if z_test is not None:
        ax.scatter(
            full_z_pca_test[:, 0], full_z_pca_test[:, 1], full_z_pca_test[:, 2], c="red", marker=".", label="test_z"
        )

    plt.title("Embedding Principal Components")
    ax.set_xlabel("pc1")
    ax.set_ylabel("pc2")
    ax.set_zlabel("pc3")

    plt.legend()
    pl.dump(fig, file(os.path.join(eval_dir, "figures", "pca_embedding.pickle"), "wb"))
    if save:
        plt.savefig(os.path.join(eval_dir, "figures", "pca_embedding.pdf"))


def plot_viewsphere_for_embedding(Rs_viewpoints, eval_dir):
    fig = plt.figure()
    ax = Axes3D(fig)
    c = np.linspace(0, 1, len(Rs_viewpoints))
    ax.scatter(
        Rs_viewpoints[:, 2, 0],
        Rs_viewpoints[:, 2, 1],
        Rs_viewpoints[:, 2, 2],
        c=c,
        marker=".",
        label="embed viewpoints",
    )
    plt.title("Embedding Viewpoints")
    plt.legend()
    plt.savefig(os.path.join(eval_dir, "figures", "embedding_viewpoints.pdf"))


def plot_t_err_hist(t_errors, eval_dir):

    x = np.sort(np.abs(t_errors[:, 0]))
    y = np.sort(np.abs(t_errors[:, 1]))
    z = np.sort(np.abs(t_errors[:, 2]))

    recall = (np.arange(len(t_errors)) + 1.0) / len(t_errors)

    fig = plt.figure()
    plt.title("Recall vs Translation Error")
    plt.grid()
    plt.plot(x, recall)
    plt.plot(y, recall)
    plt.plot(z, recall)
    plt.xlabel("translation err [mm]")
    plt.ylabel("recall")
    plt.legend(["cum x error", "cum y error", "cum z error"])
    tikz_save(
        os.path.join(eval_dir, "latex", "t_err_hist.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def plot_t_err_hist2(t_errors, eval_dir, bins=15):
    fig = plt.figure()
    plt.title("Translation Error Histogram")
    plt.xlabel("translation err [mm]")
    plt.ylabel("views")
    bounds = np.linspace(0, 100, bins + 1)
    bin_count = []
    eucl_terr = np.linalg.norm(t_errors, axis=1)
    for idx in range(bins):
        bin_idcs = np.where((eucl_terr > bounds[idx]) & (eucl_terr < bounds[idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 100 * 0.5 / bins)
    tikz_save(
        os.path.join(eval_dir, "latex", "t_err_hist2.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def plot_R_err_hist2(R_errors, eval_dir, bins=15):

    fig = plt.figure()
    plt.title("Rotation Error Histogram")
    plt.xlabel("Rotation err [deg]")
    plt.ylabel("views")
    bounds = np.linspace(0, 180, bins + 1)
    bin_count = []
    for idx in range(bins):
        bin_idcs = np.where((R_errors > bounds[idx]) & (R_errors < bounds[idx + 1]))
        bin_count.append(len(bin_idcs[0]))
    middle_bin = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    plt.bar(middle_bin, bin_count, 180 * 0.5 / bins)
    tikz_save(
        os.path.join(eval_dir, "latex", "R_err_hist2.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def plot_R_err_hist(eval_args, eval_dir, scene_ids):

    top_n_eval = eval_args.getint("EVALUATION", "TOP_N_EVAL")
    top_n = eval_args.getint("METRIC", "TOP_N")
    cam_type = eval_args.get("DATA", "cam_type")
    dataset_name = eval_args.get("DATA", "dataset")
    obj_id = eval_args.getint("DATA", "obj_id")

    if top_n_eval < 1:
        return

    data_params = dataset_params.get_dataset_params(
        dataset_name, model_type="", train_type="", test_type=cam_type, cam_type=cam_type
    )

    angle_errs = []
    for scene_id in scene_ids:
        error_file_path = os.path.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))
        if not os.path.exists(error_file_path):
            print("WARNING: " + error_file_path + " not found")
            continue
        # angle_errs_dict = inout.load_yaml(error_file_path)
        # angle_errs += [list(angle_e['errors'].values())[0] for angle_e in angle_errs_dict]

        gts = inout.load_gt(data_params["scene_gt_mpath"].format(scene_id))
        visib_gts = inout.load_yaml(data_params["scene_gt_stats_mpath"].format(scene_id, 15))
        re_dict = inout.load_yaml(error_file_path)

        for view in range(len(gts)):
            res = re_dict[view * top_n : (view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt["obj_id"] == obj_id:
                    if visib_gt["visib_fract"] > 0.1:
                        for re_e in res:
                            angle_errs += [list(re_e["errors"].values())[0]]

    if len(angle_errs) == 0:
        return

    angle_errs = np.array(angle_errs)

    fig = plt.figure()  # noqa
    plt.grid()
    plt.xlabel("angle err [deg]")
    plt.ylabel("recall")
    plt.title("Angle Error vs Recall")
    legend = []

    for n in np.unique(np.array([top_n, 1])):

        total_views = len(angle_errs) / top_n
        min_angle_errs = np.empty((total_views,))
        min_angle_errs_rect = np.empty((total_views,))

        for view in range(total_views):
            top_n_errors = angle_errs[view * top_n : (view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_angle_errs[view] = np.min(top_n_errors)
            min_angle_errs_rect[view] = np.min(np.hstack((top_n_errors, 180 - top_n_errors)))

        min_angle_errs_sorted = np.sort(min_angle_errs)
        min_angle_errs_rect_sorted = np.sort(min_angle_errs_rect)
        recall = (np.arange(total_views) + 1.0) / total_views

        # fill curve
        min_angle_errs_sorted = np.hstack((min_angle_errs_sorted, np.array([180.0])))
        min_angle_errs_rect_sorted = np.hstack((min_angle_errs_rect_sorted, np.array([90.0])))
        recall = np.hstack((recall, np.array([1.0])))

        AUC_angle = np.trapz(recall, min_angle_errs_sorted / 180.0)
        AUC_angle_rect = np.trapz(recall, min_angle_errs_rect_sorted / 90.0)

        plt.plot(min_angle_errs_sorted, recall)
        plt.plot(min_angle_errs_rect_sorted, recall)

        legend += [
            "top {0} angle err, AUC = {1:.4f}".format(n, AUC_angle),
            "top {0} rectified angle err, AUC = {1:.4f}".format(n, AUC_angle_rect),
        ]
    plt.legend(legend)
    tikz_save(
        osp.join(eval_dir, "latex", "R_err_hist.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def print_trans_rot_errors(gts, obj_id, ts_est, ts_est_old, Rs_est, Rs_est_old):

    t_errs = []
    obj_gts = []

    for gt in gts:
        if gt["obj_id"] == obj_id:
            t_errs.append(ts_est[0] - gt["cam_t_m2c"].squeeze())
            obj_gts.append(gt)

    min_t_err_idx = np.argmin(np.linalg.norm(np.array(t_errs), axis=1))
    print(min_t_err_idx)
    print(np.array(t_errs).shape)
    print(len(obj_gts))
    gt = obj_gts[min_t_err_idx].copy()

    try:
        print("Translation Error before refinement")
        print(ts_est_old[0] - gt["cam_t_m2c"].squeeze())
        print("Translation Error after refinement")
        print(t_errs[min_t_err_idx])
        print("Rotation Error before refinement")
        print(pose_error.re(Rs_est_old[0], gt["cam_R_m2c"]))
        print("Rotation Error after refinement")
        R_err = pose_error.re(Rs_est[0], gt["cam_R_m2c"])
        print(R_err)
    except:
        pass

    return (t_errs[min_t_err_idx], R_err)


# def plot_vsd_err_hist(eval_args, eval_dir, scene_ids):
def plot_vsd_err_hist(
    eval_dir, scene_ids, obj_id, dataset_name="linemod", top_n=1, delta=15, tau=20, cost="step", cam_type="primesense"
):
    # top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    # top_n = eval_args.getint('METRIC', 'TOP_N')
    # delta = eval_args.getint('METRIC', 'VSD_DELTA')
    # tau = eval_args.getint('METRIC', 'VSD_TAU')
    # cost = eval_args.get('METRIC', 'VSD_COST')
    # cam_type = eval_args.get('DATA', 'cam_type')
    # dataset_name = eval_args.get('DATA', 'dataset')
    # obj_id = eval_args.getint('DATA', 'obj_id')
    # if top_n_eval < 1:
    #     return

    data_params = dataset_params.get_dataset_params(
        dataset_name, model_type="", train_type="", test_type=cam_type, cam_type=cam_type
    )

    vsd_errs = []
    for scene_id in scene_ids:
        if dataset_name in ["linemod", "hinterstoisser"]:
            # NOTE: linemod scene_id == obj_id
            if obj_id != scene_id:
                continue

        error_file_path = osp.join(
            eval_dir,
            "error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s" % (top_n, delta, tau, cost),
            "errors_{:02d}.yml".format(scene_id),
        )

        if not osp.exists(error_file_path):
            print("WARNING: " + error_file_path + " not found")
            continue
        gts = inout.load_gt(data_params["scene_gt_mpath"].format(scene_id))
        visib_gts = inout.load_yaml(data_params["scene_gt_stats_mpath"].format(scene_id, 15))  # delta=15
        vsd_dict = inout.load_yaml(error_file_path)
        for view, vsd_e in enumerate(vsd_dict):
            vsds = vsd_dict[view * top_n : (view + 1) * top_n]
            for gt, visib_gt in zip(gts[view], visib_gts[view]):
                if gt["obj_id"] == obj_id:
                    if visib_gt["visib_fract"] > 0.1:
                        for vsd_e in vsds:
                            vsd_errs += [list(vsd_e["errors"].values())[0]]

    if len(vsd_errs) == 0:
        return
    vsd_errs = np.array(vsd_errs)
    logger.info("vsd errs: {}".format(len(vsd_errs)))

    fig = plt.figure()  # noqa
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.xlabel("vsd err")
    plt.ylabel("recall")
    plt.title("obj: {}, VSD Error vs Recall".format(obj_id))
    legend = []

    for n in np.unique(np.array([top_n, 1])):

        total_views = int(len(vsd_errs) / top_n)
        min_vsd_errs = np.empty((total_views,))

        for view in range(total_views):
            top_n_errors = vsd_errs[view * top_n : (view + 1) * top_n]
            if n == 1:
                top_n_errors = top_n_errors[np.newaxis, 0]
            min_vsd_errs[view] = np.min(top_n_errors)

        min_vsd_errs_sorted = np.sort(min_vsd_errs)
        recall = np.float32(np.arange(total_views) + 1.0) / total_views

        # fill curve
        min_vsd_errs_sorted = np.hstack((min_vsd_errs_sorted, np.array([1.0])))
        recall = np.hstack((recall, np.array([1.0])))

        AUC_vsd = np.trapz(recall, min_vsd_errs_sorted)
        plt.plot(min_vsd_errs_sorted, recall)

        legend += ["top {0} vsd err, AUC = {1:.4f}".format(n, AUC_vsd)]
        logger.info("obj:{} top {} vsd err, AUC = {:.4f}".format(obj_id, n, AUC_vsd))
    plt.legend(legend)
    out_file = osp.join(eval_dir, "latex", "vsd_err_hist_obj_{:02d}.tex".format(obj_id))
    mkdir_p(osp.dirname(out_file))
    logger.info(osp.basename(out_file))
    tikz_save(out_file, figurewidth="0.45\\textheight", figureheight="0.45\\textheight", show_info=False)


# def plot_vsd_occlusion(eval_args, eval_dir, scene_ids, all_test_visibs, bins=10):
def plot_vsd_occlusion(eval_dir, scene_ids, all_test_visibs, top_n=1, delta=15, tau=20, cost="step", bins=10):

    # top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    # top_n = eval_args.getint('METRIC', 'TOP_N')
    # delta = eval_args.getint('METRIC', 'VSD_DELTA')
    # tau = eval_args.getint('METRIC', 'VSD_TAU')
    # cost = eval_args.get('METRIC', 'VSD_COST')

    # if top_n_eval < 1:
    #     return

    all_vsd_errs = []
    for scene_id in scene_ids:
        error_file_path = osp.join(
            eval_dir,
            "error=vsd_ntop=%s_delta=%s_tau=%s_cost=%s" % (top_n, delta, tau, cost),
            "errors_{:02d}.yml".format(scene_id),
        )

        if not osp.exists(error_file_path):
            print("WARNING: " + error_file_path + " not found")
            continue

        vsd_dict = inout.load_yaml(error_file_path)
        all_vsd_errs += [list(vsd_e["errors"].values())[0] for vsd_e in vsd_dict]

    if len(all_vsd_errs) == 0:
        return
    all_vsd_errs = np.array(all_vsd_errs)

    # print( all_vsd_errs)

    fig = plt.figure()  # noqa
    # ax = plt.axes()
    # ax.set_xlim((0.0,1.0))
    # ax.set_ylim((0.0,1.0))
    ax = plt.gca()
    ax.set_xlim((0.0, 1.0))
    plt.grid()
    plt.ylabel("vsd err")
    plt.xlabel("visibility [percent]")
    # plt.xlim((0.0, 1.0))
    # plt.ylim((0.0, 1.0))

    total_views = len(all_vsd_errs) / top_n
    vsd_errs = np.empty((total_views,))

    for view in range(total_views):
        top_n_errors = all_vsd_errs[view * top_n : (view + 1) * top_n]
        vsd_errs[view] = top_n_errors[0]

    bounds = np.linspace(0, 1, bins + 1)
    bin_vsd_errs = []
    bin_count = []

    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (all_test_visibs < bounds[idx + 1]))
        bin_vsd_errs.append(vsd_errs[bin_idcs])
        bin_count.append(len(bin_idcs[0]))

    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    # plt.bar(middle_bin_vis,mean_vsd_err,0.5/bins)

    plt.boxplot(bin_vsd_errs, positions=middle_bin_vis, widths=0.5 / bins, sym="+")

    # count_str = 'bin count ' + bins * '%s '
    # count_str = count_str % tuple(bin_count)
    plt.title("Visibility vs Mean VSD Error" + str(bin_count))
    tikz_save(
        os.path.join(eval_dir, "latex", "vsd_occlusion.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


# def plot_re_rect_occlusion(eval_args, eval_dir, scene_ids, all_test_visibs, bins=10):
def plot_re_rect_occlusion(eval_dir, scene_ids, all_test_visibs, bins=10, top_n=1):
    # top_n_eval = eval_args.getint('EVALUATION', 'TOP_N_EVAL')
    # top_n = eval_args.getint('METRIC', 'TOP_N')
    # if top_n_eval < 1:
    #     return

    all_angle_errs = []
    for scene_id in scene_ids:

        if not os.path.exists(os.path.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))):
            print(
                "WARNING: "
                + osp.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))
                + " not found"
            )
            continue

        angle_errs_dict = inout.load_yaml(
            os.path.join(eval_dir, "error=re_ntop=%s" % top_n, "errors_{:02d}.yml".format(scene_id))
        )
        all_angle_errs += [list(angle_e["errors"].values())[0] for angle_e in angle_errs_dict]

    if len(all_angle_errs) == 0:
        return
    all_angle_errs = np.array(all_angle_errs)
    # print( all_vsd_errs)

    fig = plt.figure()  # noqa
    plt.grid()
    plt.ylabel("rot err [deg]")
    plt.xlabel("visibility [percent]")
    # plt.axis((-0.1, 1.1, -0.1, 1.1))
    # plt.xlim((0.0, 1.0))
    # plt.ylim((0.0, 1.0))

    total_views = len(all_angle_errs) / top_n
    angle_errs_rect = np.empty((total_views,))

    for view in range(total_views):
        top_n_errors = all_angle_errs[view * top_n : (view + 1) * top_n]
        angle_errs_rect[view] = np.min([top_n_errors[0], 180 - top_n_errors[0]])

    bounds = np.linspace(0, 1, bins + 1)
    bin_angle_errs = []
    bin_count = []

    for idx in range(bins):
        bin_idcs = np.where((all_test_visibs > bounds[idx]) & (all_test_visibs < bounds[idx + 1]))
        # median_angle_err[idx] = np.median(angle_errs_rect[bin_idcs])
        bin_angle_errs.append(angle_errs_rect[bin_idcs])
        bin_count.append(len(bin_idcs[0]))

    middle_bin_vis = bounds[:-1] + (bounds[1] - bounds[0]) / 2.0
    # plt.bar(middle_bin_vis,median_angle_err,0.5/bins)
    plt.boxplot(bin_angle_errs, positions=middle_bin_vis, widths=0.5 / bins, sym="+")

    # count_str = 'bin count ' + bins * '%s '
    # count_str = count_str % tuple(bin_count)
    plt.title("Visibility vs Median Rectified Rotation Error" + str(bin_count))
    tikz_save(
        os.path.join(eval_dir, "latex", "R_err_occlusion.tex"),
        figurewidth="0.45\\textheight",
        figureheight="0.45\\textheight",
        show_info=False,
    )


def animate_embedding_path(z_test):
    pass
