def test_get_class_parts_limits_sorted(): classes = datamodel.get_wltc_data()["classes"] class_limits = { cls: datamodel.get_class_parts_limits(cls, edges=True) for cls in classes.keys() } for (cls, l) in class_limits.items(): assert l == tuple(sorted(l)), f"Class({cls}): Unsorted!"
def test_smoke2(): wclasses = datamodel.get_wltc_data()["classes"] test_data = [(pd.Series(wclass["V_cycle"]), wclass["downscale"]["phases"], f_dsc) for wclass in wclasses.values() for f_dsc in np.linspace(0.1, 1, 10)] for (V, phases, f_dsc) in test_data: downscale.calc_V_dsc_raw(V, f_dsc, phases)
def test_get_class_parts_limits_sorted(self): classes = datamodel.get_wltc_data()["classes"] class_limits = { cls: datamodel.get_class_parts_limits(cls, edges=True) for cls in classes.keys() } for (cls, l) in class_limits.items(): self.assertSequenceEqual(l, sorted(l), "Class(%s): Unsorted!" % cls)
def test_get_class_phase_boundaries(): wcd = datamodel.get_wltc_data() cd = cycles.get_wltc_class_data(wcd["classes"], 3) pmr_boundaries = cycles.get_class_phase_boundaries(cd["lengths"], cd["V_cycle"]) assert len(pmr_boundaries) == 4 assert pmr_boundaries[0][0] == 0 assert pmr_boundaries[-1][-1] == 1800 nums = tuple(itt.chain(*pmr_boundaries)) assert tuple(sorted(nums)) == nums
def test_smoke2(): wclasses = datamodel.get_wltc_data()["classes"] test_data = [ (pd.Series(wclass["v_cycle"]), wclass["downscale"]["phases"], f_downscale) for wclass in wclasses.values() for f_downscale in np.linspace(0.1, 1, 10) ] for (V, phases, f_downscale) in test_data: downscale_class_velocity(V, f_downscale, phases)
def test_get_class_parts_limits_with_edges(): classes = datamodel.get_wltc_data()["classes"] class_limits = { cls: datamodel.get_class_parts_limits(cls, edges=True) for cls in classes.keys() } for (cls, l) in class_limits.items(): assert l[0] == 0, f"Class({cls}): Left-edge not 0!" for (cls, l) in class_limits.items(): assert (l[-1] == len(classes[cls]["V_cycle"]) - 1), f"Class({cls}): Section Right-edge not len(cycle)!"
def test_wltc_validate_class_parts(self): wltc = datamodel.get_wltc_data() for cl, cd in wltc["classes"].items(): cycle = cd["v_cycle"] parts = datamodel.get_class_parts_limits(cl, edges=True) prev_start = -1 for start in parts: assert 0 <= start <= len(cycle) assert prev_start < start prev_start = start assert prev_start == len(cycle)
def test_get_class_parts_limits_with_edges(self): classes = datamodel.get_wltc_data()["classes"] class_limits = { cls: datamodel.get_class_parts_limits(cls, edges=True) for cls in classes.keys() } for (cls, l) in class_limits.items(): self.assertEqual(l[0], 0, "Class(%s): Left-edge not 0!" % cls) for (cls, l) in class_limits.items(): self.assertEqual( l[-1], len(classes[cls]["v_cycle"]), "Class(%s): Section Right-edge not len(cycle)!" % cls, )
def test_v_distances_pipeline(wltc_class): aug = wio.make_autograph() ops = aug.wrap_funcs([ *pipelines.v_distances_pipeline().ops, # fake dsc & cap operation(None, "FAKE.V_dsc", "wltc_class_data/V_cycle", "V_dsc"), operation(None, "FAKE.V_cap", "wltc_class_data/V_cycle", "V_capped"), ]) pipe = compose(..., *ops) inp = {"wltc_data": datamodel.get_wltc_data(), "wltc_class": wltc_class} sol = pipe.compute(inp) got = sol["wltc_distances"] print(got) exp_sums = { 0: """ sum cumsum [0, 589) 11988.4 11988.4 [589, 1022) 17162.8 29151.2 [1022, 1611) 11988.4 41139.6 """, 1: """ sum cumsum [0, 589) 11162.2 11162.2 [589, 1022) 17054.3 28216.5 [1022, 1477) 24450.6 52667.1 [1477, 1800) 28869.8 81536.9 """, 2: """ sum cumsum [0, 589) 11140.3 11140.3 [589, 1022) 16995.7 28136.0 [1022, 1477) 25646.0 53782.0 [1477, 1800) 29714.9 83496.9 """, 3: """ sum cumsum [0, 589) 11140.3 11140.3 [589, 1022) 17121.2 28261.5 [1022, 1477) 25782.2 54043.7 [1477, 1800) 29714.9 83758.6 """, } assert oneliner(got) == oneliner(exp_sums[wltc_class])
def test_smoke1(): test_mass = 1577.3106 p_rated = 78.6340 v_max = 186.4861 f0 = 152.5813 f1 = 307.5789 f2 = 0.0486 f_inertial = 1.03 # TODO: get it from schema-default ## Decide WLTC-class. # wltc = datamodel.get_wltc_data() wltc_class = vehicle.decide_wltc_class(wltc["classes"], p_rated / test_mass, v_max) class_data = wltc["classes"][wltc_class] V = pd.Series(class_data["V_cycle"]) f_dsc_threshold = 0.01 # TODO: get it from schema-default f_dsc_decimals = 3 # TODO: get it from schema-default dsc_data = class_data["downscale"] phases = dsc_data["phases"] p_max_values = dsc_data["p_max_values"] downsc_coeffs = dsc_data["factor_coeffs"] f_dsc_raw = downscale.calc_f_dsc_raw( p_max_values, downsc_coeffs, p_rated, test_mass, f0, f1, f2, f_inertial, ) f_dsc = downscale.calc_f_dsc( f_dsc_raw, f_dsc_threshold, f_dsc_decimals, ) if f_dsc > 0: V = downscale.calc_V_dsc_raw(V, f_dsc, phases)
def test_smoke1(): logging.getLogger().setLevel(logging.DEBUG) test_mass = 1577.3106 p_rated = 78.6340 v_max = 186.4861 f0 = 152.5813 f1 = 307.5789 f2 = 0.0486 f_inertial = 1.03 # TODO: get it from schema-default ## Decide WLTC-class. # wltc = datamodel.get_wltc_data() wltc_class = decide_wltc_class(wltc, p_rated / test_mass, v_max) class_data = wltc["classes"][wltc_class] V = pd.Series(class_data["v_cycle"]) f_downscale_threshold = 0.01 # TODO: get it from schema-default f_downscale_decimals = 3 # TODO: get it from schema-default dsc_data = class_data["downscale"] phases = dsc_data["phases"] p_max_values = dsc_data["p_max_values"] downsc_coeffs = dsc_data["factor_coeffs"] f_downscale, _orig_f = calc_downscale_factor( p_max_values, downsc_coeffs, p_rated, f_downscale_threshold, f_downscale_decimals, test_mass, f0, f1, f2, f_inertial, ) if f_downscale > 0: V = downscale_class_velocity(V, f_downscale, phases)
ax1.xaxis.grid = True ax1.yaxis.grid = True xlim = [0, 1800] # kmh ax1.set_xlim(xlim) ylim = [0, 140] # kmh ax1.set_ylim(ylim) ax2.set_ylim(ylim) fig.set_size_inches(2 * 2 * 1.618, 2) fig.tight_layout(pad=0) return fig if __name__ == "__main__": os.chdir(path.dirname(__file__)) wltc_data = datamodel.get_wltc_data() for (class_name, class_data) in wltc_data["classes"].items(): fig = make_class_fig(class_name, class_data) img_fname = path.join("..", "docs", "_static", "wltc_%s.png" % class_name) nargs = len(sys.argv) if nargs > 1: plt.show() if nargs == 1 or nargs > 2: fig.savefig(img_fname, dpi=100) print("Stored image: %s" % img_fname)
def test_dsc_pipelines(wltc_class): aug = wio.make_autograph() ops = aug.wrap_funcs([ *pipelines.downscale_pipeline().ops, *pipelines.compensate_capped_pipeline().ops, *pipelines.v_distances_pipeline().ops, # fake dsc & cap operation(None, "FAKE.V_dsc", "wltc_class_data/V_cycle", "V_dsc"), ]) pipe = compose(..., *ops) inp = { "wltc_data": datamodel.get_wltc_data(), "wltc_class": wltc_class, "v_cap": 60, # class1 max(V) is 60.4 } sol = pipe.compute(inp) assert len(sol["compensate_phases_t_extra"]) == len( sol["class_phase_boundaries"]) exp_t_missing = ([0, 1, 0], [0, 10, 43, 192], [0, 8, 81, 203], [0, 8, 81, 203]) assert sol["compensate_phases_t_extra"].tolist( ) == exp_t_missing[wltc_class] exp_compensated_phases = [ [(0, 589), (590, 1023), (1023, 1612)], [(0, 589), (599, 1032), (1075, 1530), (1722, 2045)], [(0, 589), (597, 1030), (1111, 1566), (1769, 2092)], [(0, 589), (597, 1030), (1111, 1566), (1769, 2092)], ] compensated_phases = sol["compensated_phase_boundaries"] assert compensated_phases == exp_compensated_phases[wltc_class] V_compensated = sol["V_compensated"] assert compensated_phases[-1][-1] == V_compensated.index[-1] assert (sol["V_dsc"].sum() - V_compensated.sum()) < inp["v_cap"] exp_compensated_distances = [ [11988.4, 29146.9, 41135.3], [11162.2, 28209.7, 51666.1, 70103.2], [11140.3, 28110.5, 50564.1, 69069.5], [11140.3, 28241.0, 50779.8, 69285.2], ] compensated_distances = sol["compensated_distances"] assert (inv.vround(compensated_distances["cumsum"]) == exp_compensated_distances[wltc_class]).all() ## No CAPPING inp = { "wltc_data": datamodel.get_wltc_data(), "wltc_class": wltc_class, "v_cap": 0, } sol = pipe.compute(inp) assert len(sol["compensate_phases_t_extra"]) == len( sol["class_phase_boundaries"]) regular_phases = sol["class_phase_boundaries"] V_compensated = sol["V_compensated"] assert regular_phases[-1][-1] == V_compensated.index[-1] assert sol["V_dsc"].sum() == sol["V_compensated"].sum()
def test_cycler_pipeline(): # wltc_class): wltc_class = 0 aug = wio.make_autograph() ops = aug.wrap_funcs([ *pipelines.cycler_pipeline().ops, # fake Vs operation( lambda v: v.rename("V_dsc"), "FAKE.V_dsc", "wltc_class_data/V_cycle", "V_dsc", ), ]) pipe = compose(..., *ops) props = goodvehicle.goodVehicle() inp = { **props, "wltc_data": datamodel.get_wltc_data(), "wltc_class": wltc_class, "v_max": 190.3, "g_vmax": 6, # "n_min_drives": nmindrive.mdl_2_n_min_drives.compute(props) } datamodel.validate_model(inp, additional_properties=True) with config.evictions_skipped(True): sol = pipe.compute(inp, callbacks=(pipelines.check_dupe_cols)) cycle = sol["cycle"] assert len(cycle) == 1612 # assert len(cycle.columns) == 105 renames = { "OK_max_n": "ok_max_n", "OK_g0": "ok_gear0", "OK_p": "ok_p", "OK_n": "ok_n", "OK_gear": "ok_gear", "G_min": "g_min", "G_max0": "g_max0", } exp = [ ("t", ""), ("V_cycle", ""), ("V_dsc", ""), ("V", ""), ("A", ""), ("va_phase", ""), ("phase_1", ""), ("phase_2", ""), ("phase_3", ""), ("accel_raw", ""), ("run", ""), ("stop", ""), ("decel", ""), ("initaccel", ""), ("stopdecel", ""), ("up", ""), ("P_resist", ""), ("P_inert", ""), ("P_req", ""), ("n", "g1"), ("n", "g2"), ("n", "g3"), ("n", "g4"), ("n", "g5"), ("n", "g6"), ("n_norm", "g1"), ("n_norm", "g2"), ("n_norm", "g3"), ("n_norm", "g4"), ("n_norm", "g5"), ("n_norm", "g6"), ("p", "g1"), ("p", "g2"), ("p", "g3"), ("p", "g4"), ("p", "g5"), ("p", "g6"), ("p_avail", "g1"), ("p_avail", "g2"), ("p_avail", "g3"), ("p_avail", "g4"), ("p_avail", "g5"), ("p_avail", "g6"), ("p_avail_stable", "g1"), ("p_avail_stable", "g2"), ("p_avail_stable", "g3"), ("p_avail_stable", "g4"), ("p_avail_stable", "g5"), ("p_avail_stable", "g6"), ("p_norm", "g1"), ("p_norm", "g2"), ("p_norm", "g3"), ("p_norm", "g4"), ("p_norm", "g5"), ("p_norm", "g6"), ("P_remain", "g1"), ("P_remain", "g2"), ("P_remain", "g3"), ("P_remain", "g4"), ("P_remain", "g5"), ("P_remain", "g6"), ("ok_p", "g3"), ("ok_p", "g4"), ("ok_p", "g5"), ("ok_p", "g6"), ("ok_max_n", "g1"), ("ok_max_n", "g2"), ("ok_max_n", "g3"), ("ok_max_n", "g4"), ("ok_max_n", "g5"), ("ok_max_n", "g6"), ("ok_gear0", "g0"), ("ok_min_n_g1", "g1"), ("ok_min_n_g1_initaccel", "g1"), ("ok_min_n_g2", "g2"), ("ok_min_n_g2_stopdecel", "g2"), ("ok_min_n_g3plus_dns", "g3"), ("ok_min_n_g3plus_dns", "g4"), ("ok_min_n_g3plus_dns", "g5"), ("ok_min_n_g3plus_dns", "g6"), ("ok_min_n_g3plus_ups", "g3"), ("ok_min_n_g3plus_ups", "g4"), ("ok_min_n_g3plus_ups", "g5"), ("ok_min_n_g3plus_ups", "g6"), ("ok_n", "g1"), ("ok_n", "g2"), ("ok_n", "g3"), ("ok_n", "g4"), ("ok_n", "g5"), ("ok_n", "g6"), ("incrementing_gflags", "g0"), ("incrementing_gflags", "g1"), ("incrementing_gflags", "g2"), ("incrementing_gflags", "g3"), ("incrementing_gflags", "g4"), ("incrementing_gflags", "g5"), ("incrementing_gflags", "g6"), ("ok_gear", "g0"), ("ok_gear", "g1"), ("ok_gear", "g2"), ("ok_gear", "g3"), ("ok_gear", "g4"), ("ok_gear", "g5"), ("ok_gear", "g6"), ("g_min", ""), ("g_max0", ""), ] print(cycle.columns) # assert set(cycle.columns) == set(exp) assert set(cycle.rename(columns=renames, level=0)) == set(exp) assert not ({ "class_phase_boundaries", "n2v_g_vmax", "n95_low", "n95_high", "n_max_cycle", "n_max_vehicle", "n_max", } - sol.keys()) steps = [getattr(n, "name", n) for n in sol.plan.steps] steps_executed = [getattr(n, "name", n) for n in sol.executed] print("\n".join(textwrap.wrap(" ".join(steps), 90))) # print("\n".join(textwrap.wrap(" ".join(steps_executed), 90))) exp_steps = """ get_wltc_class_data get_class_phase_boundaries PhaseMarker interpolate_wot_on_v_grid attach_p_avail_in_gwots calc_n2v_g_vmax calc_n95 calc_n_max_vehicle make_gwots_multi_indexer FAKE.V_dsc init_cycle_velocity calc_acceleration attach_class_phase_markers calc_phase_accel_raw calc_phase_run_stop calc_phase_decel calc_phase_initaccel calc_phase_stopdecel calc_phase_up calc_p_resist calc_inertial_power calc_required_power calc_n_max_cycle calc_n_max validate_n_max join_gwots_with_cycle calc_P_remain calc_OK_p calc_OK_max_n calc_OK_g0 calc_OK_min_n derrive_ok_n_flags calc_ok_gears make_cycle_multi_indexer make_incrementing_gflags make_G_min make_G_max0 """.split() assert steps == steps_executed == exp_steps
def test_cycler_pipeline(): # wltc_class): wltc_class = 0 aug = wio.make_autograph() ops = aug.wrap_funcs([ *pipelines.cycler_pipeline().ops, # fake Vs operation(None, "FAKE.V_dsc", "wltc_class_data/V_cycle", "V_dsc"), ]) pipe = compose(..., *ops) inp = { **goodvehicle.goodVehicle(), "wltc_data": datamodel.get_wltc_data(), "wltc_class": wltc_class, "v_max": 190.3, "g_vmax": 6, } datamodel.validate_model(inp) with config.evictions_skipped(True): sol = pipe.compute(inp) exp = { "V_cycle", "V_cycle", "V", "A", "v_phase1", "v_phase2", "v_phase3", "va_phases", "P_resist", "P_inert", "P_req", "t", ("n", "g1"), ("n", "g2"), ("n", "g3"), ("n", "g4"), ("n", "g5"), ("n", "g6"), ("n_norm", "g1"), ("n_norm", "g2"), ("n_norm", "g3"), ("n_norm", "g4"), ("n_norm", "g5"), ("n_norm", "g6"), ("p", "g1"), ("p", "g2"), ("p", "g3"), ("p", "g4"), ("p", "g5"), ("p", "g6"), ("p_avail", "g1"), ("p_avail", "g2"), ("p_avail", "g3"), ("p_avail", "g4"), ("p_avail", "g5"), ("p_avail", "g6"), ("p_avail_stable", "g1"), ("p_avail_stable", "g2"), ("p_avail_stable", "g3"), ("p_avail_stable", "g4"), ("p_avail_stable", "g5"), ("p_avail_stable", "g6"), ("p_norm", "g1"), ("p_norm", "g2"), ("p_norm", "g3"), ("p_norm", "g4"), ("p_norm", "g5"), ("p_norm", "g6"), ("p_resist", ""), } assert set(sol["cycle"].columns) == exp assert not ({ "class_phase_boundaries", "n2v_g_vmax", "n_95_low", "n_95_high", "n_max_cycle", "n_max_vehicle", "n_max", } - sol.keys()) steps = [getattr(n, "name", n) for n in sol.plan.steps] steps_executed = [getattr(n, "name", n) for n in sol.executed] print(steps, steps_executed) exp_steps = """ get_wltc_class_data get_forced_cycle get_class_phase_boundaries interpolate_wot_on_v_grid attach_p_avail_in_gwots attach_p_resist_in_gwots calc_n2v_g_vmax calc_n_95 calc_n_max_vehicle make_gwots_multi_indexer FAKE.V_dsc init_cycle_velocity calc_acceleration attach_class_v_phase_markers calc_class_va_phase_markers calc_p_resist calc_inertial_power calc_required_power calc_n_max_cycle calc_n_max attach_wots """.split() assert steps == steps_executed == exp_steps