def calc_costs_selective_with_lut(lenses,
                                  disparities,
                                  nb_strategy,
                                  technique,
                                  nb_args,
                                  max_cost,
                                  refine=True,
                                  progress_hook=print):
    """
    it firstly calculates the fine and coarse depth map based on the first "circle" (HEX_OFFSETS[1]) with lenses of same focal lens
    then it adds the other lenses (based on strategy, but the first one is always the same) and either 
    - refine the values or
    - substitute the values
    
    Then it merges the costs and returns fine and coarse
    """
    coarse_costs = dict()
    coarse_costs_merged = dict()
    fine_costs = dict()
    lens_std = dict()
    num_lenses = len(lenses)
    num_targets = 0

    # 4+2
    # using four lenses from the first circle (the 4 corners of a virtual rectangle around the lens)
    # + 2 lenses that are the closest one to the center lens
    pos1 = [[-1, -1], [-1, 2], [1, 1], [1, -2], [0, -1], [0, 1]]
    pos2 = [[-1, -1], [-2, 1], [1, 1], [2, -1], [0, -1], [0, 1]]
    pos3 = [[-2, 1], [-1, 2], [2, -1], [1, -2], [0, -1], [0, 1]]

    for i, lcoord in enumerate(lenses):

        lens = lenses[lcoord]

        # some lenses have troubles, mainly the 0-type lenses, when they are far away
        # using this solution seems better
        if rtxhexgrid.hex_focal_type(lcoord) == 0:
            pos = rtxhexgrid.HEX_OFFSETS[1]
        elif rtxhexgrid.hex_focal_type(lcoord) == 1:
            pos = pos1
        elif rtxhexgrid.hex_focal_type(lcoord) == 2:
            pos = pos1
        else:
            pdb.set_trace()

        nb_lenses = _rel_to_abs(lcoord, lenses, pos)

        if i % 100 == 0:
            progress_hook("Processing lens {0}/{1} - {2}".format(
                i, num_lenses, lcoord))

        # calculate a first guess of the disparity based on the first circle
        fine, coarse, coarse_merged, lens_var = calc_costs_per_lens(
            lens, nb_lenses, disparities, max_cost, technique)
        nb_offsets, curr_disp_avg = nb_strategy(lens,
                                                lenses,
                                                coarse,
                                                disparities,
                                                max_cost=max_cost,
                                                nb_args=nb_args)

        nb_lenses = _rel_to_abs(lcoord, lenses, nb_offsets)

        if len(nb_lenses) > 0:

            #progress_hook("Refined nb: {0}".format(nb_offsets))
            fine_2, coarse_2, _, _ = calc_costs_per_lens(
                lens, nb_lenses, disparities, max_cost, technique)

            if refine is True:
                fine = np.append(fine, fine_2, axis=0)
                coarse = np.append(coarse, coarse_2, axis=0)
            else:
                fine = fine_2
                coarse = coarse_2

        num_targets += len(fine)
        coarse_costs_merged[lcoord] = rtxdisp.merge_costs_additive(
            coarse, max_cost)
        coarse_costs[lcoord] = coarse
        fine_costs[lcoord] = np.array(
            rtxdisp.merge_costs_additive(fine, max_cost))

        lens_std[lcoord] = lens_var

    progress_hook("Num comparisons: {0}".format(num_targets))

    return fine_costs, coarse_costs, coarse_costs_merged, lens_std, num_targets, 0.0
def real_lut(lens,
             lenses,
             coarse_costs,
             disparities,
             max_cost=10.0,
             nb_args=None):

    # get some parameters
    target_lenses = list(nb_args['target_lenses'].values())
    min_disp = nb_args['min_disp']
    max_disp = nb_args['max_disp']
    trade_off = nb_args['trade_off']

    # LUT to pick best combination or best performances
    B = np.array([[np.sqrt(3) / 2, 0.5], [0, 1]]).T

    #assert len(coarse_costs) <= len(target_lenses)

    offsets = []

    tref = rtxhexgrid.hex_focal_type(lens.lcoord)

    #read the lut
    lut_filename = '../disparity/lut_table.json'
    with open(lut_filename, 'r') as f:
        lut_str = json.load(f)

    lut_length = len(lut_str['most_acc_0'])
    lut_step = (max_disp - min_disp) / lut_length
    mavg = 0
    mvavg = 0
    counter = 0

    for i, ctmp in enumerate(coarse_costs):

        m, mval = rtxdisp.cost_minimum_interp(ctmp, disparities)

        mvavg += mval
        mavg += m
        counter += 1

    # m avg should be the value for the disparity
    mavg /= (counter)
    mvavg /= counter

    # look for the correct index
    disp_int = lut_str['disp_int_interp']
    disp_int['0'][0] = 20.0  #disparities[len(disparities)-1]
    disp_int[str(len(disp_int) - 1)][1] = 0.0
    disp_vals = lut_str['disp_vals_interp']
    found = False
    finished = False
    jj = 0
    while (not found and not finished):
        if jj >= len(disp_int):
            finished = True
            jj = 0
        elif mavg < disp_int[str(jj)][0] and mavg > disp_int[str(jj)][1]:
            found = True
        else:
            jj += 1

    ### need to show somehow if I didn't find it
    #if (finished and not found):
    #print("Not found! \nmavg={0}\ndisp_int={1}\ndisp_vals={2}\n".format(mavg, disp_int, disp_vals))
    index_lut = jj  #lut_length - math.floor(m / (lut_step))
    #print("m:{0}, mval:{1}, index:{2}".format(mavg, mvavg, jj))

    if trade_off == 1:
        if tref == 0:
            strat = lut_str['most_acc_0'][index_lut]
        elif tref == 1:
            strat = lut_str['most_acc_1'][index_lut]
        elif tref == 2:
            strat = lut_str['most_acc_2'][index_lut]
    elif trade_off == 0:
        if tref == 0:
            strat = lut_str['best_perf_0'][index_lut]
        elif tref == 1:
            strat = lut_str['best_perf_1'][index_lut]
        elif tref == 2:
            strat = lut_str['best_perf_2'][index_lut]

    targets = from_strat_to_offsets(strat)

    return targets, mavg