oceanval 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oceanval/__init__.py +1033 -0
- oceanval/chunkers.py +70 -0
- oceanval/data/.trackers/nctoolkit_rwi_eseqyqyonctoolkit +0 -0
- oceanval/data/001_methods.ipynb +117 -0
- oceanval/data/TM_WORLD_BORDERS-0.3.dbf +0 -0
- oceanval/data/TM_WORLD_BORDERS-0.3.prj +1 -0
- oceanval/data/TM_WORLD_BORDERS-0.3.shp +0 -0
- oceanval/data/TM_WORLD_BORDERS-0.3.shx +0 -0
- oceanval/data/_config.yml +14 -0
- oceanval/data/_toc.yml +4 -0
- oceanval/data/chunk_bias.py +62 -0
- oceanval/data/chunk_clim.py +164 -0
- oceanval/data/chunk_empty.py +1 -0
- oceanval/data/chunk_end.py +11 -0
- oceanval/data/chunk_globals.py +4 -0
- oceanval/data/chunk_point.py +897 -0
- oceanval/data/chunk_results.py +38 -0
- oceanval/data/chunk_seasonal.py +723 -0
- oceanval/data/chunk_start.py +73 -0
- oceanval/data/comparison_bias.ipynb +537 -0
- oceanval/data/comparison_point.ipynb +236 -0
- oceanval/data/comparison_regional.ipynb +362 -0
- oceanval/data/comparison_seasonal.ipynb +341 -0
- oceanval/data/comparison_spatial.ipynb +271 -0
- oceanval/data/global_subdomains.nc +0 -0
- oceanval/data/gridded_template.ipynb +1389 -0
- oceanval/data/intro.md +9 -0
- oceanval/data/intro_compare_simulations.md +10 -0
- oceanval/data/nwes_subdomains.nc +0 -0
- oceanval/data/pml_logo.jpg +0 -0
- oceanval/data/point_template.ipynb +443 -0
- oceanval/data/requirements.txt +1 -0
- oceanval/data/summary.ipynb +909 -0
- oceanval/fixers.py +66 -0
- oceanval/fvcom.py +264 -0
- oceanval/gridded.py +726 -0
- oceanval/matchall.py +1683 -0
- oceanval/parsers.py +878 -0
- oceanval/session.py +7 -0
- oceanval/tidiers.py +207 -0
- oceanval/utils.py +138 -0
- oceanval-0.1.0.dist-info/METADATA +72 -0
- oceanval-0.1.0.dist-info/RECORD +45 -0
- oceanval-0.1.0.dist-info/WHEEL +5 -0
- oceanval-0.1.0.dist-info/top_level.txt +1 -0
oceanval/__init__.py
ADDED
|
@@ -0,0 +1,1033 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import shutil
|
|
3
|
+
import glob
|
|
4
|
+
import subprocess
|
|
5
|
+
import warnings
|
|
6
|
+
import nctoolkit as nc
|
|
7
|
+
nc.session_info["stamp"] = nc.session_info["stamp"] + "_ecoval_output_"
|
|
8
|
+
import copy
|
|
9
|
+
from oceanval.matchall import matchup
|
|
10
|
+
import dill
|
|
11
|
+
#from oceanval.fixers import tidy_name
|
|
12
|
+
from oceanval.session import session_info
|
|
13
|
+
import webbrowser
|
|
14
|
+
from oceanval.chunkers import add_chunks
|
|
15
|
+
import os
|
|
16
|
+
import re
|
|
17
|
+
from oceanval.fvcom import fvcom_preprocess
|
|
18
|
+
import importlib
|
|
19
|
+
|
|
20
|
+
from oceanval.parsers import Validator, definitions
|
|
21
|
+
|
|
22
|
+
def reset():
|
|
23
|
+
# add docstring
|
|
24
|
+
"""
|
|
25
|
+
Reset the matchup definitions to their default state.
|
|
26
|
+
This function resets the matchup definitions used in oceanval to their default state.
|
|
27
|
+
"""
|
|
28
|
+
definitions.reset()
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
notebook_dict = dict()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
add_point_comparison = definitions.add_point_comparison
|
|
35
|
+
add_gridded_comparison = definitions.add_gridded_comparison
|
|
36
|
+
# add_gridded_comparison_2 = definitions.add_gridded_comparison_2
|
|
37
|
+
|
|
38
|
+
# loop through the keys and make sure all attributes are set
|
|
39
|
+
#for key in definitions.keys:
|
|
40
|
+
for key in session_info["keys"]:
|
|
41
|
+
try:
|
|
42
|
+
x = definitions[key].gridded
|
|
43
|
+
except AttributeError:
|
|
44
|
+
raise AttributeError(f"Variable '{key}' is missing 'gridded' attribute")
|
|
45
|
+
try:
|
|
46
|
+
x = definitions[key].point
|
|
47
|
+
except AttributeError:
|
|
48
|
+
raise AttributeError(f"Variable '{key}' is missing 'point' attribute")
|
|
49
|
+
try:
|
|
50
|
+
x = definitions[key].sources
|
|
51
|
+
except AttributeError:
|
|
52
|
+
raise AttributeError(f"Variable '{key}' is missing 'source' attribute")
|
|
53
|
+
try:
|
|
54
|
+
x = definitions[key].short_name
|
|
55
|
+
except AttributeError:
|
|
56
|
+
raise AttributeError(f"Variable '{key}' is missing 'short_name' attribute")
|
|
57
|
+
try:
|
|
58
|
+
x = definitions[key].long_name
|
|
59
|
+
except AttributeError:
|
|
60
|
+
raise AttributeError(f"Variable '{key}' is missing 'long_name' attribute")
|
|
61
|
+
# add a test to make sure definitions is complete
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def fix_toc(concise = True, data_dir = None, out_dir = None):
|
|
65
|
+
short_titles = dill.load(open(f"{data_dir}/oceanval_matchups/short_titles.pkl", "rb"))
|
|
66
|
+
paths = glob.glob(f"{out_dir}/oceanval_report/notebooks/*.ipynb")
|
|
67
|
+
variables = dill.load(open(f"{data_dir}/oceanval_matchups/variables_matched.pkl", "rb"))
|
|
68
|
+
variables.sort()
|
|
69
|
+
|
|
70
|
+
vv_dict = dict()
|
|
71
|
+
for vv in variables:
|
|
72
|
+
vv_paths = [os.path.basename(x) for x in paths if f"_{vv}.ip" in x]
|
|
73
|
+
if len(vv_paths) > 0:
|
|
74
|
+
vv_dict[vv] = vv_paths
|
|
75
|
+
# get summary docs
|
|
76
|
+
ss_paths = [os.path.basename(x) for x in paths if "summary" in x]
|
|
77
|
+
|
|
78
|
+
out = f"{out_dir}/oceanval_report/_toc.yml"
|
|
79
|
+
|
|
80
|
+
# write line by line to out
|
|
81
|
+
i_chapter = 1
|
|
82
|
+
with open(out, "w") as f:
|
|
83
|
+
# "format: jb-book"
|
|
84
|
+
x = f.write("format: jb-book\n")
|
|
85
|
+
x = f.write("root: intro\n")
|
|
86
|
+
x = f.write("parts:\n")
|
|
87
|
+
x = f.write(f"- caption: Introduction\n")
|
|
88
|
+
x = f.write(" chapters:\n")
|
|
89
|
+
x = f.write(f" - file: notebooks/001_methods.ipynb\n")
|
|
90
|
+
|
|
91
|
+
# open notebook and replace book_chapter with i_chapter
|
|
92
|
+
|
|
93
|
+
# open notebook and replace book_chapter with i_chapter
|
|
94
|
+
with open(f"{out_dir}/oceanval_report/notebooks/001_methods.ipynb", "r") as file:
|
|
95
|
+
filedata = file.read()
|
|
96
|
+
|
|
97
|
+
# Replace the target string
|
|
98
|
+
filedata = filedata.replace("book_chapter", str(i_chapter))
|
|
99
|
+
|
|
100
|
+
with open(f"{out_dir}/oceanval_report/notebooks/001_methods.ipynb", "w") as file:
|
|
101
|
+
file.write(filedata)
|
|
102
|
+
i_chapter += 1
|
|
103
|
+
|
|
104
|
+
x = f.write(f"- caption: Summaries\n")
|
|
105
|
+
x = f.write(" chapters:\n")
|
|
106
|
+
for ff in ss_paths:
|
|
107
|
+
x = f.write(f" - file: notebooks/{ff}\n")
|
|
108
|
+
# open notebook and replace book_chapter with i_chapter
|
|
109
|
+
with open(f"{out_dir}/oceanval_report/notebooks/{ff}", "r") as file:
|
|
110
|
+
filedata = file.read()
|
|
111
|
+
|
|
112
|
+
filedata = filedata.replace("book_chapter", str(i_chapter))
|
|
113
|
+
|
|
114
|
+
# Replace the target string
|
|
115
|
+
# Write the file out again
|
|
116
|
+
with open(f"{out_dir}/oceanval_report/notebooks/{ff}", "w") as file:
|
|
117
|
+
file.write(filedata)
|
|
118
|
+
i_chapter += 1
|
|
119
|
+
|
|
120
|
+
# loop over variables in each vv_dict
|
|
121
|
+
# value is the file in the chapter section
|
|
122
|
+
# key is the variable name, so is the section
|
|
123
|
+
for vv in vv_dict.keys():
|
|
124
|
+
# capitalize if not ph
|
|
125
|
+
vv_out = short_titles[vv]
|
|
126
|
+
|
|
127
|
+
x = f.write(f"- caption: {vv_out}\n")
|
|
128
|
+
x = f.write(" chapters:\n")
|
|
129
|
+
for ff in vv_dict[vv]:
|
|
130
|
+
x = f.write(f" - file: notebooks/{ff}\n")
|
|
131
|
+
|
|
132
|
+
# open notebook and replace book_chapter with i_chapter
|
|
133
|
+
with open(f"{out_dir}/oceanval_report/notebooks/{ff}", "r") as file:
|
|
134
|
+
filedata = file.read()
|
|
135
|
+
|
|
136
|
+
# Replace the target string
|
|
137
|
+
filedata = filedata.replace("book_chapter", str(i_chapter))
|
|
138
|
+
|
|
139
|
+
# Write the file out again
|
|
140
|
+
|
|
141
|
+
with open(f"{out_dir}/oceanval_report/notebooks/{ff}", "w") as file:
|
|
142
|
+
file.write(filedata)
|
|
143
|
+
i_chapter += 1
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def fix_toc_comparison():
|
|
148
|
+
book_dir = "oceanval_comparison"
|
|
149
|
+
|
|
150
|
+
out = f"{book_dir}/compare/_toc.yml"
|
|
151
|
+
# write line by line to out
|
|
152
|
+
with open(out, "w") as f:
|
|
153
|
+
# "format: jb-book"
|
|
154
|
+
x = f.write("format: jb-book\n")
|
|
155
|
+
x = f.write("root: intro\n")
|
|
156
|
+
x = f.write("parts:\n")
|
|
157
|
+
x = f.write(f"- caption: Comparisons with gridded surface observations\n")
|
|
158
|
+
x = f.write(" chapters:\n")
|
|
159
|
+
x = f.write(f" - file: notebooks/comparison_bias.ipynb\n")
|
|
160
|
+
x = f.write(f" - file: notebooks/comparison_spatial.ipynb\n")
|
|
161
|
+
x = f.write(f" - file: notebooks/comparison_seasonal.ipynb\n")
|
|
162
|
+
x = f.write(f" - file: notebooks/comparison_regional.ipynb\n")
|
|
163
|
+
x = f.write(f"- caption: Comparisons with point observations\n")
|
|
164
|
+
x = f.write(" chapters:\n")
|
|
165
|
+
x = f.write(f" - file: notebooks/comparison_point_surface.ipynb\n")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def validate(
|
|
171
|
+
lon_lim=None,
|
|
172
|
+
lat_lim=None,
|
|
173
|
+
concise = True,
|
|
174
|
+
variables="all",
|
|
175
|
+
fixed_scale = False,
|
|
176
|
+
region = None,
|
|
177
|
+
data_dir = ".",
|
|
178
|
+
out_dir = ".",
|
|
179
|
+
test=False,
|
|
180
|
+
):
|
|
181
|
+
# docstring
|
|
182
|
+
"""
|
|
183
|
+
Run the model evaluation for all of the available datasets, and generate a validation report.
|
|
184
|
+
|
|
185
|
+
Parameters
|
|
186
|
+
----------
|
|
187
|
+
lon_lim : list or None
|
|
188
|
+
The longitude limits for the validation. Default is None
|
|
189
|
+
lat_lim : list or None
|
|
190
|
+
The latitude limits for the validation. Default is None
|
|
191
|
+
variables : str or list
|
|
192
|
+
The variables to run the model evaluation for. Default is "all"
|
|
193
|
+
fixed_scale : bool
|
|
194
|
+
Whether to use a fixed scale for the seasonal plots. Default is False. If True, the minimum and maximum values are capped to cover the 2nd and 98th percentiles of both model and observations.
|
|
195
|
+
region : str or None
|
|
196
|
+
The region being validated. Must be either "nwes" (northwest European Shelf) or "global". Default is None.
|
|
197
|
+
test : bool
|
|
198
|
+
Default is False. Ignore, unless you are testing oceanval.
|
|
199
|
+
|
|
200
|
+
Returns
|
|
201
|
+
-------
|
|
202
|
+
None
|
|
203
|
+
"""
|
|
204
|
+
# convert data_dir to absolute path
|
|
205
|
+
data_dir = os.path.expanduser(data_dir)
|
|
206
|
+
data_dir = os.path.abspath(data_dir)
|
|
207
|
+
# regioncan only be nwes or global
|
|
208
|
+
if region is not None:
|
|
209
|
+
if region not in ["nwes", "global"]:
|
|
210
|
+
raise ValueError("region must be either 'nwes' or 'global'")
|
|
211
|
+
# ensure proper handling of ~
|
|
212
|
+
out_dir = os.path.expanduser(out_dir)
|
|
213
|
+
out_dir = os.path.abspath(out_dir)
|
|
214
|
+
|
|
215
|
+
book_dir = os.path.join(out_dir, "oceanval_report")
|
|
216
|
+
# if it doesn't exist, create it
|
|
217
|
+
if not os.path.exists(out_dir):
|
|
218
|
+
os.makedirs(out_dir)
|
|
219
|
+
# if lon_lim is not None, make sure it's a list
|
|
220
|
+
if lon_lim is not None:
|
|
221
|
+
if isinstance(lon_lim, list) == False:
|
|
222
|
+
raise ValueError("lon_lim must be a list")
|
|
223
|
+
else:
|
|
224
|
+
if len(lon_lim) != 2:
|
|
225
|
+
raise ValueError("lon_lim must be a list of length 2")
|
|
226
|
+
if lat_lim is not None:
|
|
227
|
+
if isinstance(lat_lim, list) == False:
|
|
228
|
+
raise ValueError("lat_lim must be a list")
|
|
229
|
+
else:
|
|
230
|
+
if len(lat_lim) != 2:
|
|
231
|
+
raise ValueError("lat_lim must be a list of length 2")
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
path_df = []
|
|
235
|
+
|
|
236
|
+
fast_plot = False
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
empty = True
|
|
240
|
+
|
|
241
|
+
# book directory is book, book1, book2, book10 etc.
|
|
242
|
+
|
|
243
|
+
# create a new name if one already exists
|
|
244
|
+
i = 0
|
|
245
|
+
|
|
246
|
+
if os.path.exists(book_dir):
|
|
247
|
+
# get user input to decide if it should be removed
|
|
248
|
+
while True:
|
|
249
|
+
files = glob.glob(f"{book_dir}/**/**/**", recursive=True)
|
|
250
|
+
# list all files in book, recursively
|
|
251
|
+
for ff in files:
|
|
252
|
+
if ff.startswith(f"{book_dir}/"):
|
|
253
|
+
try:
|
|
254
|
+
os.remove(ff)
|
|
255
|
+
except:
|
|
256
|
+
pass
|
|
257
|
+
files = glob.glob(f"{book_dir}/**/**/**", recursive=True)
|
|
258
|
+
# only list files
|
|
259
|
+
files = [x for x in files if os.path.isfile(x)]
|
|
260
|
+
if len(files) == 0:
|
|
261
|
+
break
|
|
262
|
+
|
|
263
|
+
# remove the results directory
|
|
264
|
+
x_path = "oceanval_results"
|
|
265
|
+
if os.path.exists(x_path):
|
|
266
|
+
if x_path == "oceanval_results":
|
|
267
|
+
shutil.rmtree(x_path)
|
|
268
|
+
|
|
269
|
+
if variables != "all":
|
|
270
|
+
if isinstance(variables, str):
|
|
271
|
+
variables = [variables]
|
|
272
|
+
|
|
273
|
+
if empty:
|
|
274
|
+
from shutil import copyfile
|
|
275
|
+
|
|
276
|
+
if not os.path.exists(book_dir):
|
|
277
|
+
os.mkdir(book_dir)
|
|
278
|
+
if not os.path.exists(f"{book_dir}/notebooks"):
|
|
279
|
+
os.mkdir(f"{book_dir}/notebooks")
|
|
280
|
+
|
|
281
|
+
data_path = importlib.resources.files(__name__).joinpath("data/001_methods.ipynb")
|
|
282
|
+
if not os.path.exists(f"{book_dir}/notebooks/001_methods.ipynb"):
|
|
283
|
+
copyfile(data_path, f"{book_dir}/notebooks/001_methods.ipynb")
|
|
284
|
+
# open this file and replace model_name with model
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
data_path = importlib.resources.files(__name__).joinpath("data/_toc.yml")
|
|
288
|
+
|
|
289
|
+
out = f"{book_dir}/" + os.path.basename(data_path)
|
|
290
|
+
copyfile(data_path, out)
|
|
291
|
+
|
|
292
|
+
data_path = importlib.resources.files(__name__).joinpath("data/requirements.txt")
|
|
293
|
+
out = f"{book_dir}/" + os.path.basename(data_path)
|
|
294
|
+
copyfile(data_path, out)
|
|
295
|
+
|
|
296
|
+
data_path = importlib.resources.files(__name__).joinpath("data/intro.md")
|
|
297
|
+
out = f"{book_dir}/" + os.path.basename(data_path)
|
|
298
|
+
copyfile(data_path, out)
|
|
299
|
+
|
|
300
|
+
# copy config
|
|
301
|
+
|
|
302
|
+
data_path = importlib.resources.files(__name__).joinpath("data/_config.yml")
|
|
303
|
+
out = f"{book_dir}/" + os.path.basename(data_path)
|
|
304
|
+
|
|
305
|
+
with open(data_path, "r") as file:
|
|
306
|
+
filedata = file.read()
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
# Write the file out again
|
|
310
|
+
with open(out, "w") as file:
|
|
311
|
+
file.write(filedata)
|
|
312
|
+
|
|
313
|
+
# copyfile(data_path, out)
|
|
314
|
+
|
|
315
|
+
path_df = []
|
|
316
|
+
|
|
317
|
+
# loop through the point matchups and generate notebooks
|
|
318
|
+
|
|
319
|
+
point_paths = glob.glob(f"{data_dir}/oceanval_matchups/point/**/**/**/**.csv")
|
|
320
|
+
point_paths = [x for x in point_paths if "unit" not in os.path.basename(x)]
|
|
321
|
+
# loop through the paths
|
|
322
|
+
for pp in point_paths:
|
|
323
|
+
ff_def = pp.replace(".csv", "_definitions.pkl")
|
|
324
|
+
definitions = dill.load(open(ff_def, "rb"))
|
|
325
|
+
vv = os.path.basename(pp).split("_")[2].replace(".csv", "")
|
|
326
|
+
if variables != "all":
|
|
327
|
+
if True:
|
|
328
|
+
if vv not in variables:
|
|
329
|
+
continue
|
|
330
|
+
source = os.path.basename(pp).split("_")[0]
|
|
331
|
+
variable = vv
|
|
332
|
+
layer = os.path.basename(pp).split("_")[1].replace(".csv", "")
|
|
333
|
+
Variable = definitions[variable].short_name
|
|
334
|
+
|
|
335
|
+
vv_file = pp
|
|
336
|
+
vv_file_find = pp.replace("../../", "")
|
|
337
|
+
|
|
338
|
+
if os.path.exists(vv_file_find):
|
|
339
|
+
if (
|
|
340
|
+
len(
|
|
341
|
+
glob.glob(
|
|
342
|
+
f"{book_dir}/notebooks/*point_{layer}_{variable}.ipynb"
|
|
343
|
+
)
|
|
344
|
+
)
|
|
345
|
+
== 0
|
|
346
|
+
):
|
|
347
|
+
file1 = importlib.resources.files(__name__).joinpath("data/point_template.ipynb")
|
|
348
|
+
with open(file1, "r") as file:
|
|
349
|
+
filedata = file.read()
|
|
350
|
+
|
|
351
|
+
if layer in [ "all", "surface"]:
|
|
352
|
+
filedata = filedata.replace(
|
|
353
|
+
"chunk_point_surface", "chunk_point"
|
|
354
|
+
)
|
|
355
|
+
else:
|
|
356
|
+
filedata = filedata.replace("chunk_point_surface", "")
|
|
357
|
+
if layer in ["bottom", "all"]:
|
|
358
|
+
if vv.lower() not in ["pco2"]:
|
|
359
|
+
filedata = filedata.replace(
|
|
360
|
+
"chunk_point_bottom", "chunk_point"
|
|
361
|
+
)
|
|
362
|
+
else:
|
|
363
|
+
filedata = filedata.replace("chunk_point_bottom", "")
|
|
364
|
+
else:
|
|
365
|
+
filedata = filedata.replace("chunk_point_bottom", "")
|
|
366
|
+
|
|
367
|
+
# Replace the target string
|
|
368
|
+
out = f"{book_dir}/notebooks/{source}_{layer}_{variable}.ipynb"
|
|
369
|
+
filedata = filedata.replace("point_variable", variable)
|
|
370
|
+
n_levels = definitions[variable].n_levels
|
|
371
|
+
if layer != "all":
|
|
372
|
+
if n_levels > 1:
|
|
373
|
+
filedata = filedata.replace(
|
|
374
|
+
"Validation of point_layer", f"Validation of {layer}"
|
|
375
|
+
)
|
|
376
|
+
else:
|
|
377
|
+
filedata = filedata.replace(
|
|
378
|
+
"Validation of point_layer", f"Validation of "
|
|
379
|
+
)
|
|
380
|
+
else:
|
|
381
|
+
filedata = filedata.replace(
|
|
382
|
+
"Validation of point_layer", f"Validation of "
|
|
383
|
+
)
|
|
384
|
+
|
|
385
|
+
filedata = filedata.replace("point_layer", layer)
|
|
386
|
+
filedata = filedata.replace("point_obs_source", source)
|
|
387
|
+
filedata = filedata.replace("template_title", Variable)
|
|
388
|
+
filedata = filedata.replace("data_dir_value", data_dir)
|
|
389
|
+
filedata = filedata.replace("out_dir_value", out_dir)
|
|
390
|
+
|
|
391
|
+
# Write the file out again
|
|
392
|
+
with open(out, "w") as file:
|
|
393
|
+
file.write(filedata)
|
|
394
|
+
|
|
395
|
+
path_df.append(
|
|
396
|
+
pd.DataFrame(
|
|
397
|
+
{
|
|
398
|
+
"variable": [variable],
|
|
399
|
+
"path": out,
|
|
400
|
+
}
|
|
401
|
+
)
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
# Loop through the gridded matchups and generate notebooks
|
|
405
|
+
# identify gridded variables in matched data
|
|
406
|
+
gridded_paths = glob.glob(f"{data_dir}/oceanval_matchups/gridded/**/**.nc")
|
|
407
|
+
|
|
408
|
+
if len(gridded_paths) > 0:
|
|
409
|
+
for vv in [
|
|
410
|
+
os.path.basename(x).split("_")[1].replace(".nc", "")
|
|
411
|
+
for x in gridded_paths
|
|
412
|
+
]:
|
|
413
|
+
for source in [
|
|
414
|
+
os.path.basename(x).split("_")[0]
|
|
415
|
+
for x in glob.glob(f"{data_dir}/oceanval_matchups/gridded/**/**_{vv}_**.nc")
|
|
416
|
+
]:
|
|
417
|
+
|
|
418
|
+
variable = vv
|
|
419
|
+
if variables != "all":
|
|
420
|
+
if vv not in variables:
|
|
421
|
+
continue
|
|
422
|
+
if not os.path.exists(
|
|
423
|
+
f"{book_dir}/notebooks/{source}_{variable}.ipynb"
|
|
424
|
+
):
|
|
425
|
+
ff_def = glob.glob(f"{data_dir}/oceanval_matchups/gridded/{variable}/{source}_*definitions*.pkl")[0]
|
|
426
|
+
definitions = dill.load(open(ff_def, "rb"))
|
|
427
|
+
Variable = definitions[variable].short_name
|
|
428
|
+
ff_nc = glob.glob(f"{data_dir}/oceanval_matchups/gridded/{variable}/{source}_*surface*.nc")[0]
|
|
429
|
+
ds = nc.open_data(ff_nc, checks = False)
|
|
430
|
+
try:
|
|
431
|
+
n_months = len(ds.months)
|
|
432
|
+
except:
|
|
433
|
+
n_months = 12
|
|
434
|
+
seasonal = n_months >= 12
|
|
435
|
+
|
|
436
|
+
file1 = importlib.resources.files(__name__).joinpath("data/gridded_template.ipynb")
|
|
437
|
+
if (
|
|
438
|
+
len(
|
|
439
|
+
glob.glob(
|
|
440
|
+
f"{book_dir}/notebooks/*{source}_{variable}.ipynb"
|
|
441
|
+
)
|
|
442
|
+
)
|
|
443
|
+
== 0
|
|
444
|
+
):
|
|
445
|
+
with open(file1, "r") as file:
|
|
446
|
+
filedata = file.read()
|
|
447
|
+
|
|
448
|
+
# Replace the target string
|
|
449
|
+
filedata = filedata.replace("template_variable", variable)
|
|
450
|
+
filedata = filedata.replace("template_title", Variable)
|
|
451
|
+
filedata = filedata.replace("data_dir_value", data_dir)
|
|
452
|
+
filedata = filedata.replace("source_name", source)
|
|
453
|
+
if region == "nwes":
|
|
454
|
+
filedata = filedata.replace("zonal_height", "6000" )
|
|
455
|
+
else:
|
|
456
|
+
filedata = filedata.replace("zonal_height", "2000" )
|
|
457
|
+
# make every letter a capital
|
|
458
|
+
source_capital = source.upper()
|
|
459
|
+
filedata = filedata.replace("source_title", source_capital)
|
|
460
|
+
if seasonal is False:
|
|
461
|
+
filedata = filedata.replace(
|
|
462
|
+
"chunk_seasonal", ""
|
|
463
|
+
)
|
|
464
|
+
# change sub_regions_value to region
|
|
465
|
+
if region is not None:
|
|
466
|
+
filedata = filedata.replace(
|
|
467
|
+
"sub_regions_value", str(region)
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
# Write the file out again
|
|
471
|
+
with open(
|
|
472
|
+
f"{book_dir}/notebooks/{source}_{variable}.ipynb", "w"
|
|
473
|
+
) as file:
|
|
474
|
+
file.write(filedata)
|
|
475
|
+
|
|
476
|
+
variable = vv
|
|
477
|
+
path_df.append(
|
|
478
|
+
pd.DataFrame(
|
|
479
|
+
{
|
|
480
|
+
"variable": [variable],
|
|
481
|
+
"path": [
|
|
482
|
+
f"{book_dir}/notebooks/{source}_{variable}.ipynb"
|
|
483
|
+
],
|
|
484
|
+
}
|
|
485
|
+
)
|
|
486
|
+
)
|
|
487
|
+
|
|
488
|
+
# need to start by figuring out whether anything has already been run...
|
|
489
|
+
|
|
490
|
+
i = 0
|
|
491
|
+
|
|
492
|
+
for ff in [
|
|
493
|
+
x for x in glob.glob("{book_dir}/notebooks/*.ipynb") if "info" not in x
|
|
494
|
+
]:
|
|
495
|
+
try:
|
|
496
|
+
i_ff = int(os.path.basename(ff).split("_")[0])
|
|
497
|
+
if i_ff > i:
|
|
498
|
+
i = i_ff
|
|
499
|
+
except:
|
|
500
|
+
pass
|
|
501
|
+
|
|
502
|
+
i_orig = i
|
|
503
|
+
|
|
504
|
+
if len(path_df) > 0:
|
|
505
|
+
path_df = pd.concat(path_df)
|
|
506
|
+
path_df = path_df.sort_values("variable").reset_index(drop=True)
|
|
507
|
+
|
|
508
|
+
for i in range(len(path_df)):
|
|
509
|
+
file1 = path_df.path.values[i]
|
|
510
|
+
# pad i with zeros using zfill
|
|
511
|
+
i_pad = str(i + 1).zfill(3)
|
|
512
|
+
new_file = (
|
|
513
|
+
os.path.dirname(file1) + "/" + i_pad + "_" + os.path.basename(file1)
|
|
514
|
+
)
|
|
515
|
+
os.rename(file1, new_file)
|
|
516
|
+
# print(key, value)
|
|
517
|
+
|
|
518
|
+
# copy the summary.ipynb notebook and add i_pad to the name
|
|
519
|
+
|
|
520
|
+
i = i + 2
|
|
521
|
+
i_pad = str(i).zfill(3)
|
|
522
|
+
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
file1 = importlib.resources.files(__name__).joinpath("data/summary.ipynb")
|
|
526
|
+
if len(glob.glob(f"{book_dir}/notebooks/*summary.ipynb")) == 0:
|
|
527
|
+
copyfile(file1, f"{book_dir}/notebooks/{i_pad}_summary.ipynb")
|
|
528
|
+
else:
|
|
529
|
+
if i > (i_orig + 1):
|
|
530
|
+
initial = glob.glob(f"{book_dir}/notebooks/*summary.ipynb")[0]
|
|
531
|
+
copyfile(initial, f"{book_dir}/notebooks/{i_pad}_summary.ipynb")
|
|
532
|
+
i += 1
|
|
533
|
+
|
|
534
|
+
# change domain_title to "Full domain"
|
|
535
|
+
|
|
536
|
+
with open(f"{book_dir}/notebooks/{i_pad}_summary.ipynb", "r") as file:
|
|
537
|
+
filedata = file.read()
|
|
538
|
+
|
|
539
|
+
# Replace the target string
|
|
540
|
+
filedata = filedata.replace("domain_title", "Full domain")
|
|
541
|
+
filedata = filedata.replace("data_dir_value", data_dir)
|
|
542
|
+
filedata = filedata.replace("out_dir_value", out_dir)
|
|
543
|
+
|
|
544
|
+
# Write the file out again
|
|
545
|
+
with open(f"{book_dir}/notebooks/{i_pad}_summary.ipynb", "w") as file:
|
|
546
|
+
file.write(filedata)
|
|
547
|
+
|
|
548
|
+
# pair the notebooks using jupyter text
|
|
549
|
+
|
|
550
|
+
os.system(
|
|
551
|
+
f"jupytext --set-formats ipynb,py:percent {book_dir}/notebooks/*.ipynb"
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
# add the chunks
|
|
555
|
+
add_chunks(out_dir)
|
|
556
|
+
|
|
557
|
+
# loop through the notebooks and set r warnings options
|
|
558
|
+
for ff in glob.glob(f"{book_dir}/notebooks/*.py"):
|
|
559
|
+
with open(ff, "r") as file:
|
|
560
|
+
filedata = file.read()
|
|
561
|
+
|
|
562
|
+
# loop through line by line, and rewrite the original file
|
|
563
|
+
lines = filedata.split("\n")
|
|
564
|
+
new_lines = []
|
|
565
|
+
for line in lines:
|
|
566
|
+
if "%%R" in line:
|
|
567
|
+
new_lines.append(line)
|
|
568
|
+
new_lines.append("options(warn=-1)")
|
|
569
|
+
else:
|
|
570
|
+
new_lines.append(line)
|
|
571
|
+
# loop through all lines in lines and replace the_test_status with True
|
|
572
|
+
for i in range(len(new_lines)):
|
|
573
|
+
new_lines[i] = new_lines[i].replace("latexpagebreak", "")
|
|
574
|
+
if "the_test_status" in new_lines[i]:
|
|
575
|
+
if test:
|
|
576
|
+
new_lines[i] = new_lines[i].replace("the_test_status", "True")
|
|
577
|
+
else:
|
|
578
|
+
new_lines[i] = new_lines[i].replace("the_test_status", "False")
|
|
579
|
+
if '"gam"' in new_lines[i]:
|
|
580
|
+
new_lines[i] = new_lines[i].replace('"gam"', '"lm"')
|
|
581
|
+
|
|
582
|
+
new_lines[i] = new_lines[i].replace("the_lon_lim", str(lon_lim))
|
|
583
|
+
new_lines[i] = new_lines[i].replace("the_lat_lim", str(lat_lim))
|
|
584
|
+
new_lines[i] = new_lines[i].replace("fixed_scale_value", str(fixed_scale))
|
|
585
|
+
# replace concice_value with concice
|
|
586
|
+
if "concise_value" in new_lines[i]:
|
|
587
|
+
if concise:
|
|
588
|
+
new_lines[i] = new_lines[i].replace(
|
|
589
|
+
"concise_value", "True"
|
|
590
|
+
)
|
|
591
|
+
else:
|
|
592
|
+
new_lines[i] = new_lines[i].replace("concise_value", "False")
|
|
593
|
+
|
|
594
|
+
# write the new lines to the file
|
|
595
|
+
with open(ff, "w") as file:
|
|
596
|
+
for line in new_lines:
|
|
597
|
+
file.write(line + "\n")
|
|
598
|
+
|
|
599
|
+
# sync the notebooks
|
|
600
|
+
#
|
|
601
|
+
os.system(f"jupytext --sync {book_dir}/notebooks/*.ipynb")
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
# loop through notebooks and change fast_plot_value to fast_plot
|
|
605
|
+
|
|
606
|
+
for ff in glob.glob(f"{book_dir}/notebooks/*.ipynb"):
|
|
607
|
+
with open(ff, "r") as file:
|
|
608
|
+
filedata = file.read()
|
|
609
|
+
|
|
610
|
+
# Replace the target string
|
|
611
|
+
filedata = filedata.replace("fast_plot_value", str(fast_plot))
|
|
612
|
+
filedata = filedata.replace("data_dir_value", data_dir)
|
|
613
|
+
filedata = filedata.replace("out_dir_value", out_dir)
|
|
614
|
+
|
|
615
|
+
# fix linees using the above
|
|
616
|
+
def fix_r_magic(x):
|
|
617
|
+
if "%%R" in x:
|
|
618
|
+
x = re.sub(r" -r\s+\d+", "", x)
|
|
619
|
+
x = x.replace("%%R", "%%R -r 120 ")
|
|
620
|
+
return x
|
|
621
|
+
|
|
622
|
+
# Write the file out again
|
|
623
|
+
with open(ff, "w") as file:
|
|
624
|
+
file.write(filedata)
|
|
625
|
+
|
|
626
|
+
# fix the toc using the function
|
|
627
|
+
|
|
628
|
+
fix_toc(concise = concise, data_dir = data_dir, out_dir = out_dir)
|
|
629
|
+
|
|
630
|
+
for ff in glob.glob(f"{book_dir}/notebooks/*.ipynb"):
|
|
631
|
+
ff_clean = ff.replace(".ipynb", ".py")
|
|
632
|
+
if os.path.exists(ff_clean):
|
|
633
|
+
os.remove(ff_clean)
|
|
634
|
+
|
|
635
|
+
# move pml_logo to book directory
|
|
636
|
+
|
|
637
|
+
shutil.copyfile(
|
|
638
|
+
importlib.resources.files(__name__).joinpath("data/pml_logo.jpg"), f"{book_dir}/pml_logo.jpg"
|
|
639
|
+
)
|
|
640
|
+
|
|
641
|
+
os.system(f"jupyter-book build {book_dir}/")
|
|
642
|
+
|
|
643
|
+
stamps = [
|
|
644
|
+
os.path.basename(x) for x in glob.glob(f"{book_dir}/notebooks/.trackers/*")
|
|
645
|
+
]
|
|
646
|
+
stamps.append("nctoolkit_rwi_uhosarcenctoolkittmp")
|
|
647
|
+
|
|
648
|
+
delete = []
|
|
649
|
+
for x in stamps:
|
|
650
|
+
delete += glob.glob("/tmp/*" + x + "*")
|
|
651
|
+
|
|
652
|
+
for ff in delete:
|
|
653
|
+
if os.path.exists(ff):
|
|
654
|
+
if "nctoolkit" in x:
|
|
655
|
+
os.remove(ff)
|
|
656
|
+
|
|
657
|
+
out_ff = f"{book_dir}/_build/html/index.html"
|
|
658
|
+
|
|
659
|
+
# create a symlink to the html file
|
|
660
|
+
if os.path.exists(f"{out_dir}/oceanval_report.html"):
|
|
661
|
+
os.remove(f"{out_dir}/oceanval_report.html")
|
|
662
|
+
os.symlink(f"{book_dir}/_build/html/index.html", f"{out_dir}/oceanval_report.html")
|
|
663
|
+
webbrowser.open(
|
|
664
|
+
"file://" + os.path.abspath(f"{book_dir}/_build/html/index.html")
|
|
665
|
+
)
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
def rebuild():
|
|
669
|
+
"""
|
|
670
|
+
Rebuild the validation report after modifying notebooks.
|
|
671
|
+
Use this if you have modified the notebooks generated and want to create a new validation report.
|
|
672
|
+
|
|
673
|
+
Parameters
|
|
674
|
+
----------
|
|
675
|
+
build : str
|
|
676
|
+
The type of the existing build. Default is None. Options are "html" or "pdf"
|
|
677
|
+
"""
|
|
678
|
+
# add a deprecation notice
|
|
679
|
+
|
|
680
|
+
os.system(f"jupyter-book build oceanval_report/")
|
|
681
|
+
|
|
682
|
+
webbrowser.open(
|
|
683
|
+
"file://" + os.path.abspath(f"oceanval_report/_build/html/index.html")
|
|
684
|
+
)
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
try:
|
|
690
|
+
from importlib.metadata import version as _version
|
|
691
|
+
except ImportError:
|
|
692
|
+
from importlib_metadata import version as _version
|
|
693
|
+
|
|
694
|
+
try:
|
|
695
|
+
__version__ = _version("oceanval")
|
|
696
|
+
except Exception:
|
|
697
|
+
__version__ = "999"
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
def compare(model_dict=None):
|
|
701
|
+
"""
|
|
702
|
+
Compare pre-validated simulations.
|
|
703
|
+
This function will compare the validation output from two simulations.
|
|
704
|
+
|
|
705
|
+
Parameters
|
|
706
|
+
----------
|
|
707
|
+
model_dict : dict
|
|
708
|
+
A dictionary of model names and the paths to the validation output. Default is None.
|
|
709
|
+
Example: {"model1": "/path/to/model1", "model2": "/path/to/model2"}
|
|
710
|
+
If the models have different grids, put the model with the smallest grid first.
|
|
711
|
+
|
|
712
|
+
"""
|
|
713
|
+
|
|
714
|
+
for key in model_dict.keys():
|
|
715
|
+
# check that the path exists
|
|
716
|
+
if not os.path.exists(model_dict[key]):
|
|
717
|
+
raise ValueError(f"Path {model_dict[key]} does not exist")
|
|
718
|
+
# convert to an absolute path
|
|
719
|
+
model_dict[key] = os.path.abspath(model_dict[key])
|
|
720
|
+
|
|
721
|
+
if os.path.exists("oceanval_comparison"):
|
|
722
|
+
# get user input to decide if it should be removed
|
|
723
|
+
user_input = input(
|
|
724
|
+
"oceanval_comparison directory already exists. This will be emptied and replaced. Do you want to proceed? (y/n): "
|
|
725
|
+
)
|
|
726
|
+
if user_input.lower() == "y":
|
|
727
|
+
while True:
|
|
728
|
+
files = glob.glob("oceanval_comparison/**/**/**", recursive=True)
|
|
729
|
+
# list all files in oceanval_comparison, recursively
|
|
730
|
+
for ff in files:
|
|
731
|
+
if ff.startswith("oceanval_comparison"):
|
|
732
|
+
try:
|
|
733
|
+
os.remove(ff)
|
|
734
|
+
except:
|
|
735
|
+
pass
|
|
736
|
+
files = glob.glob("oceanval_comparison/**/**/**", recursive=True)
|
|
737
|
+
# only list files
|
|
738
|
+
files = [x for x in files if os.path.isfile(x)]
|
|
739
|
+
if len(files) == 0:
|
|
740
|
+
break
|
|
741
|
+
else:
|
|
742
|
+
print("Exiting")
|
|
743
|
+
return None
|
|
744
|
+
|
|
745
|
+
|
|
746
|
+
if not os.path.exists("oceanval_comparison/compare"):
|
|
747
|
+
# create directory recursively
|
|
748
|
+
os.makedirs("oceanval_comparison/compare")
|
|
749
|
+
|
|
750
|
+
# copy the pml logo
|
|
751
|
+
shutil.copyfile(
|
|
752
|
+
importlib.resources.files(__name__).joinpath("data/pml_logo.jpg"),
|
|
753
|
+
"oceanval_comparison/pml_logo.jpg",
|
|
754
|
+
)
|
|
755
|
+
|
|
756
|
+
# move toc etc to oceanval_comparison/compare
|
|
757
|
+
|
|
758
|
+
data_path = importlib.resources.files(__name__).joinpath("data/_toc.yml")
|
|
759
|
+
|
|
760
|
+
out = "oceanval_comparison/compare/" + os.path.basename(data_path)
|
|
761
|
+
shutil.copyfile(data_path, out)
|
|
762
|
+
|
|
763
|
+
fix_toc_comparison()
|
|
764
|
+
|
|
765
|
+
data_path = importlib.resources.files(__name__).joinpath("data/requirements.txt")
|
|
766
|
+
|
|
767
|
+
out = "oceanval_comparison/compare/" + os.path.basename(data_path)
|
|
768
|
+
|
|
769
|
+
shutil.copyfile(data_path, out)
|
|
770
|
+
|
|
771
|
+
data_path = importlib.resources.files(__name__).joinpath("data/intro.md")
|
|
772
|
+
|
|
773
|
+
out = "oceanval_comparison/compare/" + os.path.basename(data_path)
|
|
774
|
+
|
|
775
|
+
shutil.copyfile(data_path, out)
|
|
776
|
+
|
|
777
|
+
# copy config
|
|
778
|
+
|
|
779
|
+
data_path = importlib.resources.files(__name__).joinpath("data/_config.yml")
|
|
780
|
+
|
|
781
|
+
out = "oceanval_comparison/compare/" + os.path.basename(data_path)
|
|
782
|
+
|
|
783
|
+
shutil.copyfile(data_path, out)
|
|
784
|
+
|
|
785
|
+
# copy the comparison_seasonal notebook
|
|
786
|
+
|
|
787
|
+
# make sure the directory exists
|
|
788
|
+
|
|
789
|
+
if not os.path.exists("oceanval_comparison/compare/notebooks"):
|
|
790
|
+
# create directory recursively
|
|
791
|
+
os.makedirs("oceanval_comparison/compare/notebooks")
|
|
792
|
+
|
|
793
|
+
file1 = importlib.resources.files(__name__).joinpath("data/comparison_seasonal.ipynb")
|
|
794
|
+
if len(glob.glob("oceanval_comparison/compare/notebooks/*comparison_seasonal.ipynb")) == 0:
|
|
795
|
+
shutil.copyfile(file1, "oceanval_comparison/compare/notebooks/comparison_seasonal.ipynb")
|
|
796
|
+
|
|
797
|
+
# copy comparison_overall notebook
|
|
798
|
+
|
|
799
|
+
file1 = importlib.resources.files(__name__).joinpath("data/comparison_overall.ipynb")
|
|
800
|
+
|
|
801
|
+
if len(glob.glob("oceanval_comparison/compare/notebooks/*comparison_overall.ipynb")) == 0:
|
|
802
|
+
shutil.copyfile(file1, "oceanval_comparison/compare/notebooks/comparison_overall.ipynb")
|
|
803
|
+
|
|
804
|
+
model_dict_str = str(model_dict)
|
|
805
|
+
|
|
806
|
+
with open("oceanval_comparison/compare/notebooks/comparison_seasonal.ipynb", "r") as file:
|
|
807
|
+
filedata = file.read()
|
|
808
|
+
|
|
809
|
+
# Replace the target string
|
|
810
|
+
filedata = filedata.replace("model_dict_str", model_dict_str)
|
|
811
|
+
|
|
812
|
+
# Write the file out again
|
|
813
|
+
|
|
814
|
+
with open("oceanval_comparison/compare/notebooks/comparison_seasonal.ipynb", "w") as file:
|
|
815
|
+
file.write(filedata)
|
|
816
|
+
|
|
817
|
+
# now sort out the comparison_spatial notebook
|
|
818
|
+
|
|
819
|
+
file1 = importlib.resources.files(__name__).joinpath("data/comparison_spatial.ipynb")
|
|
820
|
+
if len(glob.glob("oceanval_comparison/compare/notebooks/*comparison_spatial.ipynb")) == 0:
|
|
821
|
+
shutil.copyfile(file1, "oceanval_comparison/compare/notebooks/comparison_spatial.ipynb")
|
|
822
|
+
|
|
823
|
+
model_dict_str = str(model_dict)
|
|
824
|
+
|
|
825
|
+
with open("oceanval_comparison/compare/notebooks/comparison_spatial.ipynb", "r") as file:
|
|
826
|
+
filedata = file.read()
|
|
827
|
+
|
|
828
|
+
# Replace the target string
|
|
829
|
+
filedata = filedata.replace("model_dict_str", model_dict_str)
|
|
830
|
+
|
|
831
|
+
# Write the file out again
|
|
832
|
+
|
|
833
|
+
with open("oceanval_comparison/compare/notebooks/comparison_spatial.ipynb", "w") as file:
|
|
834
|
+
file.write(filedata)
|
|
835
|
+
|
|
836
|
+
# move the regional book
|
|
837
|
+
|
|
838
|
+
file1 = importlib.resources.files(__name__).joinpath("data/comparison_regional.ipynb")
|
|
839
|
+
if len(glob.glob("oceanval_comparison/compare/notebooks/*comparison_regional.ipynb")) == 0:
|
|
840
|
+
shutil.copyfile(file1, "oceanval_comparison/compare/notebooks/comparison_regional.ipynb")
|
|
841
|
+
|
|
842
|
+
model_dict_str = str(model_dict)
|
|
843
|
+
|
|
844
|
+
with open("oceanval_comparison/compare/notebooks/comparison_regional.ipynb", "r") as file:
|
|
845
|
+
filedata = file.read()
|
|
846
|
+
|
|
847
|
+
# Replace the target string
|
|
848
|
+
filedata = filedata.replace("model_dict_str", model_dict_str)
|
|
849
|
+
|
|
850
|
+
# Write the file out again
|
|
851
|
+
|
|
852
|
+
with open("oceanval_comparison/compare/notebooks/comparison_regional.ipynb", "w") as file:
|
|
853
|
+
file.write(filedata)
|
|
854
|
+
|
|
855
|
+
# now to comparison_bias
|
|
856
|
+
|
|
857
|
+
file1 = importlib.resources.files(__name__).joinpath("data/comparison_bias.ipynb")
|
|
858
|
+
|
|
859
|
+
if len(glob.glob("oceanval_comparison/compare/notebooks/*comparison_bias.ipynb")) == 0:
|
|
860
|
+
shutil.copyfile(file1, "oceanval_comparison/compare/notebooks/comparison_bias.ipynb")
|
|
861
|
+
|
|
862
|
+
model_dict_str = str(model_dict)
|
|
863
|
+
|
|
864
|
+
with open("oceanval_comparison/compare/notebooks/comparison_bias.ipynb", "r") as file:
|
|
865
|
+
filedata = file.read()
|
|
866
|
+
|
|
867
|
+
# Replace the target string
|
|
868
|
+
filedata = filedata.replace("model_dict_str", model_dict_str)
|
|
869
|
+
|
|
870
|
+
# Write the file out again
|
|
871
|
+
|
|
872
|
+
with open("oceanval_comparison/compare/notebooks/comparison_bias.ipynb", "w") as file:
|
|
873
|
+
file.write(filedata)
|
|
874
|
+
|
|
875
|
+
# figure out if both simulations have point data
|
|
876
|
+
|
|
877
|
+
i = 0
|
|
878
|
+
|
|
879
|
+
if i == 0:
|
|
880
|
+
for ss in [ "surface"]:
|
|
881
|
+
file1 = importlib.resources.files(__name__).joinpath("data/comparison_point.ipynb")
|
|
882
|
+
|
|
883
|
+
if (
|
|
884
|
+
len(glob.glob(f"oceanval_comparison/compare/notebooks/*comparison_point_{ss}.ipynb"))
|
|
885
|
+
== 0
|
|
886
|
+
):
|
|
887
|
+
shutil.copyfile(
|
|
888
|
+
file1, f"oceanval_comparison/compare/notebooks/comparison_point_{ss}.ipynb"
|
|
889
|
+
)
|
|
890
|
+
|
|
891
|
+
model_dict_str = str(model_dict)
|
|
892
|
+
|
|
893
|
+
with open(
|
|
894
|
+
f"oceanval_comparison/compare/notebooks/comparison_point_{ss}.ipynb", "r"
|
|
895
|
+
) as file:
|
|
896
|
+
filedata = file.read()
|
|
897
|
+
|
|
898
|
+
# Replace the target string
|
|
899
|
+
filedata = filedata.replace("model_dict_str", model_dict_str)
|
|
900
|
+
|
|
901
|
+
# Write the file out again
|
|
902
|
+
|
|
903
|
+
with open(
|
|
904
|
+
f"oceanval_comparison/compare/notebooks/comparison_point_{ss}.ipynb", "w"
|
|
905
|
+
) as file:
|
|
906
|
+
file.write(filedata)
|
|
907
|
+
# replace layer in the notebook with ss
|
|
908
|
+
with open(
|
|
909
|
+
f"oceanval_comparison/compare/notebooks/comparison_point_{ss}.ipynb", "r"
|
|
910
|
+
) as file:
|
|
911
|
+
filedata = file.read()
|
|
912
|
+
|
|
913
|
+
# Replace the target string
|
|
914
|
+
filedata = filedata.replace("layer", ss)
|
|
915
|
+
|
|
916
|
+
# Write the file out again
|
|
917
|
+
|
|
918
|
+
with open(
|
|
919
|
+
f"oceanval_comparison/compare/notebooks/comparison_point_{ss}.ipynb", "w"
|
|
920
|
+
) as file:
|
|
921
|
+
file.write(filedata)
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
# sync the notebooks
|
|
925
|
+
|
|
926
|
+
os.system("jupytext --set-formats ipynb,py:percent oceanval_comparison/compare/notebooks/*.ipynb")
|
|
927
|
+
|
|
928
|
+
add_chunks()
|
|
929
|
+
|
|
930
|
+
# replace the test status in the notebooks
|
|
931
|
+
books = glob.glob("oceanval_comparison/compare/notebooks/*.py")
|
|
932
|
+
for book in books:
|
|
933
|
+
with open(book, "r") as file:
|
|
934
|
+
filedata = file.read()
|
|
935
|
+
|
|
936
|
+
# Replace the target string
|
|
937
|
+
filedata = filedata.replace("the_test_status", "False")
|
|
938
|
+
|
|
939
|
+
# Write the file out again
|
|
940
|
+
with open(book, "w") as file:
|
|
941
|
+
file.write(filedata)
|
|
942
|
+
|
|
943
|
+
# fix the chunks
|
|
944
|
+
os.system("jupytext --sync oceanval_comparison/compare/notebooks/*.ipynb")
|
|
945
|
+
|
|
946
|
+
# loop through notebooks and change fast_plot_value to fast_plot
|
|
947
|
+
|
|
948
|
+
for ff in glob.glob("oceanval_comparison/compare/notebooks/*.ipynb"):
|
|
949
|
+
with open(ff, "r") as file:
|
|
950
|
+
filedata = file.read()
|
|
951
|
+
|
|
952
|
+
# Replace the target string
|
|
953
|
+
filedata = filedata.replace("fast_plot_value", "False")
|
|
954
|
+
|
|
955
|
+
# Write the file out again
|
|
956
|
+
with open(ff, "w") as file:
|
|
957
|
+
file.write(filedata)
|
|
958
|
+
|
|
959
|
+
os.system("jupyter-book build oceanval_comparison/compare/")
|
|
960
|
+
import webbrowser
|
|
961
|
+
|
|
962
|
+
|
|
963
|
+
webbrowser.open("file://" + os.path.abspath("oceanval_comparison/compare/_build/html/index.html"))
|
|
964
|
+
|
|
965
|
+
import platform
|
|
966
|
+
import tempfile
|
|
967
|
+
|
|
968
|
+
|
|
969
|
+
def temp_check():
|
|
970
|
+
"""
|
|
971
|
+
Function to check temp files
|
|
972
|
+
"""
|
|
973
|
+
|
|
974
|
+
if platform.system() == "Linux":
|
|
975
|
+
mylist = [f for f in glob.glob("/tmp/*")]
|
|
976
|
+
mylist = mylist + [f for f in glob.glob("/var/tmp/*")]
|
|
977
|
+
mylist = mylist + [f for f in glob.glob("/usr/tmp/*")]
|
|
978
|
+
mylist = [f for f in mylist if "nctoolkit" in f]
|
|
979
|
+
|
|
980
|
+
mylist = [x for x in mylist if "ecoval_output" in x]
|
|
981
|
+
|
|
982
|
+
session_info["old_files"] = mylist
|
|
983
|
+
|
|
984
|
+
if len(mylist) > 0:
|
|
985
|
+
if len(mylist) == 1:
|
|
986
|
+
print(
|
|
987
|
+
f"{len(mylist)} temporary file was created by oceanval in prior or current "
|
|
988
|
+
f"sessions. Consider running oceanval.deep_clean!"
|
|
989
|
+
)
|
|
990
|
+
else:
|
|
991
|
+
print(
|
|
992
|
+
f"{len(mylist)} temporary files were created by oceanval in prior or current"
|
|
993
|
+
f" sessions. Consider running oceanval.deep_clean!"
|
|
994
|
+
)
|
|
995
|
+
|
|
996
|
+
else:
|
|
997
|
+
temp_folder = tempfile.gettempdir()
|
|
998
|
+
|
|
999
|
+
mylist = [f for f in glob.glob(f"{temp_folder}/*")]
|
|
1000
|
+
mylist = [f for f in mylist if "nctoolkit" in f]
|
|
1001
|
+
mylist = [x for x in mylist if "ecovaloutput" in x]
|
|
1002
|
+
|
|
1003
|
+
if len(mylist) > 0:
|
|
1004
|
+
if len(mylist) == 1:
|
|
1005
|
+
print(
|
|
1006
|
+
f"{len(mylist)} temporary file was created by oceanval in prior or current "
|
|
1007
|
+
f"sessions. Consider running oceanval.deep_clean!"
|
|
1008
|
+
)
|
|
1009
|
+
else:
|
|
1010
|
+
print(
|
|
1011
|
+
f"{len(mylist)} temporary files were created by oceanval in prior or "
|
|
1012
|
+
f"current sessions. Consider running oceanval.deep_clean!"
|
|
1013
|
+
)
|
|
1014
|
+
|
|
1015
|
+
temp_check()
|
|
1016
|
+
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
|
|
1020
|
+
def deep_clean():
|
|
1021
|
+
"""
|
|
1022
|
+
Deep temp file cleaner.
|
|
1023
|
+
Remove all temporary files ever created by oceanval
|
|
1024
|
+
across all previous and current sesions
|
|
1025
|
+
"""
|
|
1026
|
+
|
|
1027
|
+
candidates = session_info["old_files"]
|
|
1028
|
+
|
|
1029
|
+
mylist = [f for f in candidates if "nctoolkit" in f and "ecoval_output" in f]
|
|
1030
|
+
for ff in mylist:
|
|
1031
|
+
if ff in session_info["old_files"]:
|
|
1032
|
+
if "nctoolkit" in ff and "ecoval_output" in ff:
|
|
1033
|
+
os.remove(ff)
|