From 9558c9bdc09333f8100d21498246d838058c125d Mon Sep 17 00:00:00 2001 From: Aman Singh Date: Fri, 16 Oct 2026 17:24:06 +0530 Subject: [PATCH 1/3] fix (routeparams): correct count and array lengths in from_file from_file used count-1 instead of count-2 and left status/message unsliced, while fuel/power loops missed last segment. Fix round-trip and totals. Closes #219 --- WeatherRoutingTool/routeparams.py | 12 +++++++----- tests/test_routeparams.py | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/WeatherRoutingTool/routeparams.py b/WeatherRoutingTool/routeparams.py index 6c85ffb9..add24de4 100644 --- a/WeatherRoutingTool/routeparams.py +++ b/WeatherRoutingTool/routeparams.py @@ -343,6 +343,8 @@ def from_file(cls, filename): air_temperature = air_temperature[:-1] * u.deg_C salinity = salinity[:-1] * u.dimensionless_unscaled water_temperature = water_temperature[:-1] * u.deg_C + status = status[:-1] + message = message[:-1] start = (lats_per_step[0], lons_per_step[0]) finish = (lats_per_step[count - 1], lons_per_step[count - 1]) @@ -352,7 +354,7 @@ def from_file(cls, filename): dists_per_step = cls.get_dist_from_coords(cls, lats_per_step, lons_per_step) dists_per_step = dists_per_step[:-1] - count = count - 1 + count = count - 2 ship_params_per_step = ShipParams( fuel_rate=fuel_rate, @@ -741,10 +743,10 @@ def get_fuel_per_dist(self): :rtype: astropy.units.Quantity """ fuel_per_second = self.ship_params_per_step.fuel_rate - delta_time = np.full(self.count, timedelta(seconds=0)) + delta_time = np.full(self.count + 1, timedelta(seconds=0)) fuel = np.array([]) * u.kg - for i in range(0, self.count): + for i in range(0, self.count + 1): delta_time[i] = self.starttime_per_step[i + 1] - self.starttime_per_step[i] delta_time[i] = delta_time[i].total_seconds() * u.second fuel = np.append(fuel, fuel_per_second[i] * delta_time[i]) @@ -842,7 +844,7 @@ def get_full_fuel(self): :rtype: astropy.units.Quantity """ full_fuel = 0 * u.kg - for ipoint in range(0, self.count): + for ipoint in range(0, self.count + 1): time_passed = (self.starttime_per_step[ipoint + 1] - self.starttime_per_step[ipoint]).total_seconds() fuel_per_step = self.ship_params_per_step.fuel_rate[ipoint] * time_passed * u.second full_fuel = full_fuel + fuel_per_step @@ -858,7 +860,7 @@ def get_mean_power(self): """ power_sum = 0 count = 0 - for ipoint in range(0, self.count): + for ipoint in range(0, self.count + 1): power_per_step = self.ship_params_per_step.power[ipoint] power_sum = power_sum + power_per_step count += 1 diff --git a/tests/test_routeparams.py b/tests/test_routeparams.py index 427f8c97..b69687d9 100644 --- a/tests/test_routeparams.py +++ b/tests/test_routeparams.py @@ -76,6 +76,13 @@ def test_get_acc_variables(): assert np.allclose(test_dist, rp_test.get_full_dist()) assert test_time == rp_test.get_full_travel_time() + # regression for Issue #219: round-trip must preserve count and array lengths + assert rp_test.count == 2 + assert len(rp_test.lats_per_step) == 4 + assert len(rp_test.ship_params_per_step.speed) == 3 + assert len(rp_test.ship_params_per_step.status) == 3 + assert len(rp_test.dists_per_step) == 3 + ''' Test whether parameters in `RouteParams.get_per_waypoint_coords` are calculated correctly. From ffe1db87f57b251c7150573102f1d3b82742eb43 Mon Sep 17 00:00:00 2001 From: Aman Singh Date: Mon, 2 Nov 2026 15:55:24 +0530 Subject: [PATCH 2/3] fix (routeparams): add fuel loop fixes and graphics test invariant --- tests/test_graphics.py | 11 ++++++----- tests/test_routeparams.py | 9 +++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/test_graphics.py b/tests/test_graphics.py index 53764e95..38192355 100644 --- a/tests/test_graphics.py +++ b/tests/test_graphics.py @@ -12,15 +12,16 @@ def test_plot_power_vs_dist(): count = 3 dummy_scalar = 0 - dummy_list = np.full(3, -99) - dummy_list_coords = np.full(4, -99) - fuel_consumed = np.array([1, 2, 1]) * u.kg/u.second - dist_per_step = np.array([1, 4, 5]) + dummy_list = np.full(4, -99) + dummy_list_coords = np.full(5, -99) + fuel_consumed = np.array([1, 2, 1, 1]) * u.kg / u.second + dist_per_step = np.array([1, 4, 5, 1]) time_per_step = np.array( [datetime.datetime(2022, 12, 19), datetime.datetime(2022, 12, 19) + datetime.timedelta(days=180), datetime.datetime(2022, 12, 19) + datetime.timedelta(days=360), - datetime.datetime(2022, 12, 19) + datetime.timedelta(days=400)]) + datetime.datetime(2022, 12, 19) + datetime.timedelta(days=400), + datetime.datetime(2022, 12, 19) + datetime.timedelta(days=450)]) sp = ShipParams(fuel_consumed, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, dummy_list, diff --git a/tests/test_routeparams.py b/tests/test_routeparams.py index b69687d9..0a5c8ad0 100644 --- a/tests/test_routeparams.py +++ b/tests/test_routeparams.py @@ -84,6 +84,15 @@ def test_get_acc_variables(): assert len(rp_test.dists_per_step) == 3 +def test_routeparams_eq(): + # regression for Issue #221: __eq__ must not raise AttributeError + dirname = os.path.dirname(__file__) + filename = os.path.join(dirname, 'data/min_fuel_route_test.json') + rp1 = RouteParams.from_file(filename) + rp2 = RouteParams.from_file(filename) + assert rp1 == rp2 + + ''' Test whether parameters in `RouteParams.get_per_waypoint_coords` are calculated correctly. ''' From a435b0c68e4b38fc59496b9db14cb26625226d00 Mon Sep 17 00:00:00 2001 From: Aman Singh Date: Mon, 2 Nov 2026 15:57:29 +0530 Subject: [PATCH 3/3] fix (routeparams): fix __eq__ to use ship params --- WeatherRoutingTool/routeparams.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/WeatherRoutingTool/routeparams.py b/WeatherRoutingTool/routeparams.py index add24de4..eb2355b8 100644 --- a/WeatherRoutingTool/routeparams.py +++ b/WeatherRoutingTool/routeparams.py @@ -123,9 +123,10 @@ def __eq__(self, route2): raise ValueError('Route finsh not matching') if not (np.array_equal(self.time, route2.time)): raise ValueError('Route time not matching: self=' + str(self.time) + ' other=' + str(route2.time)) - if not (np.array_equal(self.fuel, route2.fuel)): - raise ValueError('Route fuel not matching: self=' + str(self.fuel) + ' other=' + str(route2.fuel)) - if not (np.array_equal(self.rpm, route2.rpm)): + if not (np.array_equal(self.ship_params_per_step.fuel_rate, route2.ship_params_per_step.fuel_rate)): + raise ValueError('Route fuel not matching: self=' + str(self.ship_params_per_step.fuel_rate) + + ' other=' + str(route2.ship_params_per_step.fuel_rate)) + if not (np.array_equal(self.ship_params_per_step.rpm, route2.ship_params_per_step.rpm)): raise ValueError('Route rpm not matching') if not (np.array_equal(self.lats_per_step, route2.lats_per_step)): raise ValueError('Route lats_per_step not matching')