Skip to content

Commit 5d9c1a2

Browse files
committed
Fetch output curves from bulk endpoint
1 parent 54e7cf7 commit 5d9c1a2

File tree

1 file changed

+51
-8
lines changed

1 file changed

+51
-8
lines changed

src/pyetm/services/scenario_runners/fetch_output_curves.py

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import io
22
from typing import Any, Dict
3+
import pandas as pd
34
from pyetm.services.scenario_runners.base_runner import BaseRunner
45
from pyetm.services.scenario_runners.fetch_curves_generic import (
5-
GenericCurveBulkRunner,
66
GenericCurveDownloadRunner,
77
)
88
from ..service_result import ServiceResult
@@ -26,7 +26,6 @@ def run(
2626
class FetchAllOutputCurvesRunner(BaseRunner[Dict[str, io.StringIO]]):
2727
"""Download all known output curves."""
2828

29-
# Known curve types from the Rails controller
3029
CURVE_TYPES = [
3130
"merit_order",
3231
"electricity_price",
@@ -45,9 +44,53 @@ def run(
4544
client: BaseClient,
4645
scenario: Any,
4746
) -> ServiceResult[Dict[str, io.StringIO]]:
48-
return GenericCurveBulkRunner.run(
49-
client,
50-
scenario,
51-
FetchAllOutputCurvesRunner.CURVE_TYPES,
52-
curve_type="output",
53-
)
47+
"""
48+
Uses the bulk endpoint to fetch all output curves at once as a single CSV,
49+
then splits them into their carrier groups
50+
"""
51+
try:
52+
path = f"/scenarios/{scenario.id}/bulk_output_curves"
53+
# Ask explicitly for CSV to avoid content negotiation issues
54+
resp = client.session.get(path, headers={"Accept": "text/csv"})
55+
56+
if not resp.ok:
57+
return ServiceResult.fail([f"{resp.status_code}: {resp.text}"])
58+
59+
# Read the returned CSV; first column is an index (e.g., hour)
60+
try:
61+
csv_text = resp.content.decode("utf-8")
62+
df = pd.read_csv(io.StringIO(csv_text), index_col=0)
63+
except Exception as e:
64+
return ServiceResult.fail([f"Failed to parse bulk CSV: {e}"])
65+
66+
results: Dict[str, io.StringIO] = {}
67+
warnings: list[str] = []
68+
69+
groups: Dict[str, list[str]] = {}
70+
for col in df.columns:
71+
base = str(col)
72+
for sep in (":", "/"):
73+
if sep in base:
74+
base = base.split(sep, 1)[0]
75+
break
76+
groups.setdefault(base, []).append(col)
77+
78+
for base, cols in groups.items():
79+
try:
80+
sub = df[cols].dropna(how="all")
81+
buf = io.StringIO()
82+
sub.to_csv(buf, index=True)
83+
buf.seek(0)
84+
results[base] = buf
85+
except Exception as e:
86+
warnings.append(f"{base}: Failed to prepare CSV: {e}")
87+
88+
if results:
89+
return ServiceResult.ok(data=results, errors=warnings or None)
90+
else:
91+
return ServiceResult.fail(warnings or ["No curves present in CSV"])
92+
93+
except (PermissionError, ValueError, ConnectionError) as e:
94+
return ServiceResult.fail([str(e)])
95+
except Exception as e:
96+
return ServiceResult.fail([str(e)])

0 commit comments

Comments
 (0)