forked from openscm/openscm-runner
-
Notifications
You must be signed in to change notification settings - Fork 0
/
hector_wrapper.py
185 lines (150 loc) · 6.69 KB
/
hector_wrapper.py
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
"""
Hector Wrapper
"""
import logging
import os
import re
import shutil
import subprocess # nosec # have to use subprocess
import tempfile
from distutils import dir_util
import numpy as np
import pandas as pd
import platform
from scmdata import ScmRun, run_append
from ...settings import config
from .hector_utils.scenario_writer import SCENARIOFILEWRITER
from .hector_utils.parameter_writer import PARAMETERFILEWRITER
from .hector_utils.results_reader import HECTORREADER
LOGGER = logging.getLogger(__name__)
class HectorWrapper:
"""
Hector Wrapper
"""
def __init__(self, scenario_data):
"""
Intialise Hector wrapper
"""
# Initialization steps for the given scenario
# Set paths
self.input_dir = os.path.join(os.path.dirname(__file__), 'input')
self.run_dir = os.path.join(self.input_dir, 'run_dir')
self.output_dir = os.path.join(self.input_dir, 'output')
self.logs_dir = os.path.join(self.input_dir, 'logs')
# Set scenario_data to be available by the object
self.scenario_data = scenario_data.copy()
# Extract the model/scenario/region combination
self.region = scenario_data.index[0][1].replace('/', '_')
self.scenario = scenario_data.index[0][2].replace('/', '_')
self.model = scenario_data.index[0][0].replace('/', '_')
# Current Run .ini File Name
self.cur_run_ini_fn = f'{self.model}_{self.region}_{self.scenario}_cfg.ini'
# Current Run emissions file name
self.cur_run_emis_fn = f'{self.model}_{self.region}_{self.scenario}_emis.csv'
# Output file name
self.output_fn = f'outputstream_{self.model}_{self.region}_{self.scenario}.csv'
# Helper objects for writing Hector input files, and reading results
self.sfilewriter = SCENARIOFILEWRITER(self.input_dir, self.run_dir, self.cur_run_emis_fn)
self.pamfilewriter = PARAMETERFILEWRITER(self.input_dir, self.run_dir, self.cur_run_ini_fn, self.cur_run_emis_fn)
self.resultsreader = HECTORREADER(self.input_dir, self.output_dir, self.output_fn)
# Create the scenario file, save end_year for later use
self.end_year = self.sfilewriter.write_scenario_file(scenario_data)
def run_over_cfgs(self, cfgs, output_variables):
"""
Run over each configuration parameter set
write parameterfiles, run, read results
and make an ScmRun with results
"""
# Create empty list of runs
runs = []
for i, cfg in enumerate(cfgs):
# Write the ini file
self.pamfilewriter.write_parameterfile(cfg, self.region, self.scenario, self.model, self.end_year)
# Get the hector executable file
executable = self._get_executable()
# param file with relative path
param_file = os.path.join(self.run_dir, self.cur_run_ini_fn)
# Call string
call = f'{executable} {param_file}'
# Call executable
subprocess.check_call(
call,
cwd=self.input_dir,
shell=True
)
# Read Output File
run = self.resultsreader.read_results(i, output_variables, self.region, self.scenario, self.model)
# Append run to list of runs
runs.append(run)
# Return list of runs using ScmRun append function
return run_append(runs)
def cleanup_tempdirs(self):
"""
Clean up temp data from run
"""
# Clean up run directory
self._clean_dir('run_dir')
# Clean up output directory
self._clean_dir('output')
# Clean up logs directory
self._clean_dir('logs')
...
def _clean_dir(self, dir_to_clean):
"""
Remove files in given directory in input folder
"""
for file_name in os.listdir(os.path.join(self.input_dir, dir_to_clean)):
if file_name != '.gitignore':
file_path = os.path.join(self.input_dir, dir_to_clean, file_name)
try:
os.unlink(file_path)
except Exception as e:
print(f'Failed to delete {file_name}. Reason: {e}')
...
def _get_executable(self):
if platform.system() == "Windows":
executable = os.path.join(self.input_dir, "hector.exe")
else:
executable = os.path.join(self.input_dir, "hector")
return executable
# These are all the variables we're expected to be able to output at minimum
# "Surface Air Temperature Change",
# "Surface Air Ocean Blended Temperature Change",
# "Effective Radiative Forcing",
# "Effective Radiative Forcing|Anthropogenic",
# "Effective Radiative Forcing|Aerosols",
# "Effective Radiative Forcing|Aerosols|Direct Effect",
# "Effective Radiative Forcing|Aerosols|Direct Effect|BC",
# "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC Fossil and Industrial",
# "Effective Radiative Forcing|Aerosols|Direct Effect|BC|MAGICC AFOLU",
# "Effective Radiative Forcing|Aerosols|Direct Effect|OC",
# "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC Fossil and Industrial",
# "Effective Radiative Forcing|Aerosols|Direct Effect|OC|MAGICC AFOLU",
# "Effective Radiative Forcing|Aerosols|Direct Effect|SOx",
# "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC Fossil and Industrial",
# "Effective Radiative Forcing|Aerosols|Direct Effect|SOx|MAGICC AFOLU",
# "Effective Radiative Forcing|Aerosols|Indirect Effect",
# "Effective Radiative Forcing|Greenhouse Gases",
# "Effective Radiative Forcing|CO2",
# "Effective Radiative Forcing|CH4",
# "Effective Radiative Forcing|N2O",
# "Effective Radiative Forcing|F-Gases",
# "Effective Radiative Forcing|HFC125",
# "Effective Radiative Forcing|HFC134a",
# "Effective Radiative Forcing|HFC143a",
# "Effective Radiative Forcing|HFC227ea",
# "Effective Radiative Forcing|HFC23",
# "Effective Radiative Forcing|HFC245fa",
# "Effective Radiative Forcing|HFC32",
# "Effective Radiative Forcing|HFC4310mee",
# "Effective Radiative Forcing|CF4",
# "Effective Radiative Forcing|C6F14",
# "Effective Radiative Forcing|C2F6",
# "Effective Radiative Forcing|SF6",
# "Heat Uptake",
# "Heat Uptake|Ocean",
# "Atmospheric Concentrations|CO2",
# "Atmospheric Concentrations|CH4",
# "Atmospheric Concentrations|N2O",
# "Net Atmosphere to Land Flux|CO2",
# "Net Atmosphere to Ocean Flux|CO2"