Skip to content

Commit 05bfffa

Browse files
authored
(I002) setInputsCSV() (#447)
* [ModelicaSystemABC] define setInputCSV() - function to define input based on the content of a CSV file * add toInputs() - convert pandas DataFrame.to_dict(orient='list') output to OMPython input based on code written by joewa (see #447 (comment))
1 parent 25b7ee3 commit 05bfffa

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

OMPython/modelica_system_abc.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import abc
77
import ast
8+
import csv
89
from dataclasses import dataclass
910
import logging
1011
import numbers
@@ -936,6 +937,29 @@ def setOptimizationOptions(
936937
datatype="optimization-option",
937938
overridedata=None)
938939

940+
@staticmethod
941+
def toInputs(data: dict[str, list[float]]) -> dict[str, list[tuple[float, float]]]:
942+
"""
943+
Converts a dictionary of lists (from pandas DataFrame.to_dict(orient='list'))
944+
into the OMPython setInputs input format.
945+
946+
Example: mod.setInputs(**toInputs(pdf.to_dict(orient='list')))
947+
948+
Assumes the dictionary contains a key named 'time'.
949+
"""
950+
if "time" not in data:
951+
raise ValueError("The provided data must contain a 'time' key.")
952+
953+
time_series = data["time"]
954+
955+
inputs = {
956+
var_name: list(zip(time_series, values))
957+
for var_name, values in data.items()
958+
if var_name != "time"
959+
}
960+
961+
return inputs
962+
939963
def setInputs(
940964
self,
941965
*args: Any,
@@ -998,6 +1022,44 @@ def setInputs(
9981022

9991023
return True
10001024

1025+
def setInputsCSV(
1026+
self,
1027+
csvfile: os.PathLike,
1028+
) -> None:
1029+
"""
1030+
Read content from a CSV file and use it to define the time based input data.
1031+
"""
1032+
1033+
# real type is 'dict[str, list[tuple[float, float]]]' - 'dict[str, Any]' is used to make setInputs() happy
1034+
inputs: dict[str, Any] = {}
1035+
try:
1036+
with open(csvfile, newline='') as csvfh:
1037+
dialect = csv.Sniffer().sniff(csvfh.read(1024))
1038+
csvfh.seek(0)
1039+
reader = csv.DictReader(csvfh, dialect=dialect)
1040+
1041+
keys: list[str] = []
1042+
for idx, line in enumerate(reader):
1043+
if not keys:
1044+
keys = list(line.keys())
1045+
for var in keys[1:]:
1046+
if var in inputs:
1047+
raise ModelicaSystemError(f"Error reading {csvfile}: duplicated column {var}!")
1048+
inputs[var] = []
1049+
try:
1050+
# use key[0] as time; all other columns use the header as name
1051+
for var in keys[1:]:
1052+
inputs[var].append((float(line[keys[0]]), float(line[var])))
1053+
except (ValueError, TypeError) as exc2:
1054+
raise ModelicaSystemError(f"Invalid value reading {csvfile} line {idx}/{var}: "
1055+
f"{line}!") from exc2
1056+
1057+
except IOError as exc1:
1058+
raise ModelicaSystemError(f"Error reading {csvfile}: {exc1}") from exc1
1059+
1060+
if inputs:
1061+
self.setInputs(**inputs)
1062+
10011063
def _createCSVData(self, csvfile: Optional[OMPathABC] = None) -> OMPathABC:
10021064
"""
10031065
Create a csv file with inputs for the simulation/optimization of the model. If csvfile is provided as argument,

0 commit comments

Comments
 (0)