Skip to content

Commit

Permalink
Added fix for cached values affecting partial trajectories and added …
Browse files Browse the repository at this point in the history
…test
  • Loading branch information
modelonrobinandersson committed Nov 5, 2024
1 parent cc10bc6 commit 12121b8
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
15 changes: 14 additions & 1 deletion src/common/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -1208,6 +1208,7 @@ def __init__(self, fname, delayed_trajectory_loading = True, allow_file_updates=
self._is_stream = True
delayed_trajectory_loading = False
self._allow_file_updates = allow_file_updates
self._last_set_of_indices = (None, None) # used for dealing with cached data and partial trajectories

data_sections = ["name", "dataInfo", "data_2", "data_3", "data_4"]
if not self._is_stream:
Expand Down Expand Up @@ -1331,11 +1332,18 @@ def _get_name_dict(self):

return name_dict

def _can_use_partial_cache(self, start_index, stop_index):
""" Checks if start_index and stop_oindex are equal to the last cached indices. """
return self._allow_file_updates and (self._last_set_of_indices == (start_index, stop_index))

def _get_trajectory(self, data_index, start_index = 0, stop_index = None):
if isinstance(self._data_2, dict):
self._verify_file_data()

if data_index in self._data_2:
index_in_cache = data_index in self._data_2
partial_cache_ok = self._can_use_partial_cache(start_index, stop_index)
if (index_in_cache and not self._allow_file_updates) or (index_in_cache and partial_cache_ok):
print(f"Doing an early return")
return self._data_2[data_index]

file_position = self._data_2_info["file_position"]
Expand All @@ -1344,10 +1352,12 @@ def _get_trajectory(self, data_index, start_index = 0, stop_index = None):
nbr_variables = self._data_2_info["nbr_variables"]

# Account for sub-sets of data
print(f"{start_index=}, {stop_index=}")
start_index = max(0, start_index)
stop_index = max(0, nbr_points if stop_index is None else min(nbr_points, stop_index))
new_file_position = file_position + start_index*sizeof_type*nbr_variables
new_nbr_points = stop_index - start_index
print(f"{start_index=}, {stop_index=}, {new_nbr_points=}")

self._data_2[data_index] = fmi_util.read_trajectory(
encode(self._fname),
Expand Down Expand Up @@ -1589,6 +1599,8 @@ def get_variables_data(self,
if isinstance(start_index, int) and isinstance(stop_index, int) and stop_index < start_index:
raise ValueError(f"Invalid values for {start_index=} and {stop_index=}, " + \
"'start_index' needs to be less than or equal to 'stop_index'.")


trajectories = {}

# Get the corresponding time trajectory
Expand All @@ -1606,6 +1618,7 @@ def get_variables_data(self,
trajectories[name] = self._get_variable_data_as_trajectory(name, time, start_index, stop_index)

new_start_index = start_index + len(time) if len(trajectories) > 0 else None
self._last_set_of_indices = (start_index, stop_index) # update them before we exit
return trajectories, new_start_index

def _calculate_events_and_steps(self, name):
Expand Down
29 changes: 29 additions & 0 deletions tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -1849,6 +1849,7 @@ def test_get_variables_data_values2(self):
for index, test_data in test_data_sets.items():
np.testing.assert_array_almost_equal(test_data['J4.phi'].x, reference_data[index])

@testattr(stddist = True)
def test_get_variables_data_values3(self):
""" Verifing values from get_variables_data, and only asking for diagnostic variables. """
vars_to_test = ['@Diagnostics.step_time', '@Diagnostics.nbr_steps']
Expand All @@ -1875,6 +1876,7 @@ def test_get_variables_data_values3(self):
np.testing.assert_array_almost_equal(test_data['@Diagnostics.step_time'].x, reference_data['@Diagnostics.step_time'][index])
np.testing.assert_array_almost_equal(test_data['@Diagnostics.nbr_steps'].x, reference_data['@Diagnostics.nbr_steps'][index])

@testattr(stddist = True)
def test_get_variables_data_values4(self):
""" Verifing values from get_variables_data, partial trajectories and checking both time and diagnostic data."""
vars_to_test = ['time', '@Diagnostics.nbr_steps']
Expand All @@ -1901,6 +1903,33 @@ def test_get_variables_data_values4(self):
np.testing.assert_array_almost_equal(test_data['time'].x, reference_data['time'][index])
np.testing.assert_array_almost_equal(test_data['@Diagnostics.nbr_steps'].x, reference_data['@Diagnostics.nbr_steps'][index])

@testattr(stddist = True)
def test_stop_index_near_bounds(self):
""" Verify that we get expected results near the end of the result file, including
stop_index out of range.
"""
fmu = Dummy_FMUModelME2([], os.path.join(file_path, "files", "FMUs", "XML", "ME2.0", "bouncingBall.fmu"), _connect_dll=False)
res = fmu.simulate()
assert len(res['h']) == 501

rdb = ResultDymolaBinary(fmu.get_last_result_file(), allow_file_updates = True)
np.testing.assert_array_almost_equal(
(rdb.get_variables_data(['h'], 495, 496)[0]['h'].x),
np.array([0.37268813]))
np.testing.assert_array_almost_equal(
(rdb.get_variables_data(['h'], 495, 500)[0]['h'].x),
np.array([0.37268813, 0.37194424, 0.37120184, 0.37046092, 0.36972148]))

np.testing.assert_array_almost_equal(
(rdb.get_variables_data(['h'], 495, 499)[0]['h'].x),
np.array([0.37268813, 0.37194424, 0.37120184, 0.37046092]))
np.testing.assert_array_almost_equal(
(rdb.get_variables_data(['h'], 495, 501)[0]['h'].x),
np.array([0.37268813, 0.37194424, 0.37120184, 0.37046092, 0.36972148, 0.36898351]))
np.testing.assert_array_almost_equal(
(rdb.get_variables_data(['h'], 495, 502)[0]['h'].x),
np.array([0.37268813, 0.37194424, 0.37120184, 0.37046092, 0.36972148, 0.36898351]))

if assimulo_installed:
class TestFileSizeLimit:

Expand Down

0 comments on commit 12121b8

Please sign in to comment.