OceanDataStore 0.3.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.
- OceanDataStore/__init__.py +21 -0
- OceanDataStore/catalog/__init__.py +12 -0
- OceanDataStore/catalog/oceandatacatalog.py +1242 -0
- OceanDataStore/catalog/stac/README.md +34 -0
- OceanDataStore/catalog/stac/__init__.py +30 -0
- OceanDataStore/catalog/stac/create_noc_stac.py +109 -0
- OceanDataStore/catalog/stac/npd_era5_collection.py +364 -0
- OceanDataStore/catalog/stac/npd_jra55_collection.py +196 -0
- OceanDataStore/catalog/stac/ods_obs_collection.py +534 -0
- OceanDataStore/catalog/stac/rapid_evo_collection.py +309 -0
- OceanDataStore/catalog/stac/template_collection.py +85 -0
- OceanDataStore/catalog/stac/utils.py +476 -0
- OceanDataStore/cli/__init__.py +34 -0
- OceanDataStore/cli/arg_parser.py +182 -0
- OceanDataStore/cli/cli.py +203 -0
- OceanDataStore/cli/exceptions.py +83 -0
- OceanDataStore/cli/icechunk.py +888 -0
- OceanDataStore/cli/logging.py +52 -0
- OceanDataStore/cli/object_store.py +293 -0
- OceanDataStore/cli/utils.py +275 -0
- OceanDataStore/cli/zarr.py +870 -0
- OceanDataStore/data/ARMOR3D/create_ARMOR3D_P1M-m_monthly_climatology.py +135 -0
- OceanDataStore/data/ARMOR3D/download_ARMOR3D_0.125def_P1M-m_1993_2024.py +33 -0
- OceanDataStore/data/ARMOR3D/run_create_ARMOR3D_P1M-m_monthly_climatology.slurm +32 -0
- OceanDataStore/data/ARMOR3D/run_send_ARMOR3D_P1M-m_climatology_to_os.slurm +32 -0
- OceanDataStore/data/ARMOR3D/run_send_ARMOR3D_P1M-m_monthly_to_os.slurm +32 -0
- OceanDataStore/data/ARMOR3D/run_update_ARMOR3D_P1m-m_monthly_to_os.slurm +32 -0
- OceanDataStore/data/ARMOR3D/send_ARMOR3D_P1m-m_monthly_climatology_to_os.py +99 -0
- OceanDataStore/data/ARMOR3D/send_ARMOR3D_P1m-m_monthly_to_os.py +147 -0
- OceanDataStore/data/ARMOR3D/update_ARMOR3D_P1m-m_monthly_to_os.py +143 -0
- OceanDataStore/data/EN.4.2.2/create_EN4.2.2_analysis_g10_climatology.py +162 -0
- OceanDataStore/data/EN.4.2.2/download_EN4.2.2_analysis_g10_data.sh +51 -0
- OceanDataStore/data/EN.4.2.2/run_send_EN4.2.2_analysis_g10_climatology_to_os.slurm +32 -0
- OceanDataStore/data/EN.4.2.2/run_send_EN4.2.2_analysis_g10_monthly_to_os.slurm +32 -0
- OceanDataStore/data/EN.4.2.2/run_update_EN4.2.2_analysis_g10_monthly_to_os.slurm +32 -0
- OceanDataStore/data/EN.4.2.2/send_EN4.2.2_analysis_g10_monthly_climatology_to_os.py +76 -0
- OceanDataStore/data/EN.4.2.2/send_EN4.2.2_analysis_g10_monthly_to_os.py +165 -0
- OceanDataStore/data/EN.4.2.2/update_EN4.2.2_analysis_g10_monthly_to_os.py +161 -0
- OceanDataStore/data/ERA5/create_ERA5_daily_climatology.py +110 -0
- OceanDataStore/data/ERA5/create_ERA5_daily_mean.py +69 -0
- OceanDataStore/data/ERA5/create_ERA5_monthly_mean.py +74 -0
- OceanDataStore/data/ERA5/run_create_ERA5_daily_climatology.slurm +54 -0
- OceanDataStore/data/ERA5/run_send_ERA5_daily_climatology_to_os.slurm +32 -0
- OceanDataStore/data/ERA5/run_send_ERA5_daily_to_os.slurm +32 -0
- OceanDataStore/data/ERA5/run_send_ERA5_monthly_to_os.slurm +32 -0
- OceanDataStore/data/ERA5/run_update_ERA5_daily_to_os.slurm +32 -0
- OceanDataStore/data/ERA5/run_update_ERA5_monthly_to_os.slurm +32 -0
- OceanDataStore/data/ERA5/send_ERA5_daily_climatology_to_os.py +159 -0
- OceanDataStore/data/ERA5/send_ERA5_daily_to_os.py +141 -0
- OceanDataStore/data/ERA5/send_ERA5_monthly_to_os.py +173 -0
- OceanDataStore/data/ERA5/update_ERA5_daily_to_os.py +141 -0
- OceanDataStore/data/ERA5/update_ERA5_monthly_to_os.py +169 -0
- OceanDataStore/data/HadISST/download_HadISST1_data.sh +43 -0
- OceanDataStore/data/HadISST/run_send_HadISST1_monthly_to_os.slurm +32 -0
- OceanDataStore/data/HadISST/send_HadISST1_monthly_to_os.py +133 -0
- OceanDataStore/data/NSIDC/download_NSIDC_monthly_1979_2025_data.sh +54 -0
- OceanDataStore/data/NSIDC/process_NSIDC_SSI_Antarctic_data.py +130 -0
- OceanDataStore/data/NSIDC/process_NSIDC_SSI_Arctic_data.py +129 -0
- OceanDataStore/data/NSIDC/run_send_NSIDC_v4.0_to_OS.slurm +32 -0
- OceanDataStore/data/NSIDC/send_NSIDC_SII_v4.0_to_os.py +140 -0
- OceanDataStore/data/OISST/create_OISSTv2_daily_climatology.py +83 -0
- OceanDataStore/data/OISST/download_oisstv2_data.sh +43 -0
- OceanDataStore/data/OISST/run_create_OISSTv2_daily_climatology.slurm +44 -0
- OceanDataStore/data/OISST/run_send_OISSTv2_daily_climatology_to_os.slurm +32 -0
- OceanDataStore/data/OISST/run_send_OISSTv2_daily_to_os.slurm +32 -0
- OceanDataStore/data/OISST/run_send_OISSTv2_monthly_climatology_to_os.slurm +32 -0
- OceanDataStore/data/OISST/run_send_OISSTv2_monthly_to_os.slurm +32 -0
- OceanDataStore/data/OISST/run_update_OISSTv2_daily_to_os.slurm +32 -0
- OceanDataStore/data/OISST/send_OISSTv2_daily_climatology_to_os.py +154 -0
- OceanDataStore/data/OISST/send_OISSTv2_daily_ltm_climatology_to_os.py +151 -0
- OceanDataStore/data/OISST/send_OISSTv2_daily_to_os.py +142 -0
- OceanDataStore/data/OISST/send_OISSTv2_monthly_climatology_to_os.py +150 -0
- OceanDataStore/data/OISST/send_OISSTv2_monthly_to_os.py +145 -0
- OceanDataStore/data/OISST/update_OISSTv2_daily_to_os.py +142 -0
- OceanDataStore/data/OSTIA/create_OSTIA_daily_climatology.py +120 -0
- OceanDataStore/data/OSTIA/download_OSTIA_NRT.py +42 -0
- OceanDataStore/data/OSTIA/download_OSTIA_REP_1981_2025.py +42 -0
- OceanDataStore/data/OSTIA/run_create_OSTIA_daily_climatology.slurm +54 -0
- OceanDataStore/data/OSTIA/run_send_OSTIA_daily_climatology_to_os.slurm +32 -0
- OceanDataStore/data/OSTIA/run_send_OSTIA_nrt_daily_to_os.slurm +32 -0
- OceanDataStore/data/OSTIA/run_send_OSTIA_rep_daily_to_os.slurm +32 -0
- OceanDataStore/data/OSTIA/run_update_OSTIA_daily_to_os.slurm +33 -0
- OceanDataStore/data/OSTIA/send_OSTIA_daily_climatology_to_os.py +194 -0
- OceanDataStore/data/OSTIA/send_OSTIA_nrt_daily_to_os.py +141 -0
- OceanDataStore/data/OSTIA/send_OSTIA_rep_daily_to_os.py +145 -0
- OceanDataStore/data/OSTIA/update_OSTIA_copernicus_nrt_daily_to_os.py +144 -0
- OceanDataStore/data/OSTIA/update_OSTIA_nrt_daily_to_os.py +137 -0
- OceanDataStore/data/WOA23/download_WOA23_climatology.sh +41 -0
- OceanDataStore/data/WOA23/run_send_WOA23_annual_climatology_to_os.slurm +32 -0
- OceanDataStore/data/WOA23/run_send_WOA23_monthly_climatology_to_os.slurm +32 -0
- OceanDataStore/data/WOA23/send_WOA23_annual_climatology_to_os.py +263 -0
- OceanDataStore/data/WOA23/send_WOA23_monthly_climatology_to_os.py +292 -0
- OceanDataStore/data/update_icechunk_repo_attrs.py +76 -0
- OceanDataStore/data/update_noc_npd_era5v1_attrs.py +172 -0
- OceanDataStore/data/utils.py +506 -0
- OceanDataStore/zarr.py +993 -0
- oceandatastore-0.3.0.dist-info/METADATA +184 -0
- oceandatastore-0.3.0.dist-info/RECORD +104 -0
- oceandatastore-0.3.0.dist-info/WHEEL +5 -0
- oceandatastore-0.3.0.dist-info/entry_points.txt +2 -0
- oceandatastore-0.3.0.dist-info/licenses/LICENSE +201 -0
- oceandatastore-0.3.0.dist-info/scm_file_list.json +154 -0
- oceandatastore-0.3.0.dist-info/scm_version.json +8 -0
- oceandatastore-0.3.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#SBATCH --job-name=ostia_daily_climatology
|
|
3
|
+
#SBATCH --time=12:00:00
|
|
4
|
+
#SBATCH --partition=compute
|
|
5
|
+
#SBATCH --nodes=1
|
|
6
|
+
#SBATCH --mem=0
|
|
7
|
+
#SBATCH --exclusive
|
|
8
|
+
##SBATCH --mem-per-cpu=4G
|
|
9
|
+
##SBATCH --ntasks-per-node=64
|
|
10
|
+
##SBATCH --ntasks-per-socket=32
|
|
11
|
+
##SBATCH --ntasks-per-core=1
|
|
12
|
+
|
|
13
|
+
module load NEMO/prg-env
|
|
14
|
+
#============================
|
|
15
|
+
export I_MPI_SHM=icx
|
|
16
|
+
|
|
17
|
+
source /dssgfs01/working/otooth/miniforge3/bin/activate
|
|
18
|
+
conda activate env_ods
|
|
19
|
+
|
|
20
|
+
# ==============================================================
|
|
21
|
+
# run_create_OSTIA_daily_climatology.slurm
|
|
22
|
+
#
|
|
23
|
+
# Description: SLURM script to create the OSTIA daily
|
|
24
|
+
# climatology datasets.
|
|
25
|
+
#
|
|
26
|
+
# Created By: Oliver Tooth (oliver.tooth@noc.ac.uk)
|
|
27
|
+
# Created On: 2026-06-25
|
|
28
|
+
#
|
|
29
|
+
# ==============================================================
|
|
30
|
+
|
|
31
|
+
#============================
|
|
32
|
+
TIME1=`date +%s`
|
|
33
|
+
|
|
34
|
+
dpath="/dssgfs01/working/otooth/data/observations/OSTIA/"
|
|
35
|
+
|
|
36
|
+
Ystart=1991
|
|
37
|
+
Yend=$((Ystart+29))
|
|
38
|
+
|
|
39
|
+
ofile="/dssgfs01/working/otooth/data/observations/OSTIA/climatology/ostia_sst_climatology_${Ystart}-${Yend}.zarr"
|
|
40
|
+
|
|
41
|
+
echo "Start year : " $Ystart
|
|
42
|
+
echo "End year : " $Yend
|
|
43
|
+
echo "Output file : " $ofile
|
|
44
|
+
|
|
45
|
+
python create_OSTIA_daily_climatology.py $Ystart $Yend --data_path $dpath --output $ofile
|
|
46
|
+
|
|
47
|
+
#============================
|
|
48
|
+
# Job timing
|
|
49
|
+
|
|
50
|
+
TIME2=`date +%s`
|
|
51
|
+
DIFFSEC=`expr ${TIME2} - ${TIME1}`
|
|
52
|
+
echo Took ${DIFFSEC} seconds.
|
|
53
|
+
echo Took `date +%H:%M:%S -ud @${DIFFSEC}`
|
|
54
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#SBATCH --job-name=ostia_daily_climatology
|
|
3
|
+
#SBATCH --partition=test
|
|
4
|
+
#SBATCH --time=00:20:00
|
|
5
|
+
#SBATCH --ntasks-per-core=1
|
|
6
|
+
#SBATCH --ntasks-per-node=64
|
|
7
|
+
#SBATCH --ntasks-per-socket=32
|
|
8
|
+
#SBATCH --nodes=1
|
|
9
|
+
|
|
10
|
+
# ==============================================================
|
|
11
|
+
# run_send_OSTIA_daily_climatology_to_os.slurm
|
|
12
|
+
#
|
|
13
|
+
# Description: SLURM script to send the OSTIA daily
|
|
14
|
+
# climatology datasets to Icechunk repository.
|
|
15
|
+
#
|
|
16
|
+
# Created By: Ollie Tooth (oliver.tooth@noc.ac.uk)
|
|
17
|
+
# Created On: 2026-06-28
|
|
18
|
+
#
|
|
19
|
+
# ==============================================================
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# -- Python Environment -- #
|
|
23
|
+
# Activate miniconda environment:
|
|
24
|
+
source /dssgfs01/working/otooth/miniforge3/bin/activate
|
|
25
|
+
conda activate env_ods
|
|
26
|
+
|
|
27
|
+
# -- Send OSTIA daily climatology datasets to JASMIN OS -- #
|
|
28
|
+
echo "In Progress: Sending OSTIA daily climatology to Icechunk..."
|
|
29
|
+
|
|
30
|
+
python3 send_OSTIA_daily_climatology_to_os.py
|
|
31
|
+
|
|
32
|
+
echo "Completed: Sent OSTIA daily climatology to Icechunk."
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#SBATCH --job-name=send_ostia_nrt_daily
|
|
3
|
+
#SBATCH --partition=compute
|
|
4
|
+
#SBATCH --time=03:00:00
|
|
5
|
+
#SBATCH --ntasks-per-core=1
|
|
6
|
+
#SBATCH --ntasks-per-node=64
|
|
7
|
+
#SBATCH --ntasks-per-socket=32
|
|
8
|
+
#SBATCH --nodes=1
|
|
9
|
+
|
|
10
|
+
# ==============================================================
|
|
11
|
+
# run_send_OSTIA_nrt_daily_to_os.slurm
|
|
12
|
+
#
|
|
13
|
+
# Description: SLURM script to send the OSTIA Near-Real-Time daily
|
|
14
|
+
# time-series dataset to Icechunk repository.
|
|
15
|
+
#
|
|
16
|
+
# Created By: Ollie Tooth (oliver.tooth@noc.ac.uk)
|
|
17
|
+
# Created On: 2026-06-28
|
|
18
|
+
#
|
|
19
|
+
# ==============================================================
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# -- Python Environment -- #
|
|
23
|
+
# Activate miniconda environment:
|
|
24
|
+
source /dssgfs01/working/otooth/miniforge3/bin/activate
|
|
25
|
+
conda activate env_ods
|
|
26
|
+
|
|
27
|
+
# -- Send OSTIA daily time-series datasets to JASMIN OS -- #
|
|
28
|
+
echo "In Progress: Sending OSTIA Near-Real-Time Daily time-series to Icechunk..."
|
|
29
|
+
|
|
30
|
+
python3 send_OSTIA_nrt_daily_to_os.py
|
|
31
|
+
|
|
32
|
+
echo "Completed: Sent OSTIA Near-Real-Time Daily time-series to Icechunk."
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#SBATCH --job-name=send_ostia_rep_daily
|
|
3
|
+
#SBATCH --partition=compute
|
|
4
|
+
#SBATCH --time=03:00:00
|
|
5
|
+
#SBATCH --ntasks-per-core=1
|
|
6
|
+
#SBATCH --ntasks-per-node=64
|
|
7
|
+
#SBATCH --ntasks-per-socket=32
|
|
8
|
+
#SBATCH --nodes=1
|
|
9
|
+
|
|
10
|
+
# ==============================================================
|
|
11
|
+
# run_send_OSTIA_rep_daily_to_os.slurm
|
|
12
|
+
#
|
|
13
|
+
# Description: SLURM script to send the OSTIA reprocessed daily
|
|
14
|
+
# time-series dataset to Icechunk repository.
|
|
15
|
+
#
|
|
16
|
+
# Created By: Ollie Tooth (oliver.tooth@noc.ac.uk)
|
|
17
|
+
# Created On: 2026-06-28
|
|
18
|
+
#
|
|
19
|
+
# ==============================================================
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# -- Python Environment -- #
|
|
23
|
+
# Activate miniconda environment:
|
|
24
|
+
source /dssgfs01/working/otooth/miniforge3/bin/activate
|
|
25
|
+
conda activate env_ods
|
|
26
|
+
|
|
27
|
+
# -- Send OSTIA daily time-series datasets to JASMIN OS -- #
|
|
28
|
+
echo "In Progress: Sending OSTIA Reprocessed Daily time-series to Icechunk..."
|
|
29
|
+
|
|
30
|
+
python3 send_OSTIA_rep_daily_to_os.py
|
|
31
|
+
|
|
32
|
+
echo "Completed: Sent OSTIA Reprocessed Daily time-series to Icechunk."
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#SBATCH --job-name=update_ostia_daily
|
|
3
|
+
#SBATCH --partition=compute
|
|
4
|
+
#SBATCH --time=03:00:00
|
|
5
|
+
#SBATCH --ntasks-per-core=1
|
|
6
|
+
#SBATCH --ntasks-per-node=64
|
|
7
|
+
#SBATCH --ntasks-per-socket=32
|
|
8
|
+
#SBATCH --nodes=1
|
|
9
|
+
|
|
10
|
+
# ==============================================================
|
|
11
|
+
# run_update_OSTIA_daily_to_os.slurm
|
|
12
|
+
#
|
|
13
|
+
# Description: SLURM script to update the OSTIA daily
|
|
14
|
+
# time-series dataset in Icechunk repository.
|
|
15
|
+
#
|
|
16
|
+
# Created By: Ollie Tooth (oliver.tooth@noc.ac.uk)
|
|
17
|
+
# Created On: 2026-06-28
|
|
18
|
+
#
|
|
19
|
+
# ==============================================================
|
|
20
|
+
set -euo pipefail
|
|
21
|
+
|
|
22
|
+
# -- Python Environment -- #
|
|
23
|
+
# Activate miniconda environment:
|
|
24
|
+
source /dssgfs01/working/otooth/miniforge3/bin/activate
|
|
25
|
+
conda activate env_ods
|
|
26
|
+
|
|
27
|
+
# -- Send OSTIA daily time-series datasets to JASMIN OS -- #
|
|
28
|
+
echo "In Progress: Updating OSTIA Near-Real-Time Daily time-series in Icechunk..."
|
|
29
|
+
|
|
30
|
+
# python3 update_OSTIA_nrt_daily_to_os.py
|
|
31
|
+
python3 update_OSTIA_copernicus_nrt_daily_to_os.py
|
|
32
|
+
|
|
33
|
+
echo "Completed: Updated OSTIA Near-Real-Time Daily time-series in Icechunk."
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# =========================================================
|
|
2
|
+
# send_OSTIA_daily_climatology_to_os.py
|
|
3
|
+
#
|
|
4
|
+
# Script to write OSTIA North Atlantic daily climatologies
|
|
5
|
+
# to Icechunk repositories in JASMIN cloud object storage.
|
|
6
|
+
#
|
|
7
|
+
# Created By: Ollie Tooth (oliver.tooth@noc.ac.uk)
|
|
8
|
+
# =========================================================
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
import xarray as xr
|
|
13
|
+
import zarr
|
|
14
|
+
|
|
15
|
+
from OceanDataStore.cli import initialise_logging, send_to_icechunk
|
|
16
|
+
from OceanDataStore.data.utils import (
|
|
17
|
+
compute_cell_area,
|
|
18
|
+
compute_dx,
|
|
19
|
+
compute_dy,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def cyclic_moving_average(da: xr.DataArray,
|
|
26
|
+
dim: str = "clim_day",
|
|
27
|
+
window: int=31
|
|
28
|
+
) -> xr.DataArray:
|
|
29
|
+
"""
|
|
30
|
+
Compute a cyclic moving average of a DataArray using a
|
|
31
|
+
rolling mean with cyclic padding along dimension 'clim_day'.
|
|
32
|
+
|
|
33
|
+
Default window size is 31-day window (±15 days) for
|
|
34
|
+
daily climatology smoothing following Hobday et al. (2016)
|
|
35
|
+
methodology.
|
|
36
|
+
|
|
37
|
+
Parameters
|
|
38
|
+
----------
|
|
39
|
+
da : xr.DataArray
|
|
40
|
+
Input DataArray to be smoothed.
|
|
41
|
+
dim : str, optional
|
|
42
|
+
Dimension along which to compute the moving average.
|
|
43
|
+
Default is 'day'.
|
|
44
|
+
window : int, optional
|
|
45
|
+
Window size for the moving average. Default is 31.
|
|
46
|
+
|
|
47
|
+
Returns
|
|
48
|
+
-------
|
|
49
|
+
xr.DataArray
|
|
50
|
+
Smoothed DataArray with the same dimensions as the input.
|
|
51
|
+
"""
|
|
52
|
+
# Define padding size -> half window size:
|
|
53
|
+
pad = window // 2
|
|
54
|
+
|
|
55
|
+
# Define extended DataArray with cyclic padding:
|
|
56
|
+
extended = xr.concat(
|
|
57
|
+
[
|
|
58
|
+
da.isel({dim: slice(-pad, None)}),
|
|
59
|
+
da,
|
|
60
|
+
da.isel({dim: slice(0, pad)}),
|
|
61
|
+
],
|
|
62
|
+
dim=dim,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Define smoothed DataArray using rolling mean with cyclic padding:
|
|
66
|
+
smoothed = (
|
|
67
|
+
extended
|
|
68
|
+
.rolling({dim: window}, center=True)
|
|
69
|
+
.mean()
|
|
70
|
+
.isel({dim: slice(pad, -pad)})
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
smoothed[dim] = da[dim]
|
|
74
|
+
|
|
75
|
+
return smoothed
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main():
|
|
79
|
+
# ========== Initialise OceanDataStore Logging ========== #
|
|
80
|
+
initialise_logging()
|
|
81
|
+
|
|
82
|
+
# ========== Send to Icechunk Repository ========== #
|
|
83
|
+
bucket = "ostia"
|
|
84
|
+
exists = False
|
|
85
|
+
store_credentials_json = ".../credentials/jasmin_os_credentials.json"
|
|
86
|
+
branch = "main"
|
|
87
|
+
variable_commits = True
|
|
88
|
+
|
|
89
|
+
# Define climatology period:
|
|
90
|
+
start_yr = 1991
|
|
91
|
+
end_yr = 2020
|
|
92
|
+
|
|
93
|
+
logging.info(f"In Progress: Sending OSTIA daily climatology for {start_yr}-{end_yr} to Icechunk...")
|
|
94
|
+
# Open OSTIA dataset:
|
|
95
|
+
filepath = f"/dssgfs01/working/otooth/data/observations/OSTIA/climatology/ostia_sst_climatology_{start_yr}-{end_yr}.zarr"
|
|
96
|
+
ds = xr.open_dataset(filepath, engine='zarr')
|
|
97
|
+
|
|
98
|
+
# Update variable names, units, and attributes:
|
|
99
|
+
if "quantile" in ds.coords:
|
|
100
|
+
ds = ds.drop_vars(["quantile"])
|
|
101
|
+
|
|
102
|
+
# Add 31-day moving average smoothed variables:
|
|
103
|
+
ds["tos_mean_ma"] = cyclic_moving_average(ds["tos_mean"], window=31)
|
|
104
|
+
ds["tos_p10_ma"] = cyclic_moving_average(ds["tos_p10"], window=31)
|
|
105
|
+
ds["tos_p90_ma"] = cyclic_moving_average(ds["tos_p90"], window=31)
|
|
106
|
+
|
|
107
|
+
# Update variable long names:
|
|
108
|
+
ds["tos_mean"].attrs["long_name"] = "Daily Mean Sea Surface Temperature Climatology"
|
|
109
|
+
ds["tos_p10"].attrs["long_name"] = "Daily 10th Percentile Sea Surface Temperature Climatology"
|
|
110
|
+
ds["tos_p90"].attrs["long_name"] = "Daily 90th Percentile Sea Surface Temperature Climatology"
|
|
111
|
+
ds["tos_mean_ma"].attrs["long_name"] = "31-Day Moving Average of Daily Mean Sea Surface Temperature Climatology"
|
|
112
|
+
ds["tos_p10_ma"].attrs["long_name"] = "31-Day Moving Average of Daily 10th Percentile Sea Surface Temperature Climatology"
|
|
113
|
+
ds["tos_p90_ma"].attrs["long_name"] = "31-Day Moving Average of Daily 90th Percentile Sea Surface Temperature Climatology"
|
|
114
|
+
|
|
115
|
+
# Add ancillary variables:
|
|
116
|
+
ds['dx'] = compute_dx(ds)
|
|
117
|
+
ds['dy'] = compute_dy(ds)
|
|
118
|
+
ds['cell_area'] = compute_cell_area(ds)
|
|
119
|
+
|
|
120
|
+
# Update time bounds to reflect climatological period:
|
|
121
|
+
ds['time_bnds'] = xr.DataArray(
|
|
122
|
+
np.zeros((ds['clim_day'].size, 2), dtype='datetime64[ns]'),
|
|
123
|
+
dims=('clim_day', 'bnds'),
|
|
124
|
+
coords={'clim_day': ds['clim_day']},
|
|
125
|
+
)
|
|
126
|
+
ds['time_bnds'].data[:, 0] = (np.datetime64(f'{start_yr}-01-01', 'D') + (np.timedelta64(1, 'D') * np.arange(ds['clim_day'].size))).astype('datetime64[ns]')
|
|
127
|
+
ds['time_bnds'].data[:, 1] = (np.datetime64(f'{end_yr}-01-01', 'D') + (np.timedelta64(1, 'D') * np.arange(ds['clim_day'].size))).astype('datetime64[ns]')
|
|
128
|
+
|
|
129
|
+
# Update global attributes:
|
|
130
|
+
ds.attrs.clear()
|
|
131
|
+
ds = ds.assign_attrs({
|
|
132
|
+
"Conventions": "CF-1.4",
|
|
133
|
+
"title": f"OSTIA Reprocessed North Atlantic Daily Climatology ({start_yr}-{end_yr})",
|
|
134
|
+
"description": f"The Operational Sea Surface Temperature and Ice Analysis (OSTIA) Reprocessed - North Atlantic Sea Surface Temperature Daily Climatology ({start_yr}-{end_yr}). Climatology is defined following Hobday et al. (2016) methodology, where a ± 5-day pooling is used to calculate daily climatological mean and percentiles.",
|
|
135
|
+
"source": "Satellite observations: GCOM-W, AQUA, GOES<13,16>, MetoSat<08,09,10,11>, Sentinel-<3a,3b>, ERS<1,2>, Envisat, NOAA-<07,08,09,11,12,14,15,16,17,18,19,MTA>, GPM-Core, Suomi-NPP, NOAA-20.",
|
|
136
|
+
"dataset_type": "observation",
|
|
137
|
+
"product_type": "climatology",
|
|
138
|
+
"product_version": "3.2",
|
|
139
|
+
"institution": "Met Office, UK",
|
|
140
|
+
"citation": "Ocean OSTIA Sea Surface Temperature and Sea Ice Analysis. E.U. Copernicus Marine Service Information (CMEMS). Marine Data Store (MDS). DOI: 10.48670/moi-00168 (Accessed on 27 06 2026).",
|
|
141
|
+
"references": "Worsfold, M.; Good, S.; Atkinson, C.; Embury, O. Presenting a Long-Term, Reprocessed Dataset of Global Sea Surface Temperature Produced Using the OSTIA System. Remote Sens. 2024, 16, 3358. https://doi.org/10.3390/rs16183358",
|
|
142
|
+
"acknowledgement": "Generated using E.U. Copernicus Marine Service Information; https://doi.org/10.48670/moi-00168. These data were provided by GHRSST, Met Office and CMEMS.",
|
|
143
|
+
"license": "OSTIA data were obtained from https://doi.org/10.48670/moi-00168, and are provided under the Copernicus Marine Environment Monitoring Service Service Level Agreement (SLA) https://marine.copernicus.eu/user-corner/service-commitments-and-licence?pk_vid=42ac3e352be888641780994034c3bb6e",
|
|
144
|
+
"doi": "10.48670/moi-00168",
|
|
145
|
+
"platform": "gr",
|
|
146
|
+
"horizontal_grid_type": "regular rectilinear",
|
|
147
|
+
"horizontal_grid_resolution": "0.05 degree",
|
|
148
|
+
"aggregation": "mean, 10th percentile, 90th percentile",
|
|
149
|
+
"aggregation_frequency": "daily",
|
|
150
|
+
"status": "completed",
|
|
151
|
+
"update_frequency": "None",
|
|
152
|
+
"bbox": "[-44.975, 13.975, 31.025, 84.975]",
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
# Optimise chunk sizes for spatial analysis:
|
|
156
|
+
ds = ds.chunk({'clim_day': 2, 'latitude': 1080, 'longitude': 1180})
|
|
157
|
+
|
|
158
|
+
# Update variable encodings:
|
|
159
|
+
blosccodec = zarr.codecs.BloscCodec(cname="zstd", clevel=3, shuffle=zarr.codecs.BloscShuffle.shuffle)
|
|
160
|
+
for var in list(ds.data_vars) + list(ds.coords):
|
|
161
|
+
ds[var].encoding.clear()
|
|
162
|
+
ds[var].encoding['compressors'] = [blosccodec]
|
|
163
|
+
|
|
164
|
+
# Define prefix and commit message based on climatology period:
|
|
165
|
+
prefix = f"ostia_rep_na_{start_yr}_{end_yr}_daily_climatology"
|
|
166
|
+
commit_message = f"Added OSTIA SST Daily Climatology ({start_yr}-{end_yr})."
|
|
167
|
+
|
|
168
|
+
# Dask LocalCluster configuration:
|
|
169
|
+
config_kwargs = {
|
|
170
|
+
"temporary_directory":"/dssgfs01/working/otooth/Software/OceanDataStore/OceanDataStore/data/",
|
|
171
|
+
"local_directory":"/dssgfs01/working/otooth/Software/OceanDataStore/OceanDataStore/data/"
|
|
172
|
+
}
|
|
173
|
+
cluster_kwargs = {
|
|
174
|
+
"n_workers" : 20,
|
|
175
|
+
"threads_per_worker" : 1,
|
|
176
|
+
"memory_limit":"2GB"
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
send_to_icechunk(
|
|
180
|
+
file=ds,
|
|
181
|
+
bucket=bucket,
|
|
182
|
+
object_prefix=prefix,
|
|
183
|
+
store_credentials_json=store_credentials_json,
|
|
184
|
+
exists=exists,
|
|
185
|
+
append_dim='clim_day',
|
|
186
|
+
branch=branch,
|
|
187
|
+
commit_message=commit_message,
|
|
188
|
+
variable_commits=variable_commits,
|
|
189
|
+
dask_config_kwargs=config_kwargs,
|
|
190
|
+
dask_cluster_kwargs=cluster_kwargs,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
if __name__ == "__main__":
|
|
194
|
+
main()
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# =========================================================
|
|
2
|
+
# send_OSTIA_daily_to_os.py
|
|
3
|
+
#
|
|
4
|
+
# Script to write OSTIA daily data to Icechunk repositories
|
|
5
|
+
# in JASMIN cloud object storage.
|
|
6
|
+
#
|
|
7
|
+
# Created By: Ollie Tooth (oliver.tooth@noc.ac.uk)
|
|
8
|
+
# =========================================================
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
import xarray as xr
|
|
12
|
+
import zarr
|
|
13
|
+
|
|
14
|
+
from OceanDataStore.cli import initialise_logging, send_to_icechunk
|
|
15
|
+
from OceanDataStore.data.utils import (
|
|
16
|
+
compute_cell_area,
|
|
17
|
+
compute_dx,
|
|
18
|
+
compute_dy,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def main():
|
|
25
|
+
# ========== Initialise OceanDataStore Logging ========== #
|
|
26
|
+
initialise_logging()
|
|
27
|
+
|
|
28
|
+
# ========== Send to Icechunk Repository ========== #
|
|
29
|
+
bucket = "ostia"
|
|
30
|
+
exists = False
|
|
31
|
+
store_credentials_json = ".../credentials/jasmin_os_credentials.json"
|
|
32
|
+
branch = "main"
|
|
33
|
+
variable_commits = True
|
|
34
|
+
|
|
35
|
+
logging.info("In Progress: Sending OSTIA daily data to Icechunk...")
|
|
36
|
+
# Open OSTIA dataset:
|
|
37
|
+
data_path = "/dssgfs01/working/otooth/data/observations/OSTIA"
|
|
38
|
+
ds = xr.open_dataset(f"{data_path}/ostia_global_sst_daily_NA_nrt_2025_2026.zarr",
|
|
39
|
+
engine="zarr",
|
|
40
|
+
).sel(time=slice("2025-01", "2025-12"))
|
|
41
|
+
|
|
42
|
+
# Update variable units and attributes:
|
|
43
|
+
for var in ds.data_vars:
|
|
44
|
+
if "sst" in var:
|
|
45
|
+
# Transform units degK -> degC:
|
|
46
|
+
ds[var] = ds[var] - 273.15
|
|
47
|
+
ds[var].attrs["units"] = "degC"
|
|
48
|
+
|
|
49
|
+
# Rename variables:
|
|
50
|
+
ds = ds.rename({"analysed_sst": "tos",
|
|
51
|
+
"analysis_error": "tos_error",
|
|
52
|
+
"sea_ice_fraction": "siconc",
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
# Update variable long names:
|
|
56
|
+
ds["tos"].attrs["long_name"] = "Daily Mean Sea Surface Temperature"
|
|
57
|
+
ds["tos_error"].attrs["long_name"] = "Daily Standard Deviation Error Sea Surface Temperature"
|
|
58
|
+
ds["siconc"].attrs["long_name"] = "Daily Sea Ice Area Fraction"
|
|
59
|
+
|
|
60
|
+
# Add climatological day coordinate:
|
|
61
|
+
doy = ds['time'].dt.dayofyear
|
|
62
|
+
is_leap = ds['time'].dt.is_leap_year
|
|
63
|
+
after_feb28 = (~is_leap) & (doy >= 60)
|
|
64
|
+
clim_day = xr.where(after_feb28, doy + 1, doy)
|
|
65
|
+
ds = ds.assign_coords(clim_day=("time", clim_day.data))
|
|
66
|
+
ds["clim_day"].attrs["long_name"] = "Climatological Day of Year"
|
|
67
|
+
ds["clim_day"].attrs["description"] = "Climatological calendar day of year (1-366) with leap-year alignment for daily climatology calculations."
|
|
68
|
+
|
|
69
|
+
# Add ancillary variables:
|
|
70
|
+
ds['dx'] = compute_dx(ds)
|
|
71
|
+
ds['dy'] = compute_dy(ds)
|
|
72
|
+
ds['cell_area'] = compute_cell_area(ds)
|
|
73
|
+
|
|
74
|
+
# Update global attributes:
|
|
75
|
+
ds.attrs.clear()
|
|
76
|
+
ds = ds.assign_attrs({
|
|
77
|
+
"Conventions": "CF-1.4",
|
|
78
|
+
"title": "OSTIA Near-Real-Time North Atlantic Daily Timeseries",
|
|
79
|
+
"description": "The Operational Sea Surface Temperature and Ice Analysis (OSTIA) Near-Real-Time - North Atlantic Sea Surface Temperature & Sea Ice Area Fraction Daily Timeseries.",
|
|
80
|
+
"source": "Satellite observations: GCOM-W, AQUA, GOES<13,16>, MetoSat<08,09,10,11>, Sentinel-<3a,3b>, ERS<1,2>, Envisat, NOAA-<07,08,09,11,12,14,15,16,17,18,19,MTA>, GPM-Core, Suomi-NPP, NOAA-20.",
|
|
81
|
+
"dataset_type": "observation",
|
|
82
|
+
"product_type": "timeseries",
|
|
83
|
+
"product_version": "3.2",
|
|
84
|
+
"institution": "Met Office, UK",
|
|
85
|
+
"citation": "Ocean OSTIA Sea Surface Temperature and Sea Ice Analysis. E.U. Copernicus Marine Service Information (CMEMS). Marine Data Store (MDS). DOI: 10.48670/moi-00165 (Accessed on 27 06 2026).",
|
|
86
|
+
"references": "Good, S.; Fiedler, E.; Mao, C.; Martin, M.J.; Maycock, A.; Reid, R.; Roberts-Jones, J.; Searle, T.; Waters, J.; While, J.; Worsfold, M. The Current Configuration of the OSTIA System for Operational Production of Foundation Sea Surface Temperature and Ice Concentration Analyses. Remote Sens. 2020, 12, 720. doi: 10.3390/rs12040720. Donlon, C.J., Martin, M., Stark, J., Roberts-Jones, J., Fiedler, E., and Wimmer, W., 2012, The Operational Sea Surface Temperature and Sea Ice Analysis (OSTIA) system. Remote Sensing of the Environment. doi: 10.1016/j.rse.2010.10.017 2011. John D. Stark, Craig J. Donlon, Matthew J. Martin and Michael E. McCulloch, 2007, OSTIA : An operational, high resolution, real time, global sea surface temperature analysis system., Oceans 07 IEEE Aberdeen, conference proceedings. Marine challenges: coastline to deep sea. Aberdeen, Scotland.IEEE.",
|
|
87
|
+
"acknowledgement": "Generated using E.U. Copernicus Marine Service Information; https://doi.org/10.48670/moi-00165. These data were provided by GHRSST, Met Office and CMEMS.",
|
|
88
|
+
"license": "OSTIA data were obtained from https://doi.org/10.48670/moi-00165, and are provided under the Copernicus Marine Environment Monitoring Service Service Level Agreement (SLA) https://marine.copernicus.eu/user-corner/service-commitments-and-licence?pk_vid=42ac3e352be888641780994034c3bb6e",
|
|
89
|
+
"doi": "10.48670/moi-00165",
|
|
90
|
+
"platform": "gr",
|
|
91
|
+
"horizontal_grid_type": "regular rectilinear",
|
|
92
|
+
"horizontal_grid_resolution": "0.05 degree",
|
|
93
|
+
"aggregation": "mean",
|
|
94
|
+
"aggregation_frequency": "daily",
|
|
95
|
+
"status": "ongoing",
|
|
96
|
+
"update_frequency": "quarterly",
|
|
97
|
+
"bbox": "[-44.975, 13.975, 31.025, 84.975]",
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
# Optimise chunk sizes for time-series analysis:
|
|
101
|
+
# ds = ds.chunk({'time': ds['time'].size, 'latitude': 50, 'longitude': 50})
|
|
102
|
+
ds = ds.chunk({'time': 1, 'latitude': 1080, 'longitude': 1180})
|
|
103
|
+
|
|
104
|
+
# Update variable encodings:
|
|
105
|
+
blosccodec = zarr.codecs.BloscCodec(cname="zstd", clevel=3, shuffle=zarr.codecs.BloscShuffle.shuffle)
|
|
106
|
+
for var in list(ds.data_vars) + list(ds.coords):
|
|
107
|
+
ds[var].encoding.clear()
|
|
108
|
+
ds[var].encoding['compressors'] = [blosccodec]
|
|
109
|
+
|
|
110
|
+
# Define prefix and commit message based on timeseries period:
|
|
111
|
+
# prefix = "ostia_nrt_na_daily_timeseries"
|
|
112
|
+
prefix = "ostia_nrt_na_daily_spatial"
|
|
113
|
+
commit_message = "Added OSTIA Near-Real-Time North Atlantic Daily Timeseries (2025-01-01 - 2025-12-31)."
|
|
114
|
+
|
|
115
|
+
# Dask LocalCluster configuration:
|
|
116
|
+
config_kwargs = {
|
|
117
|
+
"temporary_directory":"/dssgfs01/working/otooth/Software/OceanDataStore/OceanDataStore/data/OSTIA/",
|
|
118
|
+
"local_directory":"/dssgfs01/working/otooth/Software/OceanDataStore/OceanDataStore/data/OSTIA/"
|
|
119
|
+
}
|
|
120
|
+
cluster_kwargs = {
|
|
121
|
+
"n_workers" : 20,
|
|
122
|
+
"threads_per_worker" : 1,
|
|
123
|
+
"memory_limit":"6GB"
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
send_to_icechunk(
|
|
127
|
+
file=ds,
|
|
128
|
+
bucket=bucket,
|
|
129
|
+
object_prefix=prefix,
|
|
130
|
+
store_credentials_json=store_credentials_json,
|
|
131
|
+
exists=exists,
|
|
132
|
+
append_dim='time',
|
|
133
|
+
branch=branch,
|
|
134
|
+
commit_message=commit_message,
|
|
135
|
+
variable_commits=variable_commits,
|
|
136
|
+
dask_config_kwargs=config_kwargs,
|
|
137
|
+
dask_cluster_kwargs=cluster_kwargs,
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
if __name__ == "__main__":
|
|
141
|
+
main()
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# =========================================================
|
|
2
|
+
# send_OSTIA_rep_daily_to_os.py
|
|
3
|
+
#
|
|
4
|
+
# Script to write OSTIA reprocessed daily data to Icechunk
|
|
5
|
+
# repositories in JASMIN cloud object storage.
|
|
6
|
+
#
|
|
7
|
+
# Created By: Ollie Tooth (oliver.tooth@noc.ac.uk)
|
|
8
|
+
# =========================================================
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
import xarray as xr
|
|
12
|
+
import zarr
|
|
13
|
+
|
|
14
|
+
from OceanDataStore.cli import initialise_logging, send_to_icechunk
|
|
15
|
+
from OceanDataStore.data.utils import (
|
|
16
|
+
compute_cell_area,
|
|
17
|
+
compute_dx,
|
|
18
|
+
compute_dy,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def main():
|
|
25
|
+
# ========== Initialise OceanDataStore Logging ========== #
|
|
26
|
+
initialise_logging()
|
|
27
|
+
|
|
28
|
+
# ========== Send to Icechunk Repository ========== #
|
|
29
|
+
bucket = "ostia"
|
|
30
|
+
exists = False
|
|
31
|
+
store_credentials_json = ".../credentials/jasmin_os_credentials.json"
|
|
32
|
+
branch = "main"
|
|
33
|
+
variable_commits = True
|
|
34
|
+
|
|
35
|
+
logging.info("In Progress: Sending OSTIA daily data to Icechunk...")
|
|
36
|
+
# Open OSTIA dataset:
|
|
37
|
+
data_path = "/dssgfs01/working/otooth/data/observations/OSTIA"
|
|
38
|
+
ds = xr.open_mfdataset([f"{data_path}/ostia_global_sst_daily_NA_1981_1989.zarr",
|
|
39
|
+
f"{data_path}/ostia_global_sst_daily_NA_1990_1999.zarr",
|
|
40
|
+
f"{data_path}/ostia_global_sst_daily_NA_2000_2025.zarr"],
|
|
41
|
+
engine="zarr",
|
|
42
|
+
parallel=True
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Update variable units and attributes:
|
|
47
|
+
for var in ds.data_vars:
|
|
48
|
+
if "sst" in var:
|
|
49
|
+
# Transform units degK -> degC:
|
|
50
|
+
ds[var] = ds[var] - 273.15
|
|
51
|
+
ds[var].attrs["units"] = "degC"
|
|
52
|
+
|
|
53
|
+
# Rename variables:
|
|
54
|
+
ds = ds.rename({"analysed_sst": "tos",
|
|
55
|
+
"analysis_error": "tos_error",
|
|
56
|
+
"sea_ice_fraction": "siconc",
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
# Update variable long names:
|
|
60
|
+
ds["tos"].attrs["long_name"] = "Daily Mean Sea Surface Temperature"
|
|
61
|
+
ds["tos_error"].attrs["long_name"] = "Daily Standard Deviation Error Sea Surface Temperature"
|
|
62
|
+
ds["siconc"].attrs["long_name"] = "Daily Sea Ice Area Fraction"
|
|
63
|
+
|
|
64
|
+
# Add climatological day coordinate:
|
|
65
|
+
doy = ds['time'].dt.dayofyear
|
|
66
|
+
is_leap = ds['time'].dt.is_leap_year
|
|
67
|
+
after_feb28 = (~is_leap) & (doy >= 60)
|
|
68
|
+
clim_day = xr.where(after_feb28, doy + 1, doy)
|
|
69
|
+
ds = ds.assign_coords(clim_day=("time", clim_day.data))
|
|
70
|
+
ds["clim_day"].attrs["long_name"] = "Climatological Day of Year"
|
|
71
|
+
ds["clim_day"].attrs["description"] = "Climatological calendar day of year (1-366) with leap-year alignment for daily climatology calculations."
|
|
72
|
+
|
|
73
|
+
# Add ancillary variables:
|
|
74
|
+
ds['dx'] = compute_dx(ds)
|
|
75
|
+
ds['dy'] = compute_dy(ds)
|
|
76
|
+
ds['cell_area'] = compute_cell_area(ds)
|
|
77
|
+
|
|
78
|
+
# Update global attributes:
|
|
79
|
+
ds.attrs.clear()
|
|
80
|
+
ds = ds.assign_attrs({
|
|
81
|
+
"Conventions": "CF-1.4",
|
|
82
|
+
"title": "OSTIA Reprocessed North Atlantic Daily Timeseries",
|
|
83
|
+
"description": "The Operational Sea Surface Temperature and Ice Analysis (OSTIA) Reprocessed - North Atlantic Sea Surface Temperature & Sea Ice Area Fraction Daily Timeseries.",
|
|
84
|
+
"source": "Satellite observations: GCOM-W, AQUA, GOES<13,16>, MetoSat<08,09,10,11>, Sentinel-<3a,3b>, ERS<1,2>, Envisat, NOAA-<07,08,09,11,12,14,15,16,17,18,19,MTA>, GPM-Core, Suomi-NPP, NOAA-20.",
|
|
85
|
+
"dataset_type": "observation",
|
|
86
|
+
"product_type": "timeseries",
|
|
87
|
+
"product_version": "3.2",
|
|
88
|
+
"institution": "Met Office, UK",
|
|
89
|
+
"citation": "Ocean OSTIA Sea Surface Temperature and Sea Ice Analysis. E.U. Copernicus Marine Service Information (CMEMS). Marine Data Store (MDS). DOI: 10.48670/moi-00168 (Accessed on 27 06 2026).",
|
|
90
|
+
"references": "Worsfold, M.; Good, S.; Atkinson, C.; Embury, O. Presenting a Long-Term, Reprocessed Dataset of Global Sea Surface Temperature Produced Using the OSTIA System. Remote Sens. 2024, 16, 3358. https://doi.org/10.3390/rs16183358",
|
|
91
|
+
"acknowledgement": "Generated using E.U. Copernicus Marine Service Information; https://doi.org/10.48670/moi-00168. These data were provided by GHRSST, Met Office and CMEMS.",
|
|
92
|
+
"license": "OSTIA data were obtained from https://doi.org/10.48670/moi-00168, and are provided under the Copernicus Marine Environment Monitoring Service Service Level Agreement (SLA) https://marine.copernicus.eu/user-corner/service-commitments-and-licence?pk_vid=42ac3e352be888641780994034c3bb6e",
|
|
93
|
+
"doi": "10.48670/moi-00168",
|
|
94
|
+
"platform": "gr",
|
|
95
|
+
"horizontal_grid_type": "regular rectilinear",
|
|
96
|
+
"horizontal_grid_resolution": "0.05 degree",
|
|
97
|
+
"aggregation": "mean",
|
|
98
|
+
"aggregation_frequency": "daily",
|
|
99
|
+
"status": "ongoing",
|
|
100
|
+
"update_frequency": "biannually",
|
|
101
|
+
"bbox": "[-44.975, 13.975, 31.025, 84.975]",
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
# Optimise chunk sizes for time-series analysis:
|
|
105
|
+
# ds = ds.chunk({'time': 3660, 'latitude': 50, 'longitude': 50})
|
|
106
|
+
ds = ds.chunk({'time': 2, 'latitude': 1080, 'longitude': 1180})
|
|
107
|
+
|
|
108
|
+
# Update variable encodings:
|
|
109
|
+
blosccodec = zarr.codecs.BloscCodec(cname="zstd", clevel=3, shuffle=zarr.codecs.BloscShuffle.shuffle)
|
|
110
|
+
for var in list(ds.data_vars) + list(ds.coords):
|
|
111
|
+
ds[var].encoding.clear()
|
|
112
|
+
ds[var].encoding['compressors'] = [blosccodec]
|
|
113
|
+
|
|
114
|
+
# Define prefix and commit message based on timeseries period:
|
|
115
|
+
# prefix = "ostia_rep_na_daily_timeseries"
|
|
116
|
+
prefix = "ostia_rep_na_daily_spatial"
|
|
117
|
+
commit_message = "Added OSTIA Reprocessed North Atlantic Daily Timeseries (1981-10-01 - 2025-12-18)."
|
|
118
|
+
|
|
119
|
+
# Dask LocalCluster configuration:
|
|
120
|
+
config_kwargs = {
|
|
121
|
+
"temporary_directory":"/dssgfs01/working/otooth/Software/OceanDataStore/OceanDataStore/data/",
|
|
122
|
+
"local_directory":"/dssgfs01/working/otooth/Software/OceanDataStore/OceanDataStore/data/"
|
|
123
|
+
}
|
|
124
|
+
cluster_kwargs = {
|
|
125
|
+
"n_workers" : 25,
|
|
126
|
+
"threads_per_worker" : 1,
|
|
127
|
+
"memory_limit":"6GB"
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
send_to_icechunk(
|
|
131
|
+
file=ds,
|
|
132
|
+
bucket=bucket,
|
|
133
|
+
object_prefix=prefix,
|
|
134
|
+
store_credentials_json=store_credentials_json,
|
|
135
|
+
exists=exists,
|
|
136
|
+
append_dim='time',
|
|
137
|
+
branch=branch,
|
|
138
|
+
commit_message=commit_message,
|
|
139
|
+
variable_commits=variable_commits,
|
|
140
|
+
dask_config_kwargs=config_kwargs,
|
|
141
|
+
dask_cluster_kwargs=cluster_kwargs,
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
if __name__ == "__main__":
|
|
145
|
+
main()
|