Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
thopri
PyNEMO
Commits
c8d231d4
Commit
c8d231d4
authored
4 years ago
by
thopri
Browse files
Options
Download
Email Patches
Plain Diff
added reference subset data to output of tide test
parent
79a19a75
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
50 additions
and
28 deletions
+50
-28
pynemo/tests/nemo_tide_test.py
pynemo/tests/nemo_tide_test.py
+50
-28
No files found.
pynemo/tests/nemo_tide_test.py
View file @
c8d231d4
...
...
@@ -4,7 +4,7 @@
Created on Fri May 01 2020
@author: thopri
example usage:
example usage:
(in python console)
from pynemo.tides import nemo_tide_test as tt
tt.main()
...
...
@@ -15,6 +15,9 @@ phase threshold - 10.00 degrees
model resolution - 1/16 degree
model - 'fes'
So for FES the only model currently supported only the location of the BDY file and thresholds (if different from defaults)
need to be provided. For TPXO this would vary based on the resolution e.g. TPXO7.2 is 1/4 and 'tpxo'
The script generates a excel spreadsheet that contains the locations and amplitudes and phases for all HC's
defined in the bdy file that exceed the default or defined the thresholds passed to the main function.
File locations e.g. model reference location etc are all taken from bdy file that is passed to the main function
...
...
@@ -27,7 +30,7 @@ which is then written to a spreadsheet.
Notes:
The script checks the Amplitude and Phase independently, so lat/lons for each are also returned. Each HC is saved to
a separate sheet in the spreadsheet. The name of the spreadsheet contains meta data showing thresholds and reference
model used.
model used.
Units for threshold are meters and degrees.
"""
from
netCDF4
import
Dataset
...
...
@@ -41,7 +44,7 @@ from pynemo import nemo_bdy_setup as setup
logger
=
logging
.
getLogger
(
__name__
)
logging
.
basicConfig
(
filename
=
'nrct.log'
,
level
=
logging
.
INFO
)
# TODO: add TPXO
comparision
functionality currently only uses FES as "truth"
# TODO: add TPXO
read and subset
functionality currently only uses FES as "truth"
def
main
(
bdy_file
=
'inputs/namelist_cmems.bdy'
,
amplitude_threshold
=
0.25
,
phase_threshold
=
10.00
,
model_res
=
1
/
16
,
model
=
'fes'
):
logger
.
info
(
'============================================'
)
...
...
@@ -51,7 +54,7 @@ def main(bdy_file='inputs/namelist_cmems.bdy',amplitude_threshold = 0.25,phase_t
Setup
=
setup
.
Setup
(
bdy_file
)
# default settings file
settings
=
Setup
.
settings
constituents
=
settings
[
'clname'
]
# TODO maybe define
grids
in bdy file? at the moment Z, U and Vs are generated no option for Z only.
# TODO maybe define
Z and/or UV
in bdy file? at the moment Z, U and Vs are generated
with
no option for Z only.
grids
=
[
'Z'
,
'U'
,
'V'
]
if
model
==
'fes'
:
logger
.
info
(
'using FES as reference.......'
)
...
...
@@ -68,25 +71,24 @@ def main(bdy_file='inputs/namelist_cmems.bdy',amplitude_threshold = 0.25,phase_t
# extract PyNEMO data from output files (generate list of lats,lons etc)
pynemo_out
=
extract_PyNEMO_output
(
out_fname
,
grid
)
# subset FES to match PyNEMO list of lat lons
subset
=
subset_
FES
(
pynemo_out
,
fes
)
subset
_fes
=
subset_
reference
(
pynemo_out
,
fes
)
# compare the two lists (or dicts really)
error_log
=
compare_tides
(
pynemo_out
,
subset
,
amplitude_threshold
,
phase_threshold
,
model_res
)
error_log
=
compare_tides
(
pynemo_out
,
subset
_fes
,
amplitude_threshold
,
phase_threshold
,
model_res
)
# return differences above threshold as a Pandas Dataframe and name using HC and Grid
error_log
.
name
=
constituents
[
key
].
strip
(
"',/
\n
"
)
+
grids
[
j
]
# if the dataframe is empty (no exceedance) then discard dataframe and log
# if the dataframe is empty (no exceedance
s
) then discard dataframe and log
the good news
if
error_log
.
empty
==
True
:
logger
.
info
(
'output file does not exceed threshold when compared with reference model..... thats good!'
)
logger
.
info
(
'output file does not exceed threshold when compared with reference model..... thats good!'
)
# if dataframe has values then these exceed the threshold, log and save to excel spreadsheet using dataset
# name e.g. M2Z (based on HC and grid) as name for the sheet
if
error_log
.
empty
==
False
:
logger
.
warning
(
'Exceedance in thesholds detected, check spreadsheet in dst_dir'
)
logger
.
warning
(
'Exceedance in thesholds detected, check spreadsheet in dst_dir'
)
error_log
.
to_excel
(
writer
,
sheet_name
=
error_log
.
name
)
# close writer object and save excel spreadsheet
writer
.
save
()
# code runs here if TPXO is requested as reference this hasn't been written yet so raises exception
elif
model
==
'tpxo'
:
logger
.
info
(
'using TPXO as reference.......'
)
logger
.
exception
(
'not set up to use TPXO yet...... exiting'
)
raise
Exception
(
'Not setup for TPXO use FES instead?'
)
# everything else goes here which shouldn't happen so is raised as an exception
...
...
@@ -119,12 +121,13 @@ def extract_PyNEMO_output(out_fname,grid):
pynemo_out
=
{
'lat'
:
lat
,
'lon'
:
lon
,
'amp'
:
amp
,
'phase'
:
phase
}
return
pynemo_out
# read FES netcdf file, convert lon to -180 to 180, rather than 0-360
# read FES netcdf file, convert lon to -180 to 180, rather than 0-360
it also converts amplitude from CM to M
# return a dict
def
read_fes
(
fes_fname
,
grid
):
fes_tide
=
Dataset
(
fes_fname
)
if
grid
==
'Z'
:
fes_amp
=
np
.
array
(
fes_tide
.
variables
[
'amplitude'
][:])
fes_amp
=
fes_amp
/
100
fes_phase
=
np
.
array
(
fes_tide
.
variables
[
'phase'
][:])
fes_phase
[
fes_phase
>
180.0
]
=
fes_phase
[
fes_phase
>
180.0
]
-
360.0
if
grid
!=
'Z'
:
...
...
@@ -141,70 +144,89 @@ def read_fes(fes_fname,grid):
# subset FES dict from read_FES, this uses find_nearest to find nearest FES point using PyNEMO dict from extract_PyNEMO
# It also converts FES amplitude from cm to m.
def
subset_
FES
(
pynemo_out
,
fes
):
def
subset_
reference
(
pynemo_out
,
reference
):
idx_lat
=
np
.
zeros
(
np
.
shape
(
pynemo_out
[
'lat'
]))
for
i
in
range
(
np
.
shape
(
pynemo_out
[
'lat'
])[
1
]):
idx_lat
[
0
,
i
]
=
find_nearest
(
fes
[
'lat'
],
pynemo_out
[
'lat'
][
0
,
i
])
idx_lat
[
0
,
i
]
=
find_nearest
(
reference
[
'lat'
],
pynemo_out
[
'lat'
][
0
,
i
])
idx_lat
=
idx_lat
.
astype
(
np
.
int64
)
idx_lon
=
np
.
zeros
(
np
.
shape
(
pynemo_out
[
'lon'
]))
for
i
in
range
(
np
.
shape
(
pynemo_out
[
'lon'
])[
1
]):
idx_lon
[
0
,
i
]
=
find_nearest
(
fes
[
'lon'
],
pynemo_out
[
'lon'
][
0
,
i
])
idx_lon
[
0
,
i
]
=
find_nearest
(
reference
[
'lon'
],
pynemo_out
[
'lon'
][
0
,
i
])
idx_lon
=
idx_lon
.
astype
(
np
.
int64
)
fes_amp_sub
=
fes
[
'amp'
][
idx_lat
,
idx_lon
]
fes_amp_sub
=
fes_amp_sub
/
100
fes_phase_sub
=
fes
[
'phase'
][
idx_lat
,
idx_lon
]
fes_lat_sub
=
fes
[
'lat'
][
idx_lat
]
fes_lon_sub
=
fes
[
'lon'
][
idx_lon
]
subset
=
{
'lat'
:
fes_lat_sub
,
'lon'
:
fes_lon_sub
,
'amp'
:
fes_amp_sub
,
'phase'
:
fes_phase_sub
}
amp_sub
=
reference
[
'amp'
][
idx_lat
,
idx_lon
]
phase_sub
=
reference
[
'phase'
][
idx_lat
,
idx_lon
]
lat_sub
=
reference
[
'lat'
][
idx_lat
]
lon_sub
=
reference
[
'lon'
][
idx_lon
]
subset
=
{
'lat'
:
lat_sub
,
'lon'
:
lon_sub
,
'amp'
:
amp_sub
,
'phase'
:
phase_sub
}
return
subset
# takes pynemo extract dict, subset fes dict, and the thresholds and model res passed to main function.
# returns a Pandas Dataframe with any PyNEMO values that exceed the nearest FES point by defined threshold
# It also checks lats and lons are within the model reference resolution
# i.e. ensure closest model reference point is used.
def
compare_tides
(
pynemo_out
,
subset
_fes
,
amp_thres
,
phase_thres
,
model_res
):
def
compare_tides
(
pynemo_out
,
subset
,
amp_thres
,
phase_thres
,
model_res
):
# compare lat and lons
diff_lat
=
np
.
abs
(
pynemo_out
[
'lat'
]
-
subset
_fes
[
'lat'
])
diff_lon
=
np
.
abs
(
pynemo_out
[
'lon'
]
-
subset
_fes
[
'lon'
])
diff_lat
=
np
.
abs
(
pynemo_out
[
'lat'
]
-
subset
[
'lat'
])
diff_lon
=
np
.
abs
(
pynemo_out
[
'lon'
]
-
subset
[
'lon'
])
exceed_lat
=
diff_lat
>
model_res
exceed_lon
=
diff_lon
>
model_res
exceed_sum
=
np
.
sum
(
exceed_lat
+
exceed_lon
)
if
exceed_sum
>
0
:
raise
Exception
(
'Dont Panic: Lat and/or Lon further away from model point than model resolution'
)
# compare amp
abs_amp
=
np
.
abs
(
pynemo_out
[
'amp'
]
-
subset
_fes
[
'amp'
])
abs_amp
=
np
.
abs
(
pynemo_out
[
'amp'
]
-
subset
[
'amp'
])
abs_amp_thres
=
abs_amp
>
amp_thres
err_amp
=
pynemo_out
[
'amp'
][
abs_amp_thres
].
tolist
()
err_amp_lats
=
pynemo_out
[
'lat'
][
abs_amp_thres
].
tolist
()
err_amp_lons
=
pynemo_out
[
'lon'
][
abs_amp_thres
].
tolist
()
err_ref_amp
=
subset
[
'amp'
][
abs_amp_thres
].
tolist
()
err_ref_lats_amp
=
subset
[
'lat'
][
abs_amp_thres
].
tolist
()
err_ref_lons_amp
=
subset
[
'lon'
][
abs_amp_thres
].
tolist
()
# compare phase
abs_ph
=
np
.
abs
(
pynemo_out
[
'phase'
]
-
subset
_fes
[
'phase'
])
abs_ph
=
np
.
abs
(
pynemo_out
[
'phase'
]
-
subset
[
'phase'
])
abs_ph_thres
=
abs_ph
>
phase_thres
err_pha
=
pynemo_out
[
'phase'
][
abs_ph_thres
[
0
,:]].
tolist
()
err_pha_lats
=
pynemo_out
[
'lat'
][
abs_ph_thres
].
tolist
()
err_pha_lons
=
pynemo_out
[
'lon'
][
abs_ph_thres
].
tolist
()
err_ref_pha
=
subset
[
'phase'
][
abs_ph_thres
].
tolist
()
err_ref_lats_pha
=
subset
[
'lat'
][
abs_ph_thres
].
tolist
()
err_ref_lons_pha
=
subset
[
'lon'
][
abs_ph_thres
].
tolist
()
lerr_pha
,
lerr_amp
=
len
(
err_pha
),
len
(
err_amp
)
max_len
=
max
(
lerr_pha
,
lerr_amp
)
if
not
max_len
==
lerr_pha
:
err_pha
.
extend
([
''
]
*
(
max_len
-
lerr_pha
))
err_pha_lats
.
extend
([
''
]
*
(
max_len
-
lerr_pha
))
err_pha_lons
.
extend
([
''
]
*
(
max_len
-
lerr_pha
))
err_ref_pha
.
extend
([
''
]
*
(
max_len
-
lerr_pha
))
err_ref_lats_pha
.
extend
([
''
]
*
(
max_len
-
lerr_pha
))
err_ref_lons_pha
.
extend
([
''
]
*
(
max_len
-
lerr_pha
))
if
not
max_len
==
lerr_amp
:
err_amp
.
extend
([
''
]
*
(
max_len
-
lerr_amp
))
err_amp_lats
.
extend
([
''
]
*
(
max_len
-
lerr_amp
))
err_amp_lons
.
extend
([
''
]
*
(
max_len
-
lerr_amp
))
err_ref_amp
.
extend
([
''
]
*
(
max_len
-
lerr_amp
))
err_ref_lats_amp
.
extend
([
''
]
*
(
max_len
-
lerr_amp
))
err_ref_lons_amp
.
extend
([
''
]
*
(
max_len
-
lerr_amp
))
err_log
=
pd
.
DataFrame
({
'amp_lat'
:
err_amp_lats
,
'amp_lon'
:
err_amp_lons
,
'amp'
:
err_amp
,
'ref_amp'
:
err_ref_amp
,
'ref_amp_lats'
:
err_ref_lats_amp
,
'ref_amp_lons'
:
err_ref_lons_amp
,
'phase_lat'
:
err_pha_lats
,
'phase_lon'
:
err_pha_lons
,
'phase'
:
err_pha
})
'phase'
:
err_pha
,
'ref_phase'
:
err_ref_pha
,
'ref_phase_lats'
:
err_ref_lats_pha
,
'ref_phase_lons'
:
err_ref_lons_pha
})
return
err_log
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment