diff --git a/documentation/changelog.rst b/documentation/changelog.rst index 570c80ba8..253d2e99f 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -25,6 +25,7 @@ Infrastructure / Support * The setting FLEXMEASURES_PLUGINS can be set as environment variable now (as a comma-separated list) [see `PR #660 `_] * Packaging was modernized to stop calling setup.py directly [see `PR #671 `_] * Remove API versions 1.0, 1.1, 1.2, 1.3 and 2.0, while making sure that sunset endpoints keep returning ``HTTP status 410 (Gone)`` responses [see `PR #667 `_ and `PR #717 `_] +* Support Pandas 2 [see `PR #673 `_] * Add code documentation from package structure and docstrings to official docs [see `PR #698 `_] .. warning:: The setting `FLEXMEASURES_PLUGIN_PATHS` has been deprecated since v0.7. It has now been sunset. Please replace it with :ref:`plugin-config`. diff --git a/documentation/plugin/customisation.rst b/documentation/plugin/customisation.rst index 835122309..8230e47ee 100644 --- a/documentation/plugin/customisation.rst +++ b/documentation/plugin/customisation.rst @@ -42,7 +42,7 @@ The following minimal example gives you an idea of some meta information you can """ return pd.Series( self.sensor.get_attribute("capacity_in_mw"), - index=pd.date_range(self.start, self.end, freq=self.resolution, closed="left"), + index=pd.date_range(self.start, self.end, freq=self.resolution, inclusive="left"), ) def deserialize_config(self): diff --git a/flexmeasures/data/models/planning/linear_optimization.py b/flexmeasures/data/models/planning/linear_optimization.py index 48247ac79..f0d79f866 100644 --- a/flexmeasures/data/models/planning/linear_optimization.py +++ b/flexmeasures/data/models/planning/linear_optimization.py @@ -74,7 +74,8 @@ def device_scheduler( # noqa C901 # Check if commitments have the same time window and resolution as the constraints start = device_constraints[0].index.to_pydatetime()[0] - resolution = pd.to_timedelta(device_constraints[0].index.freq) + # Workaround for https://github.com/pandas-dev/pandas/issues/53643. Was: resolution = pd.to_timedelta(device_constraints[0].index.freq) + resolution = pd.to_timedelta(device_constraints[0].index.freq).to_pytimedelta() end = device_constraints[0].index.to_pydatetime()[-1] + resolution if len(commitment_quantities) != 0: start_c = commitment_quantities[0].index.to_pydatetime()[0] diff --git a/flexmeasures/data/models/planning/tests/test_solver.py b/flexmeasures/data/models/planning/tests/test_solver.py index 904aafd97..48f00f771 100644 --- a/flexmeasures/data/models/planning/tests/test_solver.py +++ b/flexmeasures/data/models/planning/tests/test_solver.py @@ -566,15 +566,15 @@ def compute_schedule(flex_model): # test for soc_minima # check that the local minimum constraint is respected - assert soc_schedule2.loc[datetime(2015, 1, 2, 7)] >= 3.5 + assert soc_schedule2.loc["2015-01-02T08:00:00+01:00"] >= 3.5 # test for soc_maxima # check that the local maximum constraint is respected - assert soc_schedule2.loc[datetime(2015, 1, 2, 14)] <= 1.0 + assert soc_schedule2.loc["2015-01-02T15:00:00+01:00"] <= 1.0 # test for soc_targets # check that the SOC target (at 19 pm, local time) is met - assert soc_schedule2.loc[datetime(2015, 1, 2, 18)] == 2.0 + assert soc_schedule2.loc["2015-01-02T19:00:00+01:00"] == 2.0 @pytest.mark.parametrize( diff --git a/flexmeasures/data/models/reporting/pandas_reporter.py b/flexmeasures/data/models/reporting/pandas_reporter.py index 4169cfd69..1e1e98179 100644 --- a/flexmeasures/data/models/reporting/pandas_reporter.py +++ b/flexmeasures/data/models/reporting/pandas_reporter.py @@ -10,7 +10,6 @@ from flexmeasures.data.schemas.reporting.pandas_reporter import ( PandasReporterConfigSchema, ) -from flexmeasures.data.models.time_series import TimedBelief from flexmeasures.utils.time_utils import server_now @@ -43,6 +42,9 @@ def _compute( defined in `final_df_output` field of the report_config. """ + if belief_time is None: + belief_time = server_now() + # apply pandas transformations to the dataframes in `self.data` self._apply_transformations() @@ -51,9 +53,9 @@ def _compute( if isinstance(final_output, tb.BeliefsDataFrame): # filing the missing indexes with default values: - # belief_time=server_now(), cummulative_probability=0.5, source=data_source + # belief_time=belief_time, cummulative_probability=0.5, source=data_source if "belief_time" not in final_output.index.names: - final_output["belief_time"] = [server_now()] * len(final_output) + final_output["belief_time"] = [belief_time] * len(final_output) final_output = final_output.set_index("belief_time", append=True) if "cumulative_probability" not in final_output.index.names: @@ -71,18 +73,13 @@ def _compute( ) elif isinstance(final_output, tb.BeliefsSeries): - - timed_beliefs = [ - TimedBelief( - sensor=final_output.sensor, - source=self.data_source, - belief_time=server_now(), - event_start=event_start, - event_value=event_value, - ) - for event_start, event_value in final_output.iteritems() - ] - final_output = tb.BeliefsDataFrame(timed_beliefs) + final_output = final_output.to_frame("event_value") + final_output["belief_time"] = belief_time + final_output["cumulative_probability"] = 0.5 + final_output["source"] = self.data_source + final_output = final_output.set_index( + ["belief_time", "source", "cumulative_probability"], append=True + ) return final_output diff --git a/flexmeasures/data/models/time_series.py b/flexmeasures/data/models/time_series.py index e0c78cb9a..222863437 100644 --- a/flexmeasures/data/models/time_series.py +++ b/flexmeasures/data/models/time_series.py @@ -711,7 +711,7 @@ def search( # todo: compute median of collective belief instead of median of first belief (update expected test results accordingly) # todo: move to timely-beliefs: select mean/median belief if ( - bdf.lineage.number_of_sources == 1 + bdf.lineage.number_of_sources <= 1 and bdf.lineage.probabilistic_depth == 1 ): # Fast track, no need to loop over beliefs diff --git a/requirements/app.in b/requirements/app.in index af292a2c1..684b2bafe 100644 --- a/requirements/app.in +++ b/requirements/app.in @@ -29,8 +29,8 @@ redis >4.5, <5 tldextract pyomo>=5.6 tabulate -timetomodel>=0.7.1 -timely-beliefs[forecast]>=1.18 +timetomodel>=0.7.3 +timely-beliefs[forecast]>=1.20.1 python-dotenv # a backport, not needed in Python3.8 importlib_metadata diff --git a/requirements/app.txt b/requirements/app.txt index 215052b2e..c5aa68400 100644 --- a/requirements/app.txt +++ b/requirements/app.txt @@ -314,9 +314,9 @@ tabulate==0.9.0 # via -r requirements/app.in threadpoolctl==3.1.0 # via scikit-learn -timely-beliefs[forecast]==1.19.0 +timely-beliefs[forecast]==1.20.1 # via -r requirements/app.in -timetomodel==0.7.2 +timetomodel==0.7.3 # via -r requirements/app.in tldextract==3.4.0 # via -r requirements/app.in