Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save beliefs data to file #519

Merged
merged 9 commits into from Nov 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions documentation/changelog.rst
Expand Up @@ -13,6 +13,7 @@ New features
* Visually distinguish forecasts/schedules (dashed lines) from measurements (solid lines), and expand the tooltip with timing info regarding the forecast/schedule horizon or measurement lag [see `PR #503 <http://www.github.com/FlexMeasures/flexmeasures/pull/503>`_]
* The asset page also allows to show sensor data from other assets that belong to the same account [see `PR #500 <http://www.github.com/FlexMeasures/flexmeasures/pull/500>`_]
* Improved import of time series data from CSV file: 1) drop duplicate records with warning, and 2) allow configuring which column contains explicit recording times for each data point (use case: import forecasts) [see `PR #501 <http://www.github.com/FlexMeasures/flexmeasures/pull/501>`_]
* The CLI command ``flexmeasures show beliefs`` supports showing beliefs data in a custom resolution and/or timezone, and also saving the shown beliefs data to a CSV file [see `PR #519 <http://www.github.com/FlexMeasures/flexmeasures/pull/519>`_]

Bugfixes
-----------
Expand Down
3 changes: 2 additions & 1 deletion documentation/cli/change_log.rst
Expand Up @@ -4,9 +4,10 @@
FlexMeasures CLI Changelog
**********************

since v0.12.0 | November xx, 2022
since v0.12.0 | November XX, 2022
=================================

* Add ``--resolution``, ``--timezone`` and ``--to-file`` options to ``flexmeasures show beliefs``, to show beliefs data in a custom resolution and/or timezone, and also to save shown beliefs data to a CSV file.
* Fix ``flexmeasures db-ops dump`` and ``flexmeasures db-ops restore`` incorrectly reporting a success when `pg_dump` and `pg_restore` are not installed.

since v0.11.0 | August 28, 2022
Expand Down
48 changes: 42 additions & 6 deletions flexmeasures/cli/data_show.py
Expand Up @@ -258,20 +258,45 @@ def list_data_sources():
type=DataSourceIdField(),
help="Source of the beliefs (an existing source id).",
)
@click.option(
"--resolution",
"resolution",
type=DurationField(),
required=False,
help="Resolution of the data. If not set, defaults to the minimum resolution of the sensor data.",
)
@click.option(
"--timezone",
"timezone",
type=str,
required=False,
help="Timezone of the data. If not set, defaults to the timezone of the first non-empty sensor.",
)
@click.option(
"--to-file",
"filepath",
required=False,
type=str,
help="Set a filepath to store the beliefs as a CSV file.",
)
def plot_beliefs(
sensors: List[Sensor],
start: datetime,
duration: timedelta,
resolution: Optional[timedelta],
timezone: Optional[str],
belief_time_before: Optional[datetime],
source: Optional[DataSource],
filepath: Optional[str],
):
"""
Show a simple plot of belief data directly in the terminal.
Show a simple plot of belief data directly in the terminal, and optionally, save the data to a CSV file.
"""
sensors = list(sensors)
minimum_resampling_resolution = determine_minimum_resampling_resolution(
[sensor.event_resolution for sensor in sensors]
)
if resolution is None:
resolution = determine_minimum_resampling_resolution(
[sensor.event_resolution for sensor in sensors]
)

# query data
beliefs_by_sensor = TimedBelief.search(
Expand All @@ -281,7 +306,7 @@ def plot_beliefs(
beliefs_before=belief_time_before,
source=source,
one_deterministic_belief_per_event=True,
resolution=minimum_resampling_resolution,
resolution=resolution,
sum_multiple=False,
)
# only keep non-empty
Expand All @@ -303,6 +328,11 @@ def plot_beliefs(
df = pd.concat([simplify_index(df) for df in beliefs_by_sensor.values()], axis=1)
df.columns = beliefs_by_sensor.keys()

# Convert to the requested or default timezone
if timezone is not None:
timezone = sensors[0].timezone
df.index = df.index.tz_convert(timezone)

# Build title
if len(sensors) == 1:
title = f"Beliefs for Sensor '{sensors[0].name}' (Id {sensors[0].id}).\n"
Expand All @@ -313,7 +343,7 @@ def plot_beliefs(
title += f"\nOnly beliefs made before: {belief_time_before}."
if source:
title += f"\nSource: {source.description}"
title += f"\nThe time resolution (x-axis) is {naturaldelta(minimum_resampling_resolution)}."
title += f"\nThe time resolution (x-axis) is {naturaldelta(resolution)}."

uniplot.plot(
[df[col] for col in df.columns],
Expand All @@ -325,6 +355,12 @@ def plot_beliefs(
if shared_unit
else [s.name + f" (in {s.unit})" for s in sensors],
)
if filepath is not None:
df.columns = pd.MultiIndex.from_arrays(
[df.columns, [df.sensor.unit for df in beliefs_by_sensor.values()]]
)
df.to_csv(filepath)
click.echo("Data saved to file.")


app.cli.add_command(fm_show_data)
6 changes: 5 additions & 1 deletion flexmeasures/cli/tests/test_data_show.py
@@ -1,4 +1,5 @@
import pytest
from click.formatting import wrap_text

from flexmeasures.data.models.time_series import Sensor
from flexmeasures.cli.tests.utils import get_click_commands
Expand Down Expand Up @@ -121,5 +122,8 @@ def test_cli_help(app):
for cmd in get_click_commands(data_show):
result = runner.invoke(cmd, ["--help"])
assert "Usage" in result.output
assert cmd.__doc__.strip() in result.output
assert (
wrap_text(cmd.__doc__.strip(), initial_indent=" ", subsequent_indent=" ")
in result.output
)
assert result.exit_code == 0