Beispiel #1
0
def load_real_maneuver(input_cache_fish_label,
                       maneuver_index,
                       use_total_cost=False,
                       disable_wait_time=True):
    cache = pickle.load(
        open(
            os.path.join(MANEUVER_INPUT_CACHE_PATH,
                         input_cache_fish_label + ".pickle"), "rb"))
    fish = maneuveringfish.ManeuveringFish(
        fork_length=cache['fish']['fork_length_cm'],
        mean_water_velocity=cache['fish']['mean_focal_current_speed_cm_per_s'],
        base_mass=cache['fish']['mass_g'],
        temperature=cache['fish']['temperature'],
        SMR=cache['fish']['SMR'],
        max_thrust=cache['fish']['max_thrust'],
        NREI=cache['fish']['NREI'],
        use_total_cost=use_total_cost,
        disable_wait_time=disable_wait_time)
    maneuver = cache['maneuvers'][maneuver_index]
    prey_velocity = maneuver['prey_speed_cm_per_s']
    fish.focal_velocity = maneuver[
        'focal_current_speed_cm_per_s']  # todo just make this a maneuver attribute to avoid confusion
    xd, yd = maneuver['detection_point_2D_cm']
    return {
        'fish': fish,
        'fv': fish.focal_velocity,
        'pv': prey_velocity,
        'xd': xd,
        'yd': yd
    }
Beispiel #2
0
def create_typical_fish(species, **kwargs):  # typical fish
    return maneuveringfish.ManeuveringFish(
        fork_length=typical[species]['fork_length'],
        mean_water_velocity=kwargs.get(
            'mean_water_velocity', typical[species]['mean_water_velocity']),
        base_mass=typical[species]['mass'],
        temperature=typical[species]['temperature'],
        SMR=typical[species]['SMR'],
        max_thrust=typical[species]['max_thrust'],
        NREI=typical[species]['NREI'],
        use_total_cost=kwargs.get('use_total_cost', False),
        disable_wait_time=False)
Beispiel #3
0
def check_johansen_et_al(display=False, suppress_output=False):
    # Checks maneuver cost predictions against empirical measurements from Johansen et al
    # It looks like they had costs per maneuver of 1.28 mg O2 / kg for freestream swimming and 0.78 for refuge swimming,
    # both at a temperature of 15 C and velocity of 68 cm/s, with rainbow trout of size 33 cm and 423 g. With the width x
    # depth of the tube being 25 x 26 cm, we might assume the average detected prey's lateral distance was around 15 cm or
    # so, and I'll assume prey were detected fairly early (say 30 cm upstream) on average.
    fork_length = 33
    mean_water_velocity = 68
    xd = -30
    yd = 15
    max_thrust = 2.4 * fork_length + 40
    fish_mass = 423  # this input defaults the model to a rainbow trout length-mass regression
    fish_SMR = 0.0  # default to sockeye SMR for given temperature
    fish_NREI = 0.0  # unused in this case
    temperature = 15  # only for SMR
    use_total_cost = False
    disable_wait_time = False
    fish = maneuveringfish.ManeuveringFish(fork_length, mean_water_velocity,
                                           fish_mass, temperature, fish_SMR,
                                           max_thrust, fish_NREI,
                                           use_total_cost, disable_wait_time)
    detection_point_3D = (xd, yd, 0.0)
    maneuver = optimize.optimal_maneuver(fish,
                                         detection_point_3D=detection_point_3D)
    visualize.summarize_solution(maneuver,
                                 display=display,
                                 title='Cost Table Check',
                                 export_path=None,
                                 detailed=True)
    joulesPerMgO2 = 3.36 * 4.184
    costMgO2 = maneuver.activity_cost / joulesPerMgO2
    costMgO2PerKG = costMgO2 / (fish_mass / 1000)
    print("Maneuver cost of locomotion alone is ", costMgO2PerKG, "mg O2 / kg")
    print("Focal swimming cost including SMR in is ",
          3600 * (fish.focal_swimming_cost_including_SMR / joulesPerMgO2),
          " mg O2 / kg / hr"
          )  # convert from focal_swimming_cost_including_SMR in J/s
    SMR_per_hour = 3600 * (fish.SMR_J_per_s / joulesPerMgO2) / (fish_mass /
                                                                1000)
    print("SMR per hour is ", SMR_per_hour, " mg O2 / kg / hr"
          )  # convert from focal_swimming_cost_including_SMR in J/s
    print("Cost of SMR during maneuver is ",
          SMR_per_hour * maneuver.duration / 3600)
    print("Locomotion cost for focal swimming for duration of maneuver is ",
          (maneuver.duration * fish.focal_swimming_cost_of_locomotion /
           joulesPerMgO2) / (fish_mass / 1000), " mg O2 / kg")
    total_cost_during_maneuver = costMgO2PerKG + SMR_per_hour * maneuver.duration / 3600
    print(
        f"MAIN COMPARISON: estimated cost (locomotion + SMR) of maneuver is {total_cost_during_maneuver} mg O2 / kg, compared to Johansen's 1.28 mg O2 / kg"
    )
    return maneuver, fish
def fix_broken_files(fork_length, focal_velocity, prey_velocity,
                     energy_cost_file, pursuit_duration_file):
    """ I initially use the file_contents variables below to read in the values from the input files, but then
        I also use the same arrays to build up the corrected output files. """
    # Load the files and prepare NaN indices
    print("Fixing NaNs for fl={0:.1f}, fv={1:.1f}, pv={2:.1f}.".format(
        fork_length, focal_velocity, prey_velocity))
    ec_file_contents = np.genfromtxt(
        energy_cost_file,
        delimiter=',')[:, :-1]  # odd indexing avoids adding an extra NaN from
    pd_file_contents = np.genfromtxt(
        pursuit_duration_file,
        delimiter=',')[:, :-1]  # the rightmost delimiter in each row
    xs = ec_file_contents[1:, 0]
    ys = ec_file_contents[0, 1:]
    ec_data = ec_file_contents[1:, 1:]
    nan_indices = np.argwhere(np.isnan(ec_data))
    # nan_indices = np.argwhere(ec_data) # if I wanted this function to rebuild the whole table
    # Prepare the fish for calculations
    max_thrust = 2.4 * fork_length + 40
    fish_mass = 0.0  # this input defaults the model to a rainbow trout length-mass regression
    fish_SMR = 0.0  # unused in this case
    fish_NREI = 0.0  # also unused in this case
    temperature = 10  # also unused in this case
    use_total_cost = False
    disable_wait_time = False
    fish = maneuveringfish.ManeuveringFish(fork_length, focal_velocity,
                                           fish_mass, temperature, fish_SMR,
                                           max_thrust, fish_NREI,
                                           use_total_cost, disable_wait_time)
    for x_ind, y_ind in nan_indices:
        # sol = optimize_cuckoo.optimal_maneuver_CS(fish, detection_point_3D=(xs[x_ind], ys[y_ind], 0.0), prey_velocity=prey_velocity, n=25, iterations=1500, p_a=0.25, suppress_output=False) # TEMP
        sol = optimize_cuckoo.optimal_maneuver_CS(
            fish,
            detection_point_3D=(xs[x_ind], ys[y_ind], 0.0),
            prey_velocity=prey_velocity,
            n=50,
            iterations=3000,
            p_a=0.25,
            suppress_output=False)
        assert (sol.energy_cost != CONVERGENCE_FAILURE_COST)
        ec_file_contents[x_ind + 1, y_ind + 1] = sol.energy_cost
        pd_file_contents[x_ind + 1, y_ind + 1] = sol.pursuit_duration
    np.savetxt("/Users/Jason/Desktop/ManeuverTemp/ec_results.csv",
               ec_file_contents,
               fmt='%.7f,')
    np.savetxt("/Users/Jason/Desktop/ManeuverTemp/pd_results.csv",
               pd_file_contents,
               fmt='%.7f,')
Beispiel #5
0
def check_cost_table_value(fork_length,
                           mean_water_velocity,
                           xd,
                           yd,
                           display=False,
                           suppress_output=False):
    max_thrust = 2.4 * fork_length + 40
    fish_mass = 0.0  # this input defaults the model to a rainbow trout length-mass regression
    fish_SMR = 0.0  # unused in this case
    fish_NREI = 0.0  # also unused in this case
    temperature = 10  # also unused in this case
    use_total_cost = False
    disable_wait_time = False
    fish = maneuveringfish.ManeuveringFish(fork_length, mean_water_velocity,
                                           fish_mass, temperature, fish_SMR,
                                           max_thrust, fish_NREI,
                                           use_total_cost, disable_wait_time)
    detection_point_3D = (xd, yd, 0.0)
    maneuver = optimize.optimal_maneuver(fish,
                                         detection_point_3D=detection_point_3D)
    # visualize.summarize_solution(maneuver, display=display, title='Cost Table Check', export_path=None, detailed=True)
    return maneuver
        'focal_velocity': 42,
        'prey_velocity': 48,
        'mass': 920,
        'temperature': 6,
        'max_thrust': 159,
        'NREI': 0.017,
        'detection_distance': 35,
        'SMR': 40
    }
}
species = 'Dolly Varden'
fish = maneuveringfish.ManeuveringFish(
    fork_length=typical[species]['fork_length'],
    mean_water_velocity=typical[species]['focal_velocity'],
    mass=typical[species]['mass'],
    temperature=typical[species]['temperature'],
    SMR=typical[species]['SMR'],
    max_thrust=typical[species]['max_thrust'],
    NREI=typical[species]['NREI'],
    use_total_cost=False,
    disable_wait_time=False)
xd, yd = (-typical[species]['detection_distance'] / 1.414,
          typical[species]['detection_distance'] / 1.414)
prey_velocity = typical[species]['prey_velocity']


def objective_function(p):
    return maneuver.maneuver_from_proportions(fish, prey_velocity, xd, yd,
                                              p).fitness


def problem_description(verbose=True):
Beispiel #7
0
# # opt = optimize.run_convergence_test(typical_fish[species], detection_point_3D=detection_point_3D)
# opt, opt_model = optimize.optimal_maneuver(test_fish, n=DEFAULT_OPT_N, max_iterations=DEFAULT_OPT_ITERATIONS, detection_point_3D=detection_point_3D, tracked=True, return_optimization_model=True)

# best solution is 0.159198

# visualize.summarize_solution(opt, display = True, title = 'Typical Dolly', export_path = None, detailed=True, add_text_panel=True)

test_x = -135.3565092
test_y = 1.2
fork_length = 3.0
velocity = 1.0
fish = maneuveringfish.ManeuveringFish(
    fork_length=fork_length,
    mean_water_velocity=velocity,
    base_mass=0,  # defaults to regression from length
    temperature=10,  # irrelevant in this case
    SMR=0,  # irrelevant in this case
    max_thrust=250,
    NREI=0,  # irrelevant in this case
    use_total_cost=False,
    disable_wait_time=False)
opt, opt_model = optimize.optimal_maneuver(
    fish,
    detection_point_3D=(test_x, test_y, 0.0),
    max_iterations=(DEFAULT_OPT_ITERATIONS),
    max_n=(DEFAULT_OPT_N),
    tracked=True,
    return_optimization_model=True,
    suppress_output=False)
print(
    f"Had {opt_model.nfe_nonconvergent} nonconvergent evaluations out of {opt_model.nfe}"
)
def calculate_cost_tables(fork_length, velocity, taskid):
    fish = maneuveringfish.ManeuveringFish(fork_length=fork_length,
                                           mean_water_velocity=velocity,
                                           base_mass=0,  # defaults to regression from length
                                           temperature=10,  # irrelevant in this case
                                           SMR=0,  # irrelevant in this case
                                           max_thrust=250,
                                           NREI=0,  # irrelevant in this case
                                           use_total_cost=False,
                                           disable_wait_time=False)
    prey_length_mm_for_max_distance = 25  # mm, set the max distance considered to the max at which 25-mm prey could be resolved (asymptotically approaches 3 m for large fish)
    max_visible_distance = 12 * prey_length_mm_for_max_distance * (1. - np.exp(-0.2 * fork_length)) # max visible distance of prey in cm
    # the minimum lateral (y) distance we'll consider for maneuver is 0.2 cm, basically just a head-snap maneuver for the smallest drift foragers
    # We also insert a couple of manual values in there to get consistent coverage at short distances before the scaled values kick in for all fish.
    (xmin, xmax, ymin, ymax) = (-max_visible_distance, max_visible_distance, 0.2, max_visible_distance)
    sp = 4 # sp = spacing power used to emphasize points closer to the fish while still covering much more distant points adequately
    def scale(x):
        return (x)**sp
    def scale_inv(x):
        return abs(abs(x)**(1.0/sp))
    xs = np.concatenate([-abs(np.flip(scale(np.linspace(scale_inv(1), scale_inv(-xmin), 24))[1:], axis=0)), [-0.1], scale(np.linspace(scale_inv(1), scale_inv(xmax), 14)[1:])])
    ys = np.concatenate([[ymin, 0.7, 1.2, 1.8], scale(np.linspace(scale_inv(1), scale_inv(xmax), 25)[2:])])
    if FAST_TEST:
        xs = xs[::5]
        ys = ys[::5]
    # This grid has 999 values per sheet.
    # for x in xs: print("x = {0:.5f}".format(x)) # print statements that can be used to check grid spacing
    # for y in ys: print("y = {0:.5f}".format(y))
    ac = np.zeros(shape=(len(xs),len(ys)))
    pd = np.zeros(shape=(len(xs),len(ys)))
    rd = np.zeros(shape=(len(xs),len(ys)))
    count = 1
    final_count = float(len(xs) * len(ys))
    for i in range(len(xs)):
        for j in range(len(ys)):
            print("Calculating optimal maneuver for detection point ", xs[i], ", ", ys[j], ", 0")
            sol = optimize.optimal_maneuver(fish,
                                            detection_point_3D=(xs[i], ys[j], 0.0),
                                            max_iterations=(100 if FAST_TEST else DEFAULT_OPT_ITERATIONS),
                                            max_n=(30 if FAST_TEST else DEFAULT_OPT_N),
                                            suppress_output=True)
            if sol.activity_cost != CONVERGENCE_FAILURE_COST:
                ac[i,j] = sol.activity_cost
                pd[i,j] = sol.pursuit_duration
                rd[i,j] = sol.return_duration
            else:
                ac[i,j] = np.nan
                pd[i,j] = np.nan
                rd[i, j] = np.nan
            if IS_MAC:
                print(f"Solution {count} of {final_count:.0f}: For fl={fork_length:.1f} cm, v={velocity:.1f} cm/s, at x={xs[i]:.2f} and y={ys[j]:.2f}, energy cost is {sol.activity_cost:.5f} J and pursuit duration is {sol.pursuit_duration:.3f} and return duration is {sol.return_duration:.3f} s.")
            if count % 5 == 0 and not IS_MAC:
                db_execute("UPDATE maneuver_model_tasks SET progress={0} WHERE taskid={1}".format(count/final_count, taskid))
            count += 1 
    # Now, run quality control check on the ec and pd values, redoing calculation if they're too far off from their neighbors or came out np.nan the first time
    for table in [ac]: # base the check only on ac
        imax = table.shape[0]
        jmax = table.shape[1]
        for i in range(imax):
            for j in range(jmax):
                i_min = 0 if i == 0 else i-1
                i_max = imax+1 if i == imax else i+2
                j_min = 0 if j == 0 else j-1
                j_max = jmax+1 if j == jmax else j+2
                neighbors = table[i_min:i_max, j_min:j_max]
                notnan_neighbors = neighbors[~np.isnan(neighbors)]
                if len(notnan_neighbors) >= 3 or np.isnan(table[i,j]): # only do the neighbor-based QC check if there are enough "neighbors" (2 + current number) to check against the median
                    neighbor_median = np.median(notnan_neighbors) # median of 4 (corner), 6 (edge), or 9-value (center) block around present cell
                    ratio_to_median = table[i,j] / neighbor_median
                    worst_allowable_ratio = 3.0 # assume optimal solution wasn't found if solution differs from neighbors by factor of 3
                    if ratio_to_median < 1/worst_allowable_ratio or ratio_to_median > worst_allowable_ratio or np.isnan(table[i,j]):
                        for retry in (2,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4): # If we didn't get reasonable values the first time, try again with more rigorous but time-consuming algorithm parameters
                            if not IS_MAC: db_execute("UPDATE maneuver_model_tasks SET retries=retries+1 WHERE taskid={0}".format(taskid))
                            sol = optimize.optimal_maneuver(fish,
                                                            detection_point_3D=(xs[i], ys[j], 0.0),
                                                            max_iterations=(retry*DEFAULT_OPT_ITERATIONS),
                                                            max_n=(retry*DEFAULT_OPT_N),
                                                            suppress_output=True)
                            if sol.activity_cost < ac[i, j]:
                                ac[i,j] = sol.activity_cost
                                pd[i,j] = sol.pursuit_duration
                                rd[i,j] = sol.return_duration
                                ratio_to_median = table[i,j] / neighbor_median
                                if 1/worst_allowable_ratio <= ratio_to_median <= worst_allowable_ratio:
                                    break
                        if np.isnan(table[i,j]):
                            print(f"Retries still produced NaN activity cost for x={xs[i]}, y={ys[j]} with fl={fork_length}, velocity={velocity}.")
                        if ratio_to_median < 1/worst_allowable_ratio or ratio_to_median > worst_allowable_ratio:
                            print(f"Retries to match neighbors failed for x={xs[i]}, y={ys[j]} with fl={fork_length}, velocity={velocity}, ratio_to_median={ratio_to_median}.")
                            if not IS_MAC: db_execute(f"UPDATE maneuver_model_tasks SET has_failed_retries=1 WHERE taskid={taskid}")
    # Count up final number of NaNs if any, using the activity cost table
    nan_count = np.count_nonzero(np.isnan(ac))
    if nan_count > 0 and not IS_MAC:
        db_execute(f"UPDATE maneuver_model_tasks SET nan_count={nan_count} WHERE taskid={taskid}")
    # Now add on the mirror image of the first 4 columns to each extrapolation, with negative y values, to facilitate smooth interpolation near y=0
    ys = np.concatenate([np.flip(-ys[:4], axis=0), ys])
    ac = np.concatenate([np.flip(ac[:,:4], axis=1), ac], axis=1)
    pd = np.concatenate([np.flip(pd[:,:4], axis=1), pd], axis=1)
    rd = np.concatenate([np.flip(rd[:,:4], axis=1), rd], axis=1)
    return ac, pd, rd, xs, ys