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

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 

10 

11tsd_config = {"data": "TODO: Specify the path to the target values measured", 

12 "key": None, 

13 "sheet_name": None, 

14 "sep": ","} 

15 

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} 

24 

25# Specify kwargs for multiple-class-calibration 

26kwargs_multiple_classes = {"merge_multiple_classes": True, 

27 "fix_start_time": 0, 

28 "timedelta": 0} 

29 

30default_input_config = {"sim_input_names": None, 

31 "sim_data_path": None, 

32 "meas_input_names": None, 

33 "meas_input_data": tsd_config, 

34 } 

35 

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"}} 

49 

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} 

58 

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} 

67 

68kwargs_dlib_min = {"num_function_calls": int(1e9), 

69 "solver_epsilon": 0} 

70 

71kwargs_scipy_min = {"tol": None, 

72 "options": {"maxfun": 1}, 

73 "constraints": None, 

74 "jac": None, 

75 "hess": None, 

76 "hessp": None} 

77 

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 } 

85 

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 } 

95 

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} 

103 

104 

105def get_goals_from_config(config): 

106 """ 

107 Read the data for a Goals object. 

108 

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)) 

123 

124 

125def get_tuner_paras_from_config(config): 

126 """ 

127 Read the data for a TunerParas object. 

128 

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"]) 

140 

141 

142def get_calibration_classes_from_config(config): 

143 """ 

144 Read the data for a CalibrationClass object. 

145 

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 

170 

171 

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. 

177 

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) 

187 

188 with open(filepath, "a+") as file: 

189 file.seek(0) 

190 file.truncate() 

191 toml.dump(config, file) 

192 

193 

194def read_config(filepath): 

195 """ 

196 Read the given file and return the toml-config 

197 

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 

206 

207 

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