This repository has been archived by the owner on Sep 19, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.py
executable file
·266 lines (223 loc) · 10.3 KB
/
main.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
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
#! /usr/bin/env python
# main python script
#
# 2008-06-27 CAF
# 2008-08-27 CAF Added checks for existing files, fixed bug when variable
# name is changed U->ua
# 2008-11-06 CAF added ensemble id, output dir for plots, and project name
# 2008-11-18 CAF added climo and plot directories.
# 2008-11-20 CAF added support for multiple required variables for
# derived fields.
# 2008-12-01 CAF added namelist option on command line, switched
# system call to ncl to popen
# skip variable if it's missing
# 2009-01-27 CAF changed climo dir structure
# 2009-03-04 CAF added logic to handle different file numbers for
# required variables
# 2009-05-22 CAF changed method of field_number creation, var_att
# files can now have *2*z
# *2*s *3* formatted Requires line
# 2009-05-27 CAF seach for filenames w/wo date range
# 2009-06-12 CAF Don't do climatology for I and D
# 2010-12-02 HS added environment variables to set maximum data sizes
# 2010-12-14 HS added termination call when error occurs with reformat
# 2012-06-08 HS set environment variable (OPTIONS_FILE) if
# namelist.global_vars.write_plot_vars is defined
# 2015-06-26 SR Added optional <ESGF> section quality check and print
# 2015-06-30 a_laue_ax: added ESMValTool version
import sys
sys.path.append("./interface_scripts")
# path to ESMVal python toolbox library
sys.path.append("./diag_scripts/lib/python")
sys.path.append("./diag_scripts")
from auxiliary import info, error, print_header, ncl_version_check
## from climate import climate
from optparse import OptionParser
import datetime
import projects
import os
import pdb
import reformat
import xml.sax
import xml_parsers
# Define ESMValTool version
version = "1.1.0"
os.environ['0_ESMValTool_version'] = version
# Check NCL version
ncl_version_check()
# Check command arguments.
usage = "%prog nml/namelist-file.xml"
description = """ESMValTool - Earth System Model Evaluation Tool.
For further help, check the doc/-folder for pdfs and references therein."""
parser = OptionParser(usage=usage, description=description)
parser.add_option("-r", "--reformat",
action="store_true", dest="reformat", default=False,
help="run reformat scripts for the observations according to namelist")
options, args = parser.parse_args()
if len(args) == 0:
parser.print_help()
sys.exit(0)
# Get command arguments.
input_xml_full_path = args[0]
# Parse input namelist into project_info-dictionary.
Project = xml_parsers.namelistHandler()
parser = xml.sax.make_parser()
parser.setContentHandler(Project)
parser.parse(input_xml_full_path)
# Project_info is a dictionary with all info from the namelist.
project_info = Project.project_info
if options.reformat:
if 'REFORMAT' not in project_info.keys():
error('No REFORMAT tag specified in {0}'.format(input_xml_full_path))
if len(project_info['REFORMAT']) == 0:
info('No reformat script specified',1,1)
print_header({}, options.reformat)
for k,v in project_info['REFORMAT'].iteritems():
if not os.path.exists(v):
error('Path {0} does not exist'.format(v))
projects.run_executable(v,
project_info,
1,
False,
write_di=False)
sys.exit(0)
verbosity = project_info['GLOBAL']['verbosity']
climo_dir = project_info['GLOBAL']['climo_dir']
exit_on_warning = project_info['GLOBAL'].get('exit_on_warning', False)
# Additional entries to 'project_info'. The 'project_info' construct
# is one way by which Python passes on information to the NCL-routines.
project_info['RUNTIME'] = {}
# Input xml path/file
project_info['RUNTIME']['xml'] = input_xml_full_path
input_xml_file = os.path.basename(input_xml_full_path)
project_info['RUNTIME']['xml_name'] = input_xml_file
# Master references-acknowledgements file (hard coded)
in_refs = os.path.join(os.getcwd(), 'doc/MASTER_authors-refs-acknow.txt')
project_info['RUNTIME']['in_refs'] = in_refs
# Create refs-acknows file in workdir (delete if existing)
wrk_dir = project_info['GLOBAL']['wrk_dir']
if not os.path.isdir(wrk_dir):
os.mkdir(wrk_dir)
# Prepare writing of references/acknowledgementes to file
refs_acknows_file = str.replace(input_xml_file, "namelist_", "refs-acknows_")
refs_acknows_file = refs_acknows_file.split(os.extsep)[0] + ".log"
out_refs = os.path.join(wrk_dir, refs_acknows_file)
if (os.path.isfile(out_refs)):
os.remove(out_refs)
f = open(out_refs, "w")
f.close()
project_info['RUNTIME']['out_refs'] = out_refs
# Current working directory
project_info['RUNTIME']['cwd'] = os.getcwd()
# Summary to std-out before starting the loop
timestamp1 = datetime.datetime.now()
timestamp_format = "%Y-%m-%d -- %H:%M:%S"
print_header(project_info, options.reformat)
info("Starting the Earth System Model Evaluation Tool v" + version + " at time: "
+ timestamp1.strftime(timestamp_format) + "...", verbosity, 1)
# Load ESGF config info (if specified in namelist)
print project_info['ESGF']
if 'ESGF' in project_info and 'config_file' in project_info['ESGF']:
esgf_config_file = project_info['ESGF']['config_file']
if os.path.isfile(esgf_config_file):
info("Loading ESGF config file", verbosity, 2)
esgf_config_handler = xml_parsers.ESGFConfigHandler()
parser = xml.sax.make_parser()
parser.setContentHandler(esgf_config_handler)
parser.parse(esgf_config_file)
esgf_config = esgf_config_handler.current_tag.config
esgf_config.config_file_name = esgf_config_file
info("ESGF config file loaded", verbosity, 2)
# Summary of ESGF config info (if exists) to std-out
info('', verbosity, 3)
info('Summary of ESGF config information:',\
verbosity, 3)
msg = str(esgf_config)
for msg_line in msg.split('\n'):
info(msg_line, verbosity, 3)
info("", verbosity, 3)
# Perform quality check on ESGF config
projects.ESGF.quality_check(esgf_config)
info("ESGF config file passed quality check.", verbosity, 2)
# Store ESGF config in project_info
project_info['ESGF']['config'] = esgf_config
# Also, add fullpath of namelist file to
# ESGF section of project info, so it can be
# included in report/console output
project_info['ESGF']['namelist_fullpath']\
= input_xml_full_path
else:
msg = "Cannot find ESGF config file '%s'" % esgf_config_file
raise IOError(msg)
# Loop over all diagnostics defined in project_info and
# create/prepare netCDF files for each variable
for currDiag in project_info['DIAGNOSTICS']:
# Are the requested variables derived from other, more basic, variables?
requested_vars = currDiag.get_variables_list()
# Update currDiag-specific models
project_info['MODELS'] = projects.remove_diag_specific_models(
project_info['MODELS'])
diag_specific_models = currDiag.get_diag_models()
projects.add_model(project_info, diag_specific_models)
# Prepare/reformat model data for each model
for model in project_info['MODELS']:
currProject = getattr(vars()['projects'], model.split_entries()[0])()
model_name = currProject.get_model_name(model)
project_name = currProject.get_project_name(model)
info("", verbosity, 1)
info("MODEL = " + model_name + " (" + project_name + ")", verbosity, 1)
# variables needed for target variable, according to variable_defs
variable_defs_base_vars = currDiag.add_base_vars_fields(requested_vars, model)
# if not all variable_defs_base_vars are available, try to fetch
# the target variable directly (relevant for derived variables)
base_vars = currDiag.select_base_vars(variable_defs_base_vars,
model,
currProject,
project_info)
# process base variables
for base_var in base_vars:
if currDiag.id_is_explicitly_excluded(base_var, model):
continue
info("VARIABLE = " + base_var.var + " (" + base_var.fld + ")",
verbosity, 1)
# Rewrite netcdf to expected input format.
info("Calling cmor_reformat.py to check/reformat model data",
verbosity, 2)
reformat.cmor_reformat(currProject, project_info, base_var, model)
variables = currDiag.get_variables()
field_types = currDiag.get_field_types()
project_info['RUNTIME']['currDiag'] = currDiag
for derived_var, derived_field in zip(variables, field_types):
project_info['RUNTIME']['derived_var'] = derived_var
project_info['RUNTIME']['derived_field_type'] = derived_field
executable = "./interface_scripts/derive_var.ncl"
info("", verbosity, required_verbosity=1)
info("Calling " + executable + " for '" + derived_var + "'",
verbosity, required_verbosity=1)
projects.run_executable(executable, project_info, verbosity,
exit_on_warning)
project_info['RUNTIME']['derived_var'] = "Undefined"
executable = "./diag_scripts/" + currDiag.get_diag_script()
configfile = currDiag.get_diag_script_cfg()
info("", verbosity, required_verbosity=1)
info("Running diag_script: " + executable, verbosity, required_verbosity=1)
info("with configuration file: " + configfile, verbosity,
required_verbosity=1)
projects.run_executable(executable,
project_info,
verbosity,
exit_on_warning,
launcher_arguments=currDiag.get_launcher_arguments())
# delete environment variable
del(os.environ['0_ESMValTool_version'])
#End time timing
timestamp2 = datetime.datetime.now()
info("", verbosity, 1)
info("Ending the Earth System Model Evaluation Tool v" + version + " at time: "
+ timestamp2.strftime(timestamp_format), verbosity, 1)
info("Time for running namelist was: " + str(timestamp2 - timestamp1), verbosity, 1)
# Remind the user about reference/acknowledgement file
info("", verbosity, 1)
info("For the required references/acknowledgements of these diagnostics see: ",
verbosity, 1)
info(out_refs, verbosity, 1)