
Benchmark MIOST sea surface height maps (Geostrophic + Equatorial Wave + Barotrop modes)
2023-04-27 MIOST_SSH_GEOS_BENCHMARK_DEMO
Authors: CLS & Datlas Copyright: 2023 CLS & Datlas License: MIT
Benchmark of MIOST sea surface height maps
Benchmark of MIOST sea surface height maps
The notebook aims to evaluate the sea surface height maps produced by the MIOST system.
<h5> These maps are equivalent to the SEALEVEL_GLO_PHY_L4_MY_008_047 product distributed by the Copernicus Marine Service, except that a nadir altimeter (SARAL/Altika, SEALEVEL_GLO_PHY_L3_MY_008_062 product) has been excluded from the mapping. </h5>
<h5> We provide below a demonstration of the validation of these maps against the independent SSH data from the Saral/AltiKa altimeter distributed by CMEMS </h5>
General Note 1: Execute each cell through the button from the top MENU (or keyboard shortcut Shift + Enter). General Note 2: If, for any reason, the kernel is not working anymore, in the top MENU, click on the button. Then, in the top MENU, click on “Cell” and select “Run All Above Selected Cell”. ***
Learning outcomes
At the end of this notebook you will know:
How you can evaluated sea surface height maps with independent alongtrack data: statistical and spectral analysis
[1]:
from glob import glob
import numpy as np
import os
[2]:
import sys
sys.path.append('..')
from src.mod_plot import *
from src.mod_stat import *
from src.mod_spectral import *
[3]:
import logging
logger = logging.getLogger()
logger.setLevel(logging.INFO)
Parameters
Parameters
[4]:
time_min = '2019-01-01' # time min for analysis
time_max = '2019-12-31' # time max for analysis
output_dir = '../results' # output directory path
os.system(f'mkdir -p {output_dir}')
stat_output_filename = f'{output_dir}/stat_sla_miost_geos_eqwaves_barotrop.nc' # output statistical analysis filename
lambda_min = 65. # minimun spatial scale in kilometer to consider on the filtered signal
lambda_max = 500. # maximum spatial scale in kilometer to consider on the filtered signal
psd_output_filename = f'{output_dir}/psd_sla_miost_geos_eqwaves_barotrop.nc' # output spectral analysis filename
segment_lenght = 1000. # spectral parameer: along-track segment lenght in kilometer to consider in the spectral analysis
Input files
Input files
Sea Surface Height from Saral/AltiKa
[6]:
list_of_file = sorted(glob('../data/independent_alongtrack/alg/2019/*.nc'))
ds_alg = xr.open_mfdataset(list_of_file, combine='nested', concat_dim='time')
ds_alg = ds_alg.where((ds_alg.time >= np.datetime64(time_min)) & (ds_alg.time <= np.datetime64(time_max)), drop=True)
ds_alg = ds_alg.sortby('time')
ds_alg
[6]:
<xarray.Dataset>
Dimensions: (time: 14437696)
Coordinates:
* time (time) datetime64[ns] 2019-01-01T00:04:07.003014144 ... 2...
longitude (time) float64 dask.array<chunksize=(44621,), meta=np.ndarray>
latitude (time) float64 dask.array<chunksize=(44621,), meta=np.ndarray>
Data variables:
cycle (time) float64 dask.array<chunksize=(44621,), meta=np.ndarray>
track (time) float64 dask.array<chunksize=(44621,), meta=np.ndarray>
sla_unfiltered (time) float32 dask.array<chunksize=(44621,), meta=np.ndarray>
sla_filtered (time) float32 dask.array<chunksize=(44621,), meta=np.ndarray>
dac (time) float32 dask.array<chunksize=(44621,), meta=np.ndarray>
ocean_tide (time) float32 dask.array<chunksize=(44621,), meta=np.ndarray>
internal_tide (time) float32 dask.array<chunksize=(44621,), meta=np.ndarray>
lwe (time) float32 dask.array<chunksize=(44621,), meta=np.ndarray>
mdt (time) float32 dask.array<chunksize=(44621,), meta=np.ndarray>
tpa_correction (time) float32 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0 0.0
Attributes: (12/44)
Conventions: CF-1.6
Metadata_Conventions: Unidata Dataset Discovery v1.0
cdm_data_type: Swath
comment: Sea surface height measured by altimeter...
contact: servicedesk.cmems@mercator-ocean.eu
creator_email: servicedesk.cmems@mercator-ocean.eu
... ...
summary: SSALTO/DUACS Delayed-Time Level-3 sea su...
time_coverage_duration: P24H11M29.716548S
time_coverage_end: 2019-01-01T23:36:52Z
time_coverage_resolution: P1S
time_coverage_start: 2018-12-31T23:25:22Z
title: DT Altika Drifting Phase Global Ocean Al...Sea Surface Height maps to evaluate
[7]:
list_of_maps = sorted(glob('../data/maps/MIOST_geos_barotrop_eqwaves_global_allsat-alg/*.nc'))
ds_maps = xr.open_mfdataset(list_of_maps, combine='nested', concat_dim='time')
ds_maps = ds_maps.sel(time=slice(time_min, time_max))
ds_maps
[7]:
<xarray.Dataset>
Dimensions: (longitude: 3600, latitude: 1701, time: 365)
Coordinates:
* longitude (longitude) float64 0.0 0.1 0.2 0.3 ... 359.6 359.7 359.8 359.9
* latitude (latitude) float32 -80.05 -79.95 -79.85 ... 89.75 89.85 89.95
* time (time) datetime64[ns] 2019-01-01 2019-01-02 ... 2019-12-31
Data variables:
sla (time, latitude, longitude) float64 dask.array<chunksize=(1, 1701, 3600), meta=np.ndarray>
ugosa (time, latitude, longitude) float64 dask.array<chunksize=(1, 1701, 3600), meta=np.ndarray>
vgosa (time, latitude, longitude) float64 dask.array<chunksize=(1, 1701, 3600), meta=np.ndarray>
adt (time, latitude, longitude) float64 dask.array<chunksize=(1, 1701, 3600), meta=np.ndarray>
ugos (time, latitude, longitude) float64 dask.array<chunksize=(1, 1701, 3600), meta=np.ndarray>
vgos (time, latitude, longitude) float64 dask.array<chunksize=(1, 1701, 3600), meta=np.ndarray>
Statistical & Spectral Analysis
Statistical & Spectral Analysis
2.1 Interpolate sea surface height maps onto along-track positions
[8]:
ds_interp = run_interpolation(ds_maps, ds_alg)
ds_interp = ds_interp.dropna('time')
ds_interp
2023-07-07 16:59:29 INFO fetch data from 2019-01-01 00:00:00 to 2019-02-01 00:00:00
2023-07-07 16:59:41 INFO fetch data from 2019-01-31 00:00:00 to 2019-03-01 00:00:00
2023-07-07 16:59:51 INFO fetch data from 2019-02-28 00:00:00 to 2019-04-01 00:00:00
2023-07-07 17:00:01 INFO fetch data from 2019-03-31 00:00:00 to 2019-05-01 00:00:00
2023-07-07 17:00:10 INFO fetch data from 2019-04-30 00:00:00 to 2019-06-01 00:00:00
2023-07-07 17:00:30 INFO fetch data from 2019-05-31 00:00:00 to 2019-07-01 00:00:00
2023-07-07 17:00:42 INFO fetch data from 2019-06-30 00:00:00 to 2019-08-01 00:00:00
2023-07-07 17:00:52 INFO fetch data from 2019-07-31 00:00:00 to 2019-09-01 00:00:00
2023-07-07 17:01:07 INFO fetch data from 2019-08-31 00:00:00 to 2019-10-01 00:00:00
2023-07-07 17:01:16 INFO fetch data from 2019-09-30 00:00:00 to 2019-11-01 00:00:00
2023-07-07 17:01:24 INFO fetch data from 2019-10-31 00:00:00 to 2019-12-01 00:00:00
2023-07-07 17:01:32 INFO fetch data from 2019-11-30 00:00:00 to 2019-12-31 00:00:00
[8]:
<xarray.Dataset>
Dimensions: (time: 14370249)
Coordinates:
* time (time) datetime64[ns] 2019-01-01T00:04:07.003014144 .....
Data variables: (12/13)
cycle (time) float64 126.0 126.0 126.0 ... 136.0 136.0 136.0
track (time) float64 9.0 9.0 9.0 9.0 ... 408.0 408.0 408.0
sla_unfiltered (time) float32 0.127 0.101 0.07 ... 0.007 0.056 0.01
sla_filtered (time) float32 0.117 0.128 0.142 ... 0.03 0.031 0.027
dac (time) float32 0.303 0.299 0.296 ... 0.172 0.171 0.172
ocean_tide (time) float32 -0.091 -0.096 -0.099 ... -0.304 -0.314
... ...
lwe (time) float32 -0.019 -0.019 -0.019 ... 0.014 0.014 0.016
mdt (time) float32 -0.104 -0.106 -0.108 ... -1.138 -1.154
tpa_correction (time) float32 0.0 0.0 0.0 0.0 0.0 ... 0.0 0.0 0.0 0.0
longitude (time) float64 64.42 64.33 64.25 ... 246.7 246.6 246.3
latitude (time) float64 69.9 69.95 70.01 ... -69.27 -69.32 -69.55
msla_interpolated (time) float64 0.1479 0.1481 0.1486 ... 0.02042 0.031242.2 Compute grid boxes statistics & statistics by regime (coastal, offshore low variability, offshore high variability)
[9]:
compute_stat_scores(ds_interp, lambda_min, lambda_max, stat_output_filename)
2023-07-07 17:01:44 INFO Compute mapping error all scales
2023-07-07 17:01:44 INFO Compute mapping error for scales between 65.0 and 500.0 km
2023-07-07 17:02:41 INFO Compute binning statistics
2023-07-07 17:02:54 INFO Compute statistics by oceanic regime
2023-07-07 17:03:24 INFO Stat file saved as: ../results/stat_sla_miost_geos_eqwaves_barotrop.nc
[10]:
# Plot gridded stats
# Hvplot
# plot_stat_score_map(stat_output_filename)
# Matplotlib
plot_stat_score_map_png(stat_output_filename)
[11]:
plot_stat_score_timeseries(stat_output_filename)
[11]:
[12]:
plot_stat_by_regimes(stat_output_filename)
[12]:
| mapping_err_var [m²] | sla_unfiltered_var [m²] | mapping_err_filtered_var [m²] | sla_filtered_var [m²] | var_score_allscale | var_score_filtered | |
|---|---|---|---|---|---|---|
| coastal | 0.002546 | 0.008303 | 0.000548 | 0.001813 | 0.693327 | 0.697649 |
| offshore_highvar | 0.002893 | 0.053263 | 0.000958 | 0.021750 | 0.945677 | 0.955963 |
| offshore_lowvar | 0.001178 | 0.006299 | 0.000224 | 0.001775 | 0.812999 | 0.873896 |
| equatorial_band | 0.001399 | 0.005975 | 0.000307 | 0.000536 | 0.765894 | 0.426543 |
| arctic | 0.002417 | 0.007084 | 0.000407 | 0.001019 | 0.658796 | 0.600981 |
| antarctic | 0.003420 | 0.002344 | 0.000680 | 0.000753 | -0.458979 | 0.096746 |
2.3 Compute Spectral scores
[13]:
compute_psd_scores(ds_interp, psd_output_filename, lenght_scale=segment_lenght)
2023-07-07 17:03:37 INFO Segment computation...
2023-07-07 17:03:49 INFO Spectral analysis...
2023-07-07 18:25:21 INFO Saving ouput...
2023-07-07 18:25:31 INFO PSD file saved as: ../results/psd_sla_miost_geos_eqwaves_barotrop.nc
[13]:
# Plot effective resolution
# Hvplot
# plot_effective_resolution(psd_output_filename)
# Matplotlib
plot_effective_resolution_png(psd_output_filename)
[14]:
plot_psd_scores(psd_output_filename)
[14]:
The interactive plot above allows you to explore the spectral metrics by latitude / longitude box
[ ]: