diff --git a/cara/models.py b/cara/models.py index 80f993d5..6a7a1531 100644 --- a/cara/models.py +++ b/cara/models.py @@ -762,6 +762,7 @@ class ConcentrationModel: return (self.infected.emission_rate(time)) / (IVRR * V) + @method_cache def state_change_times(self) -> typing.List[float]: """ All time dependent entities on this model must provide information about @@ -777,11 +778,18 @@ class ConcentrationModel: """ Find the most recent/previous state change. + Find the nearest time less than the given one. If there is a state + change exactly at ``time`` the previous state change is returned + (except at ``time == 0``). + """ - for change_time in self.state_change_times()[::-1]: - if change_time < time: - return change_time - return 0. + times = self.state_change_times() + t_index = np.searchsorted(times, time) + # Search sorted gives us the index to insert the given time. Instead we + # want to get the index of the most recent time, so reduce the index by + # one unless we are already at 0. + t_index = max([t_index - 1, 0]) + return times[t_index] def _next_state_change(self, time: float) -> float: """ diff --git a/cara/tests/models/test_concentration_model.py b/cara/tests/models/test_concentration_model.py index 9470dd56..5e246533 100644 --- a/cara/tests/models/test_concentration_model.py +++ b/cara/tests/models/test_concentration_model.py @@ -70,6 +70,7 @@ def simple_conc_model(): @pytest.mark.parametrize( "time, expected_last_state_change", [ + [-15., 0.], # Out of range goes to the last state. [0., 0], [1., 0], [1.05, 1.], @@ -80,6 +81,7 @@ def simple_conc_model(): [2., 1.999], [2.1, 2], [3., 2], + [15., 3.], # Out of range goes to the last state. ] ) def test_last_state_change_time( @@ -90,10 +92,6 @@ def test_last_state_change_time( assert simple_conc_model.last_state_change(float(time)) == expected_last_state_change -def test_last_state_change_time_out_of_range(simple_conc_model: models.ConcentrationModel): - assert simple_conc_model.last_state_change(3.1) == 3.0 - - @pytest.mark.parametrize( "time, expected_next_state_change", [ [0, 0],