Coverage for aixcalibuha/utils/configuration.py: 70%
53 statements
« prev ^ index » next coverage.py v7.4.1, created at 2024-01-27 10:48 +0000
« prev ^ index » next coverage.py v7.4.1, created at 2024-01-27 10:48 +0000
1"""
2Module to with configs and functions to read configs for objects in this repository.
3"""
4import os
5import collections
6import toml
7import numpy as np
8from ebcpy import data_types
9from aixcalibuha import Goals, CalibrationClass, TunerParas
11tsd_config = {"data": "TODO: Specify the path to the target values measured",
12 "key": None,
13 "sheet_name": None,
14 "sep": ","}
16kwargs_calibrator = {"timedelta": 0,
17 "save_files": False,
18 "verbose_logging": True,
19 "show_plot": True,
20 "create_tsd_plot": True,
21 "save_tsd_plot": True,
22 "fail_on_error": False,
23 "ret_val_on_error": np.NAN}
25# Specify kwargs for multiple-class-calibration
26kwargs_multiple_classes = {"merge_multiple_classes": True,
27 "fix_start_time": 0,
28 "timedelta": 0}
30default_input_config = {"sim_input_names": None,
31 "sim_data_path": None,
32 "meas_input_names": None,
33 "meas_input_data": tsd_config,
34 }
36default_cal_class_config = {"name": "TODO: Specify the name of the calibration class",
37 "start_time": "TODO: Specify the start time of the class - e.g 0",
38 "stop_time": "TODO: Specify the end time of the class",
39 "goals": {"meas_target_data": tsd_config,
40 "variable_names": "TODO: Specify variable names",
41 "weightings": "TODO: Insert null if you don´t need special weightings. "
42 "Else specify which goal get´s which weighting through a list"},
43 "tuner_paras": {"names":
44 "TODO: Specify the names of the tuner parameters list",
45 "initial_values":
46 "TODO: Specify the inital values of the tuner parameters list",
47 "bounds":
48 "TODO: Specify the boundaries of the tuner parameters as a list of tuples"}}
50default_calibration_config = {
51 "statistical_measure": "TODO: Specify the statistical "
52 "measure for calibration (RMSE, MAE, etc.)",
53 "calibration_classes": [default_cal_class_config],
54 "start_time_method": 'fixstart',
55 "settings": kwargs_calibrator,
56 "settings multiple classes": kwargs_multiple_classes
57}
59kwargs_scipy_dif_evo = {"maxiter": 30,
60 "popsize": 5,
61 "mutation": (0.5, 1),
62 "recombination": 0.7,
63 "seed": None,
64 "polish": True,
65 "init": 'latinhypercube',
66 "atol": 0}
68kwargs_dlib_min = {"num_function_calls": int(1e9),
69 "solver_epsilon": 0}
71kwargs_scipy_min = {"tol": None,
72 "options": {"maxfun": 1},
73 "constraints": None,
74 "jac": None,
75 "hess": None,
76 "hessp": None}
78default_optimization_config = {"framework": "TODO: Choose the framework for calibration",
79 "method": "TODO: Choose the method of the framework",
80 "settings": {
81 "scipy_differential_evolution": kwargs_scipy_dif_evo,
82 "dlib_minimize": kwargs_dlib_min,
83 "scipy_minimize": kwargs_scipy_min}
84 }
86default_sim_config = {"packages": None,
87 "model_name": None,
88 "type": "DymolaAPI",
89 "dymola_path": None,
90 "dymola_interface_path": None,
91 "equidistant_output": True,
92 "show_window": False,
93 "get_structural_parameters": True
94 }
96default_config = {
97 "Working Directory": "TODO: Add the path where you want to work here",
98 "SimulationAPI": default_sim_config,
99 "Optimization": default_optimization_config,
100 "Input Data": default_input_config,
101 "Calibration": default_calibration_config
102}
105def get_goals_from_config(config):
106 """
107 Read the data for a Goals object.
109 :param dict config:
110 Config holding the following cols for
111 - meas_target_data
112 - variable_names
113 - Optional: weightings
114 :return: Goals goals
115 Loaded Goals object
116 """
117 config_mtd = config["meas_target_data"]
118 mtd = data_types.TimeSeriesData(**config_mtd)
119 return Goals(meas_target_data=mtd,
120 variable_names=config["variable_names"],
121 statistical_measure=config["statistical_measure"],
122 weightings=config.get("weightings", None))
125def get_tuner_paras_from_config(config):
126 """
127 Read the data for a TunerParas object.
129 :param dict config:
130 Config holding the following cols for
131 - names
132 - initial_values
133 - bounds
134 :return: TunerParas tuner_paras
135 Loaded Goals object
136 """
137 return TunerParas(names=config["names"],
138 initial_values=config["initial_values"],
139 bounds=config["bounds"])
142def get_calibration_classes_from_config(config):
143 """
144 Read the data for a CalibrationClass object.
146 :param list config:
147 List of dicts with configs holding the following cols for
148 - names
149 - start_time
150 - stop_time
151 - Optional: goals, tuner_paras, relevant_intervals
152 :return: TunerParas tuner_paras
153 Loaded Goals object
154 """
155 cal_classes = []
156 for cal_class_config in config:
157 goals, tuner_paras = None, None
158 if "goals" in cal_class_config:
159 goals = get_goals_from_config(cal_class_config["goals"])
160 if "tuner_paras" in cal_class_config:
161 tuner_paras = get_tuner_paras_from_config(cal_class_config["tuner_paras"])
162 cal_classes.append(
163 CalibrationClass(name=cal_class_config["name"],
164 start_time=cal_class_config["start_time"],
165 stop_time=cal_class_config["stop_time"],
166 goals=goals,
167 tuner_paras=tuner_paras,
168 relevant_intervals=cal_class_config.get("relevant_intervals", None)))
169 return cal_classes
172def write_config(filepath, config):
173 """
174 Write the given config to the filepath.
175 If the file already exists, the data is recursively
176 updated.
178 :param str,os.path.normpath filepath:
179 Filepath with the config.
180 :param: dict config:
181 Config to be saved
182 """
183 if os.path.exists(filepath):
184 existing_config = read_config(filepath)
185 if existing_config:
186 config = _update(existing_config, config)
188 with open(filepath, "a+") as file:
189 file.seek(0)
190 file.truncate()
191 toml.dump(config, file)
194def read_config(filepath):
195 """
196 Read the given file and return the toml-config
198 :param str,os.path.normpath filepath:
199 Filepath with the config.
200 :return: dict config:
201 Loaded config
202 """
203 with open(filepath, "r") as file:
204 config = toml.load(file)
205 return config
208def _update(dic, new_dic):
209 """Recursively update a given dictionary with a new one"""
210 for key, val in new_dic.items():
211 if isinstance(val, collections.abc.Mapping):
212 dic[key] = _update(dic.get(key, {}), val)
213 else:
214 dic[key] = val
215 return dic