-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.py
More file actions
274 lines (198 loc) · 15.5 KB
/
Copy pathmain.py
File metadata and controls
274 lines (198 loc) · 15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
from matplotlib import typing
import src.utilities as utils
from pathlib import Path
import src # loading the src module to access its functions/methods
import otoole
import shutil
from typing import Dict
# from src import (
# cluster_data, run_simulation, new_list, CFandSDP, conversionlts, conversionld, conversionlh, conversionldc,
# yearsplit, daysindaytype, new_yaml_param, copy_and_rename, intraday_kotzur, intraday_welsch, intraday_welsch2, read_csvfile, graph, table
# )
# Load configuration
config_path:Path=Path('config/config.yaml')
config:dict = utils.load_config(config_path)
utils.print_update(level=2,message="Extracting parameters from the configuration")
scenario_name:str = config['scenario_name']
days_in_year:int = config['days_in_year']
seasons:int = config['seasons']
hour_grouping:int= config['hour_grouping']
n_clusters:int= config['n_clusters']
StorageLevelStart:float = config['StorageLevelStart']
StorageMaxCapacity:float = config['StorageMaxCapacity']
ResidualStorageCapacity:float = config['ResidualStorageCapacity']
results_destination_folder:Path = Path(config['results']['directory'])
results_destination_folder.mkdir(parents=True, exist_ok=True)
results_GUI_destination_folder:Path = Path(config['results']['directory_GUI'])
results_GUI_destination_folder.mkdir(parents=True, exist_ok=True)
results_copied_filename:str = config['results']['results_copied_filename']
results_excel_file:str = config['results']['results_excel_file']
input_CF_csv_file:Path = Path(config['data_8760']['directory']) / config['data_8760']['CF']
input_SDP_csv_file:Path = Path(config['data_8760']['directory']) / config['data_8760']['SDP']
representative_days, chronological_sequence = src.cluster_data(input_CF_csv_file,input_SDP_csv_file,n_clusters)
utils.print_update(level=2,message=f"Representative days: {representative_days}")
# Number of blocks per day based on the hour grouping
blocks_per_day:int = 24 // hour_grouping
utils.print_update(level=2,message=f"Hour Grouping from config: {hour_grouping}")
# Total timeslices considering the representative days
timeslices:int = len(representative_days) * blocks_per_day
utils.print_update(level=2,message=f"Timeslices: {timeslices}")
# Chronological timeslices is number of days in year * blocks per day. If hourly analysis, chronological timeslice is 8760
chronological_timeslices:int = days_in_year * blocks_per_day
year_split:int = 1 / timeslices
day_split:int = hour_grouping / (24 * 365)
cases:dict = config['cases']
# cases:dict = {k: cases[k] for k in list(cases.keys())[1:2]} # 20250719:EL: testing each scenario
utils.print_info(f"Cases from config: {list(cases.keys())}")
# """
for case_name, case_info in cases.items():
if case_name == 'Model_Cluster':
utils.print_update(level=1,message=f"Updating case: {case_name}")
# Updating timeslicecro
output_timeslicecro_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['timeslicecro']
src.new_list(chronological_timeslices, output_timeslicecro_csv_file)
# Updating conversionlts
output_conversionlts_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['conversionlts']
src.conversionlts(blocks_per_day, chronological_timeslices, timeslices, chronological_sequence, representative_days, output_conversionlts_csv_file)
# Updating day split in yaml file
otoole_yaml_file = Path(case_info['root_directory']) / case_info['otoole_config']
src.new_yaml_param(otoole_yaml_file, 'DaySplit', day_split)
if case_name == 'Model_Kotzur':
utils.print_update(level=1,message=f"Updating case: {case_name}")
# Updating dayscro
output_dayscro_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['dayscro']
src.new_list(days_in_year, output_dayscro_csv_file)
# Updating conversionld
output_conversionld_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['conversionld']
src.conversionld(timeslices, len(representative_days), output_conversionld_csv_file)
# Updating conversionldc
output_conversionldc_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['conversionldc']
src.conversionldc(chronological_sequence, representative_days, days_in_year, output_conversionldc_csv_file)
# Updating day split in yaml file
otoole_yaml_file = Path(case_info['root_directory']) / case_info['otoole_config']
src.new_yaml_param(otoole_yaml_file, 'DaySplit', day_split)
if case_name == 'Model_Welsch':
utils.print_update(level=1,message=f"Updating case: {case_name}")
# Updating dailytimebracket
output_dailytimebracket_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['dailytimebracket']
src.new_list(blocks_per_day, output_dailytimebracket_csv_file)
# Updating conversionld
output_conversionld_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['conversionld']
src.conversionld(timeslices, len(representative_days), output_conversionld_csv_file)
# Updating conversionlh
output_conversionlh_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['conversionlh']
src.conversionlh(timeslices, blocks_per_day, output_conversionlh_csv_file)
# Updating conversionls
output_conversionls_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['conversionls']
src.conversionld(timeslices, seasons, output_conversionls_csv_file, label='SEASON')
# Updating daysindaytype
output_daysindaytype_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['daysindaytype']
src.daysindaytype(representative_days, chronological_sequence, output_daysindaytype_csv_file)
# Updating day split in yaml file
otoole_yaml_file = Path(case_info['root_directory']) / case_info['otoole_config']
src.new_yaml_param(otoole_yaml_file, 'DaySplit', day_split)
if case_name == 'Model_Niet' or case_name == 'Model_Cluster' or case_name == 'Model_Kotzur' or case_name == 'Model_Welsch':
utils.print_update(level=1,message=f"Updating case: {case_name}")
# Define the source directory
source_template = Path("inputs_csv")
# List all CSV files in the directory
csv_files = list(source_template.glob('*.csv'))
# Creating txt from csv using otoole
input_csv_dir = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory']
output_txt_file = Path(case_info['root_directory']) / case_info['output_otoole_txt']
template_config = Path(case_info['root_directory']) / case_info['otoole_config']
#-----------------------------------------------------
# 20250719 --- Missing workflow step added by Elias
otoole_cfg=utils.load_config(template_config)
excepted_file_names = set(otoole_cfg.keys())
# Copy matching files to input_csv_dir directory
input_csv_dir.mkdir(exist_ok=True)
for csv_file in csv_files:
# Remove .csv extension and compare
name_no_ext = csv_file.stem
if name_no_ext in excepted_file_names:
shutil.copy(csv_file, input_csv_dir / csv_file.name)
utils.print_update(level=3,message=f"Copied: {csv_file.name}")
utils.print_update(level=2,message="Using Otoole python API to convert CSV files to TXT")
utils.print_update(level=3,message=f"Converting CSV files to TXT for case: {case_name}")
#-----------------------------------------------------
# Updating timeslice
output_timeslice_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['timeslice']
src.new_list(timeslices, output_timeslice_csv_file)
# Updating daytype
output_daytype_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['daytype']
daytypes = len(representative_days)
src.new_list(daytypes, output_daytype_csv_file)
# Updating yearsplit
output_yearsplit_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['yearsplit']
src.yearsplit(timeslices, representative_days, chronological_sequence, days_in_year, output_yearsplit_csv_file)
# Updating capacity factor (averaging the values)
output_CF_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['capacity_factor']
src.CFandSDP(input_CF_csv_file, representative_days, hour_grouping, output_CF_csv_file, operation='mean')
# Updating specified demand profile (summing the values)
output_SDP_csv_file = Path(case_info['root_directory']) / case_info['input_otoole_csv']['directory'] / case_info['input_otoole_csv']['specified_demand_profile']
src.CFandSDP(input_SDP_csv_file, representative_days, hour_grouping, output_SDP_csv_file, operation='sum')
# Updating year split in yaml file
# This is no longer necessary because the yearsplit was updated in the CSV.
# But I kept it in case the yearsplit is the same in some study.
otoole_yaml_file = Path(case_info['root_directory']) / case_info['otoole_config']
print(otoole_yaml_file)
src.new_yaml_param(otoole_yaml_file, 'YearSplit', year_split)
# Updating storage info in yaml file
#src.new_yaml_param(otoole_yaml_file, 'StorageLevelStart', StorageLevelStart)
src.new_yaml_param(otoole_yaml_file, 'StorageMaxCapacity', StorageMaxCapacity)
src.new_yaml_param(otoole_yaml_file, 'ResidualStorageCapacity', ResidualStorageCapacity)
# command = f"otoole convert csv datafile {input_csv_dir} {output_txt_file} {template_config}"
# result = subprocess.run(command, shell=True, text=True, capture_output=True)
print
result=otoole.convert(template_config, 'csv', 'datafile', input_csv_dir, output_txt_file) # using API instead of CLI
if result:
utils.print_update(level=2,message="✔️ Otoole conversion executed successfully.")
else:
utils.print_update(level=2,message="❌ Otoole conversion failed.")
utils.print_update(level=2,message=f"Running simulation for case: {case_name}")
src.run_simulation(case_info)
utils.print_update(level=2,message=f"Saving results case: {case_name}")
results_case = Path(case_info['root_directory']) / case_info['results']['directory'] / case_info['results']['storage_level']
new_results_filename = '_'.join([scenario_name,results_copied_filename,case_name]) + '.csv'
src.copy_and_rename(results_case, results_destination_folder, new_results_filename)
data_sol_results = Path(case_info['root_directory']) / case_info['data_sol']
simulation_results = Path(case_info['root_directory']) / case_info['simulation_results']
results_file = Path(results_destination_folder) / results_excel_file
capacity_path = Path(case_info['root_directory']) / case_info['results']['directory'] / case_info['results']['power_capacity']
storage_capacity_path = Path(case_info['root_directory']) / case_info['results']['directory'] / case_info['results']['storage_capacity']
src.table(simulation_results, data_sol_results, scenario_name, case_name, capacity_path, storage_capacity_path, 'WINDPOWER', 'BATTERY', results_file)
# """
print("Generating graph")
file_conversionlts = Path(config['cases']['Model_Cluster']['root_directory']) / config['cases']['Model_Cluster']['input_otoole_csv']['directory'] / config['cases']['Model_Cluster']['input_otoole_csv']['conversionlts']
file_kotzur_storage = Path(config['cases']['Model_Kotzur']['root_directory']) / config['cases']['Model_Kotzur']['results']['directory'] / config['cases']['Model_Kotzur']['results']['storage_levelTS']
file_kotzur_intraday = Path(results_destination_folder) / ('_'.join([scenario_name,results_copied_filename,'Model_Kotzur_intraday']) + '.csv')
file_kotzur_storage_start = Path(config['cases']['Model_Kotzur']['root_directory']) / config['cases']['Model_Kotzur']['results']['directory'] / config['cases']['Model_Kotzur']['results']['storage_level_Start']
print(f"temp_DEBUG_prob_EL| file_kotzur_storage_start: {file_kotzur_storage_start}")
StorageLevelStartKotzur = src.read_csvfile(file_kotzur_storage_start)
src.intraday_kotzur(file_conversionlts, file_kotzur_storage, StorageLevelStartKotzur, file_kotzur_intraday)
file_welsch_storage = Path(config['cases']['Model_Welsch']['root_directory']) / config['cases']['Model_Welsch']['results']['directory'] / config['cases']['Model_Welsch']['results']['storage_levelTS']
file_welsch_intraday = Path(results_destination_folder) / ('_'.join([scenario_name,results_copied_filename,'Model_Welsch_intraday']) + '.csv')
file_welsch_storage_start = Path(config['cases']['Model_Welsch']['root_directory']) / config['cases']['Model_Welsch']['results']['directory'] / config['cases']['Model_Welsch']['results']['storage_level_Start']
StorageLevelStartWelsch = src.read_csvfile(file_welsch_storage_start)
src.intraday_welsch2(file_welsch_storage, blocks_per_day, timeslices, representative_days, chronological_sequence, StorageLevelStartWelsch, file_welsch_intraday)
file_base = Path(results_destination_folder) / ('_'.join(['k365h1WND_Storage_Level_Model_Niet']) + '.csv')
file_kotzur = Path(results_destination_folder) / ('_'.join([scenario_name,results_copied_filename,'Model_Kotzur']) + '.csv')
file_cluster = Path(results_destination_folder) / ('_'.join([scenario_name,results_copied_filename,'Model_Cluster']) + '.csv')
file_niet = Path(results_destination_folder) / ('_'.join([scenario_name,results_copied_filename,'Model_Niet']) + '.csv')
file_welsch = Path(results_destination_folder) / ('_'.join([scenario_name,results_copied_filename,'Model_Welsch']) + '.csv')
" Any output_yearsplit_csv_file"
output_yearsplit_csv_file=Path(config['cases']['Model_Cluster']['root_directory']) / config['cases']['Model_Cluster']['input_otoole_csv']['directory'] / config['cases']['Model_Cluster']['input_otoole_csv']['yearsplit']
fig, fig2, fig3 = src.graph(file_base, file_kotzur, file_kotzur_intraday, file_cluster, file_niet, file_welsch, file_welsch_intraday, representative_days, blocks_per_day, output_yearsplit_csv_file)
figure_filename = '_'.join([scenario_name, 'Figure']) + '.png'
figure_path = Path(results_destination_folder) / figure_filename
figure_GUI_pah = Path(results_GUI_destination_folder) / figure_filename
fig.savefig(figure_path)
#fig.savefig(figure_GUI_pah)
figure2_filename = '_'.join([scenario_name, 'Figure_Hourly']) + '.png'
figure2_path = Path(results_destination_folder) / figure2_filename
fig2.savefig(figure2_path)
fig2.savefig(figure_GUI_pah)
figure3_filename = '_'.join([scenario_name, 'Figure_Hourly_2Weeks']) + '.png'
figure3_path = Path(results_destination_folder) / figure3_filename
fig3.savefig(figure3_path)