
Benchmark MIOST geostrophic currents maps
2023-04-27 MIOST_UV_BENCHMARK_DEMO
Authors: CLS & Datlas Copyright: 2023 CLS & Datlas License: MIT
Benchmark of MIOST geostrophic currents maps
Benchmark of MIOST geostrophic currents maps
The notebook aims to evaluate the surface current maps produced by the MIOST system. Here, the geostrophic, barotrop and equatorial waves modes are considered in the surface state reconstruction.
<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 current data from the drifters database distributed by CMEMS (INSITU_GLO_PHY_UV_DISCRETE_MY_013_044 product) </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 currents maps with drifters database: statistical and spectral analysis
[1]:
from glob import glob
import numpy as np
import os
import warnings
warnings.filterwarnings("ignore")
[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_uv_miost_geos_eqwaves_barotrop.nc' # output statistical analysis filename
psd_output_filename = f'{output_dir}/psd_uv_miost_geos_eqwaves_barotrop.nc' # output spectral analysis filename
segment_lenght = np.timedelta64(40, 'D') # spectral parameter: drifters segment lenght in days to consider in the spectral analysis
Input files
Input files
Sea Surface currents from Drifters database
[5]:
filenames_drifters = sorted(glob('/work/ALT/swot/aval/wisa/data_challenge_ose/data/independent_drifters/uv_drifters_*.nc'))
[6]:
ds_drifter = xr.open_mfdataset(filenames_drifters, combine='nested', concat_dim='time')
ds_drifter = ds_drifter.where((ds_drifter.time >= np.datetime64(time_min)) & (ds_drifter.time <= np.datetime64(time_max)), drop=True)
ds_drifter
[6]:
<xarray.Dataset>
Dimensions: (time: 2156405)
Coordinates:
* time (time) datetime64[ns] 2019-01-01 ... 2019-12-31
latitude (time) float32 dask.array<chunksize=(5559,), meta=np.ndarray>
longitude (time) float32 dask.array<chunksize=(5559,), meta=np.ndarray>
Data variables:
EWCT (time) float32 dask.array<chunksize=(5559,), meta=np.ndarray>
NSCT (time) float32 dask.array<chunksize=(5559,), meta=np.ndarray>
sensor_id (time) float64 dask.array<chunksize=(5559,), meta=np.ndarray>
Attributes: (12/46)
data_type: OceanSITES trajectory data
format_version: 2.0
platform_code: 116275
date_update: 2020-10-13T12:17:40Z
institution: AOML
institution_edmo_code: 1799
... ...
deployment_lat: -58.44
last_longitude_observation: 82.75
last_latitude_observation: -18.49
date_drog_lost: 2017-01-21T03:37:00Z
death_type: stop transmitting
last_date_observation: 2019-01-16T01:51:00ZSea Surface current maps to evaluate
[7]:
list_of_maps = sorted(glob('/work/ALT/swot/aval/wisa/data_challenge_ose/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 currents maps onto drifters positions
[8]:
ds_interp = run_interpolation_drifters(ds_maps, ds_drifter, time_min, time_max)
ds_interp = ds_interp.dropna('time')
ds_interp = ds_interp.sortby('time')
ds_interp
2023-04-28 12:25:06 INFO fetch data from 2019-01-01 00:00:00 to 2019-02-01 00:00:00
2023-04-28 12:25:17 INFO fetch data from 2019-01-01 00:00:00 to 2019-02-01 00:00:00
2023-04-28 12:25:27 INFO fetch data from 2019-01-31 00:00:00 to 2019-03-01 00:00:00
2023-04-28 12:25:37 INFO fetch data from 2019-01-31 00:00:00 to 2019-03-01 00:00:00
2023-04-28 12:25:47 INFO fetch data from 2019-02-28 00:00:00 to 2019-04-01 00:00:00
2023-04-28 12:25:58 INFO fetch data from 2019-02-28 00:00:00 to 2019-04-01 00:00:00
2023-04-28 12:26:09 INFO fetch data from 2019-03-31 00:00:00 to 2019-05-01 00:00:00
2023-04-28 12:26:19 INFO fetch data from 2019-03-31 00:00:00 to 2019-05-01 00:00:00
2023-04-28 12:26:30 INFO fetch data from 2019-04-30 00:00:00 to 2019-06-01 00:00:00
2023-04-28 12:26:41 INFO fetch data from 2019-04-30 00:00:00 to 2019-06-01 00:00:00
2023-04-28 12:26:52 INFO fetch data from 2019-05-31 00:00:00 to 2019-07-01 00:00:00
2023-04-28 12:27:03 INFO fetch data from 2019-05-31 00:00:00 to 2019-07-01 00:00:00
2023-04-28 12:27:14 INFO fetch data from 2019-06-30 00:00:00 to 2019-08-01 00:00:00
2023-04-28 12:27:25 INFO fetch data from 2019-06-30 00:00:00 to 2019-08-01 00:00:00
2023-04-28 12:27:37 INFO fetch data from 2019-07-31 00:00:00 to 2019-09-01 00:00:00
2023-04-28 12:27:48 INFO fetch data from 2019-07-31 00:00:00 to 2019-09-01 00:00:00
2023-04-28 12:27:59 INFO fetch data from 2019-08-31 00:00:00 to 2019-10-01 00:00:00
2023-04-28 12:28:10 INFO fetch data from 2019-08-31 00:00:00 to 2019-10-01 00:00:00
2023-04-28 12:28:21 INFO fetch data from 2019-09-30 00:00:00 to 2019-11-01 00:00:00
2023-04-28 12:28:33 INFO fetch data from 2019-09-30 00:00:00 to 2019-11-01 00:00:00
2023-04-28 12:28:44 INFO fetch data from 2019-10-31 00:00:00 to 2019-12-01 00:00:00
2023-04-28 12:28:56 INFO fetch data from 2019-10-31 00:00:00 to 2019-12-01 00:00:00
2023-04-28 12:29:06 INFO fetch data from 2019-11-30 00:00:00 to 2019-12-31 00:00:00
2023-04-28 12:29:18 INFO fetch data from 2019-11-30 00:00:00 to 2019-12-31 00:00:00
[8]:
<xarray.Dataset>
Dimensions: (time: 2107837)
Coordinates:
* time (time) datetime64[ns] 2019-01-01 ... 2019-12-31
Data variables:
EWCT (time) float32 -0.1013 -0.1692 ... -0.04298 -0.07795
NSCT (time) float32 0.2415 0.00305 ... 0.03121 -0.1021
sensor_id (time) float64 1.163e+05 1.164e+05 ... 6.831e+07
latitude (time) float32 -20.17 -23.35 -29.47 ... -16.64 -32.11
longitude (time) float32 87.07 -6.986 -12.2 ... 86.61 121.6 95.08
ugos_interpolated (time) float64 -0.105 0.006239 ... 0.01937 -0.0214
vgos_interpolated (time) float64 0.15 -0.05987 -0.03892 ... 0.181 0.037942.2 Compute grid boxes statistics & statistics by regime (coastal, offshore low variability, offshore high variability)
[9]:
# Compute gridded stats
compute_stat_scores_uv(ds_interp, stat_output_filename)
2023-04-28 12:29:30 INFO Compute mapping error all scales
2023-04-28 12:29:30 INFO Compute statistics
2023-04-28 12:29:35 INFO Stat file saved as: ../results/stat_uv_miost_geos_eqwaves_barotrop.nc
2023-04-28 12:29:35 INFO Compute statistics by oceanic regime
[10]:
# Plot gridded stats
# Hvplot
# plot_stat_score_map_uv(stat_output_filename)
# Matplotlib
plot_stat_score_map_uv_png(stat_output_filename)
The figure shows that the maximum mapping errors are found in intense current systems, for example in the GulfStream, Kuroshio and Agulhas regions.
However, when considering the full scale of motion in the drifter database, the surface current maps capture up to 80% of the variability of drifter currents in the Western Boundary Currents and Antarctic Circumpolar Currents (ACC). The geostrophic signal dominates the ageostrophic signal in these regions. In regions with low ocean variability, only a few percent of the total drifter current variability is recovered in the maps, which may be associated with a larger ageostrophic signal in these regions.
[11]:
plot_stat_uv_by_regimes(stat_output_filename)
[11]:
| mapping_err_u_var [m²/s²] | mapping_err_v_var [m²/s²] | ugos_interpolated_var [m²/s²] | EWCT_var [m²/s²] | vgos_interpolated_var [m²/s²] | NSCT_var [m²/s²] | var_score_u_allscale | var_score_v_allscale | |
|---|---|---|---|---|---|---|---|---|
| coastal | 0.057947 | 0.029261 | 0.047382 | 0.055541 | 0.029803 | 0.045997 | -0.043305 | 0.363849 |
| offshore_highvar | 0.037413 | 0.038441 | 0.109855 | 0.139475 | 0.103847 | 0.121805 | 0.731755 | 0.684403 |
| offshore_lowvar | 0.045661 | 0.021087 | 0.037863 | 0.043436 | 0.016299 | 0.030965 | -0.051212 | 0.319015 |
| equatorial_band | 0.309956 | 0.066951 | 0.280028 | 0.106822 | 0.060847 | 0.057751 | -1.901612 | -0.159305 |
| arctic | 0.014028 | 0.014531 | 0.004840 | 0.018808 | 0.005297 | 0.019888 | 0.254177 | 0.269362 |
| antarctic | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
2.4 Compute Spectral scores
[13]:
# Compute PSD scores
compute_psd_scores_current(ds_interp, psd_output_filename, lenght_scale=segment_lenght)
2023-04-28 12:30:27 INFO Segment computation...
2023-04-28 12:34:13 INFO Spectral analysis...
2023-04-28 12:34:13 INFO Write output...
2023-04-28 12:34:13 INFO PSD file saved as: ../results/psd_uv_miost_geos_eqwaves_barotrop.nc
[14]:
# Plot Zonally averaged rotary spectra
# Hvplot
# plot_psd_scores_currents(psd_output_filename)
# Matplotlib
plot_psd_scores_currents_png(psd_output_filename)
[15]:
# Plot Zonally averaged rotary spectra
plot_psd_scores_currents_1D(psd_output_filename)
[15]:
The interactive plot above allows you to explore the spectral metrics by latitude band
[ ]: