Working with HYCOM data#
This notebook walks through common xarray operations on HYCOM output: slicing, regional masking, curvilinear plotting, time-based aggregations, and groupby for seasonal analysis.
We open the archive lazily with chunks={"time": 1} so the examples work on any size of archive without loading everything into memory (see Lazy loading & chunking to learn more about chunk sizes and lazy loading).
import xhycom
GRID_PATH = "/cluster/home/nlo043/NERSC-HYCOM-CICE/TP2a0.10/topo/regional.grid"
DATA_PATH = "/nird/datalake/NS9481K/shuang/TP2_output/expt_02.8/"
# Open the full archive lazily — no data read until .compute()
ds = xhycom.open_mfdataset(DATA_PATH + "archm.2020*", grid=GRID_PATH, chunks={"time": 1})
ds
<xarray.Dataset> Size: 1TB
Dimensions: (y: 380, x: 400, time: 366, k: 50, ki: 51)
Coordinates:
lon (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
* time (time) object 3kB 2020-01-01 00:00:00 ... 2020-12-31 00:00:00
* k (k) int64 400B 1 2 3 4 5 6 7 8 9 ... 42 43 44 45 46 47 48 49 50
dens (k) float64 400B dask.array<chunksize=(50,), meta=np.ndarray>
* ki (ki) int64 408B 0 1 2 3 4 5 6 7 8 ... 42 43 44 45 46 47 48 49 50
Dimensions without coordinates: y, x
Data variables: (12/83)
montg1 (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
srfhgt (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
oneta (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
surflx (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
wtrflx (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
salflx (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
... ...
CO2_wind (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
ECO_bots (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
surface__1 (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
surface__2 (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
si_u (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
si_v (time, y, x) float64 445MB dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
Attributes:
iversn: 23
iexpt: 28
yrflag: 3- y: 380
- x: 400
- time: 366
- k: 50
- ki: 51
- lon(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (T-point)
- units :
- degrees_east
- standard_name :
- longitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (T-point)
- units :
- degrees_north
- standard_name :
- latitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (U-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (U-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (V-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (V-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - time(time)object2020-01-01 00:00:00 ... 2020-12-...
- long_name :
- time
- axis :
- T
array([cftime.DatetimeGregorian(2020, 1, 1, 0, 0, 0, 0, has_year_zero=False), cftime.DatetimeGregorian(2020, 1, 2, 0, 0, 0, 0, has_year_zero=False), cftime.DatetimeGregorian(2020, 1, 3, 0, 0, 0, 0, has_year_zero=False), ..., cftime.DatetimeGregorian(2020, 12, 29, 0, 0, 0, 0, has_year_zero=False), cftime.DatetimeGregorian(2020, 12, 30, 0, 0, 0, 0, has_year_zero=False), cftime.DatetimeGregorian(2020, 12, 31, 0, 0, 0, 0, has_year_zero=False)], shape=(366,), dtype=object) - k(k)int641 2 3 4 5 6 7 ... 45 46 47 48 49 50
- long_name :
- layer index
- units :
- 1
- axis :
- Z
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]) - dens(k)float64dask.array<chunksize=(50,), meta=np.ndarray>
- long_name :
- target sigma-2 layer density
- units :
- kg m-3
Array Chunk Bytes 400 B 400 B Shape (50,) (50,) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - ki(ki)int640 1 2 3 4 5 6 ... 45 46 47 48 49 50
- long_name :
- layer interface index
- units :
- 1
- axis :
- Z
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50])
- montg1(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- Montgomery potential
- units :
- m2 s-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - srfhgt(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sea surface height
- units :
- Pa
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - oneta(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- free surface elevation
- units :
- m
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - surflx(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- net surface heat flux
- units :
- W m-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - wtrflx(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- net surface freshwater flux
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - salflx(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- surface salt flux
- units :
- PSU m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - bl_dpth(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- boundary layer depth
- units :
- Pa
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - mix_dpth(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- mixed layer depth
- units :
- Pa
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - tmix(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- mixed layer temperature
- units :
- degC
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - smix(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- mixed layer salinity
- units :
- PSU
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - thmix(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- mixed layer thickness
- units :
- Pa
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - umix(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- mixed layer x velocity
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - vmix(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- mixed layer y velocity
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - kemix(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- mixed layer kinetic energy
- units :
- m2 s-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - covice(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sea ice coverage fraction
- units :
- 1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - thkice(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sea ice thickness
- units :
- m
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - temice(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sea ice surface temperature
- units :
- degC
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - u_btrop(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- barotropic x velocity
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - v_btrop(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- barotropic y velocity
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - kebtrop(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- barotropic kinetic energy
- units :
- m2 s-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - u-vel.(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- sea water x velocity
- units :
- m s-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - v-vel.(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- sea water y velocity
- units :
- m s-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - k.e.(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- kinetic energy
- units :
- m2 s-2
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - thknss(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- layer pressure thickness
- units :
- Pa
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - temp(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- sea water potential temperature
- units :
- degC
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - salin(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- sea water salinity
- units :
- PSU
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - density(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- sea water potential density (sigma-2)
- units :
- kg m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_c(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- dissolved inorganic carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_TA(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- total alkalinity
- units :
- mmol eq m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_no3(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- nitrate
- units :
- mmol N m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_nh4(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- ammonium
- units :
- mmol N m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_pho(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- phosphate
- units :
- mmol P m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_sil(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- silicate
- units :
- mmol Si m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_oxy(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- dissolved oxygen
- units :
- mmol O m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_fla(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- flagellate carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_dia(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- diatom carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_ccl(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- coccolithophore carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_cclc(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- coccolithophore calcite carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_caco(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- particulate inorganic carbon (calcite)
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_diac(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- diatom calcite carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_flac(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- flagellate calcite carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_micr(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- microzooplankton carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_meso(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- mesozooplankton carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_det(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- detritus carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_opa(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- opal (biogenic silica)
- units :
- mmol Si m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_dom(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- dissolved organic matter carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_dsnk(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- detritus sinking flux
- units :
- mmol C m-2 s-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_pH(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- seawater pH
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_pCO2(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- partial pressure of CO2
- units :
- uatm
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_Carb_1(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- carbonate concentration
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_BiCa(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- bicarbonate concentration
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_Carb_2(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- carbonate concentration
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_Om_c(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- calcite saturation state (Omega)
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_Om_a(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- aragonite saturation state (Omega)
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_prim(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- primary production
- units :
- mmol C m-3 s-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_secp(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- secondary production
- units :
- mmol C m-3 s-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_netp(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- net primary production
- units :
- mmol C m-3 s-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_parm(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- BGC parameter field
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_Nlim(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- nitrogen limitation factor
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_Plim(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- phosphorus limitation factor
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_Slim(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- silicate limitation factor
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_Llim(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- light limitation factor
- units :
- 1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_deni(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- denitrification
- units :
- mmol N m-3 s-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_snks(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- sinking rate
- units :
- m d-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_c2ch_1(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- carbon to chlorophyll ratio
- units :
- g C g-1 Chl
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_c2ch_2(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- carbon to chlorophyll ratio
- units :
- g C g-1 Chl
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_c2ch_3(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- carbon to chlorophyll ratio
- units :
- g C g-1 Chl
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - light_sw(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- shortwave irradiance in water
- units :
- W m-2
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - light_pa(time, ki, y, x)float64dask.array<chunksize=(1, 51, 380, 400), meta=np.ndarray>
- long_name :
- PAR irradiance
- units :
- W m-2
Array Chunk Bytes 21.14 GiB 59.14 MiB Shape (366, 51, 380, 400) (1, 51, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - attenuat(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- light attenuation coefficient
- units :
- m-1
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - total_ch(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- total chlorophyll
- units :
- mg Chl m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - total_ca(time, k, y, x)float64dask.array<chunksize=(1, 50, 380, 400), meta=np.ndarray>
- long_name :
- total carbon
- units :
- mmol C m-3
Array Chunk Bytes 20.72 GiB 57.98 MiB Shape (366, 50, 380, 400) (1, 50, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_sed4(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sediment pool 4
- units :
- mmol m-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_sed1(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sediment pool 1
- units :
- mmol m-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_sed2(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sediment pool 2
- units :
- mmol m-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_sed3(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sediment pool 3
- units :
- mmol m-2
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_fair(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- air-sea CO2 flux
- units :
- mmol C m-2 d-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - CO2_wind(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- wind speed for gas exchange
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - ECO_bots(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- bottom sediment flux
- units :
- 1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - surface__1(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - surface__2(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - si_u(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sea ice x velocity
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray - si_v(time, y, x)float64dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
- long_name :
- sea ice y velocity
- units :
- m s-1
Array Chunk Bytes 424.44 MiB 1.16 MiB Shape (366, 380, 400) (1, 380, 400) Dask graph 366 chunks in 733 graph layers Data type float64 numpy.ndarray
- iversn :
- 23
- iexpt :
- 28
- yrflag :
- 3
ds["srfhgt"].mean(dim=["y", "x"]).plot()
[<matplotlib.lines.Line2D at 0x1548cf3c69d0>]
ds["mix_dpth"].mean(dim=["y", "x"]).plot()
[<matplotlib.lines.Line2D at 0x154760a38f50>]
Physical units and derived fields#
By default the data come back exactly as stored on disk, so some fields are in
HYCOM’s native units — sea-surface height as geopotential, and layer thickness /
mixed-layer depth as pressure in Pa. Pass postprocess=True to convert these to
physical units and add a few derived fields:
Field |
Native |
|
|---|---|---|
|
geopotential (m² s⁻²) |
sea-surface height in m (÷ g = 9.806) |
|
pressure (Pa) |
m (÷ onem = 9806) |
|
baroclinic ( |
total current (+ barotropic), tagged |
|
— |
|
|
— |
1 ocean / 0 land, from the bathymetry |
You can also apply it to an already-open dataset with xhycom.postprocess(ds).
A note on velocities. HYCOM writes u-vel./v-vel. differently per file type: an
instantaneous archv stores the baroclinic layer velocity, so the total current is
u-vel. + u_btrop; a mean archm already stores the total (the barotropic part is
summed in online). postprocess=True reconciles both to the total current — adding
the barotropic part for archv, annotating archm — and records the provenance in
ds.attrs["archive_type"] ("instantaneous" / "mean") and da.attrs["hycom_velocity"]
("total" / "baroclinic"). If you select velocities via variables=, the barotropic
u_btrop/v_btrop are pulled in automatically to build the total, then dropped.
# Same archive with native units converted + derived fields added.
# Kept on a separate handle so the rest of the notebook keeps the raw `ds`.
ds_pp = xhycom.open_mfdataset(DATA_PATH + "archm.2020*", grid=GRID_PATH, chunks={"time": 1}, postprocess=True)
ds_pp["srfhgt"].mean(dim=["y", "x"]).plot()
[<matplotlib.lines.Line2D at 0x1548b0ad3390>]
ds_pp["mix_dpth"].mean(dim=["y", "x"]).plot()
[<matplotlib.lines.Line2D at 0x154719edddd0>]
# postprocess reconciles u-vel./v-vel. to the total current, and records how:
ds_pp.attrs["archive_type"], ds_pp["u-vel."].attrs["hycom_velocity"]
Slicing#
xarray’s isel (index-based) and sel (label-based) selectors work directly.
# Surface temperature at the first time step
sst = ds["temp"].isel(time=0, k=0)
sst
<xarray.DataArray 'temp' (y: 380, x: 400)> Size: 1MB
dask.array<getitem, shape=(380, 400), dtype=float64, chunksize=(380, 400), chunktype=numpy.ndarray>
Coordinates:
lon (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
k int64 8B 1
time object 8B 2020-01-01 00:00:00
dens float64 8B dask.array<chunksize=(), meta=np.ndarray>
Dimensions without coordinates: y, x
Attributes:
long_name: sea water potential temperature
units: degC- y: 380
- x: 400
- dask.array<chunksize=(380, 400), meta=np.ndarray>
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 734 graph layers Data type float64 numpy.ndarray - lon(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (T-point)
- units :
- degrees_east
- standard_name :
- longitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (T-point)
- units :
- degrees_north
- standard_name :
- latitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (U-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (U-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (V-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (V-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - k()int641
- long_name :
- layer index
- units :
- 1
- axis :
- Z
array(1)
- time()object2020-01-01 00:00:00
- long_name :
- time
- axis :
- T
array(cftime.DatetimeGregorian(2020, 1, 1, 0, 0, 0, 0, has_year_zero=False), dtype=object) - dens()float64dask.array<chunksize=(), meta=np.ndarray>
- long_name :
- target sigma-2 layer density
- units :
- kg m-3
Array Chunk Bytes 8 B 8 B Shape () () Dask graph 1 chunks in 2 graph layers Data type float64 numpy.ndarray
- long_name :
- sea water potential temperature
- units :
- degC
sst.plot()
<matplotlib.collections.QuadMesh at 0x1548b2f34390>
temp_at_fixed_dens = ds["temp"].isel(time=0).isel(k=13)
temp_at_fixed_dens
<xarray.DataArray 'temp' (y: 380, x: 400)> Size: 1MB
dask.array<getitem, shape=(380, 400), dtype=float64, chunksize=(380, 400), chunktype=numpy.ndarray>
Coordinates:
lon (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
k int64 8B 14
time object 8B 2020-01-01 00:00:00
dens float64 8B dask.array<chunksize=(), meta=np.ndarray>
Dimensions without coordinates: y, x
Attributes:
long_name: sea water potential temperature
units: degC- y: 380
- x: 400
- dask.array<chunksize=(380, 400), meta=np.ndarray>
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 735 graph layers Data type float64 numpy.ndarray - lon(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (T-point)
- units :
- degrees_east
- standard_name :
- longitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (T-point)
- units :
- degrees_north
- standard_name :
- latitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (U-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (U-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (V-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (V-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - k()int6414
- long_name :
- layer index
- units :
- 1
- axis :
- Z
array(14)
- time()object2020-01-01 00:00:00
- long_name :
- time
- axis :
- T
array(cftime.DatetimeGregorian(2020, 1, 1, 0, 0, 0, 0, has_year_zero=False), dtype=object) - dens()float64dask.array<chunksize=(), meta=np.ndarray>
- long_name :
- target sigma-2 layer density
- units :
- kg m-3
Array Chunk Bytes 8 B 8 B Shape () () Dask graph 1 chunks in 2 graph layers Data type float64 numpy.ndarray
- long_name :
- sea water potential temperature
- units :
- degC
temp_at_fixed_dens.plot()
<matplotlib.collections.QuadMesh at 0x154718008390>
# Select by layer density instead of layer index
the_same_temp = ds["temp"].isel(time=0).sel(dens=27.0, method="nearest")
the_same_temp.plot()
<matplotlib.collections.QuadMesh at 0x154903f33d10>
Regional analysis#
HYCOM uses a curvilinear grid, so lon and lat are 2-D arrays — you cannot use .sel(lon=..., lat=...) for spatial subsetting. Instead, build a boolean mask from the coordinate arrays and apply it with .where().
# Boolean mask: True inside the region, False outside
mask = (ds.lon > -30) & (ds.lon < 30) & (ds.lat > 50) & (ds.lat < 80)
mask.plot(cmap='RdYlGn');
Apply the mask to a variable — grid points outside the region become NaN:
sst_region = ds['temp'].isel(k=0).where(mask)
sst_region.isel(time=0).plot();
With the mask applied, reductions like .mean() automatically ignore the masked-out (NaN) points. Here we compute a time series of mean surface temperature inside the region:
sst_ts = sst_region.mean(dim=['y', 'x']).compute()
sst_ts.plot()
import matplotlib.pyplot as plt
plt.ylabel('Mean SST (degC)')
plt.title('Regional mean surface temperature');
The same pattern works for any variable. For example, sea-ice extent (fraction of the masked area with ice concentration above 15 %):
ice_extent = (ds['covice'].where(mask) > 0.15).mean(dim=['y', 'x']).compute()
ice_extent.plot()
plt.ylabel('Ice extent fraction')
plt.title('Sea-ice extent in masked region (covice > 0.15);');
Seasonal and monthly analysis with groupby#
groupby splits the time axis by a label — calendar month, season, year — and applies a reduction. Everything stays lazy until .compute() is called.
# 4-season mean of surface temperature (reads all files on .compute())
sst_seasonal = ds["temp"].isel(k=0).groupby("time.season").mean()
sst_seasonal
<xarray.DataArray 'temp' (season: 4, y: 380, x: 400)> Size: 5MB
dask.array<stack, shape=(4, 380, 400), dtype=float64, chunksize=(1, 380, 400), chunktype=numpy.ndarray>
Coordinates:
* season (season) object 32B 'DJF' 'JJA' 'MAM' 'SON'
lon (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
k int64 8B 1
dens float64 8B dask.array<chunksize=(), meta=np.ndarray>
Dimensions without coordinates: y, x
Attributes:
long_name: sea water potential temperature
units: degC- season: 4
- y: 380
- x: 400
- dask.array<chunksize=(1, 380, 400), meta=np.ndarray>
Array Chunk Bytes 4.64 MiB 1.16 MiB Shape (4, 380, 400) (1, 380, 400) Dask graph 4 chunks in 759 graph layers Data type float64 numpy.ndarray - season(season)object'DJF' 'JJA' 'MAM' 'SON'
array(['DJF', 'JJA', 'MAM', 'SON'], dtype=object)
- lon(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (T-point)
- units :
- degrees_east
- standard_name :
- longitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (T-point)
- units :
- degrees_north
- standard_name :
- latitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (U-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (U-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (V-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (V-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - k()int641
- long_name :
- layer index
- units :
- 1
- axis :
- Z
array(1)
- dens()float64dask.array<chunksize=(), meta=np.ndarray>
- long_name :
- target sigma-2 layer density
- units :
- kg m-3
Array Chunk Bytes 8 B 8 B Shape () () Dask graph 1 chunks in 2 graph layers Data type float64 numpy.ndarray
- long_name :
- sea water potential temperature
- units :
- degC
sst_seasonal.plot(col="season", col_wrap=2)
<xarray.plot.facetgrid.FacetGrid at 0x15484a405a50>
March sea-ice concentration#
Monthly groupby lets you compute a climatological mean for any specific month. Here we extract March (month 3) mean sea-ice concentration across all years.
# Climatological March sea-ice concentration
ice_monthly = ds["covice"].groupby("time.month").mean()
march_ice = ice_monthly.sel(month=3)
march_ice
<xarray.DataArray 'covice' (y: 380, x: 400)> Size: 1MB
dask.array<getitem, shape=(380, 400), dtype=float64, chunksize=(380, 400), chunktype=numpy.ndarray>
Coordinates:
lon (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_u (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lon_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
lat_v (y, x) float64 1MB dask.array<chunksize=(380, 400), meta=np.ndarray>
month int64 8B 3
Dimensions without coordinates: y, x
Attributes:
long_name: sea ice coverage fraction
units: 1- y: 380
- x: 400
- dask.array<chunksize=(380, 400), meta=np.ndarray>
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 795 graph layers Data type float64 numpy.ndarray - lon(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (T-point)
- units :
- degrees_east
- standard_name :
- longitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (T-point)
- units :
- degrees_north
- standard_name :
- latitude
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (U-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_u(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (U-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lon_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- longitude (V-point)
- units :
- degrees_east
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - lat_v(y, x)float64dask.array<chunksize=(380, 400), meta=np.ndarray>
- long_name :
- latitude (V-point)
- units :
- degrees_north
Array Chunk Bytes 1.16 MiB 1.16 MiB Shape (380, 400) (380, 400) Dask graph 1 chunks in 1 graph layer Data type float64 numpy.ndarray - month()int643
array(3)
- long_name :
- sea ice coverage fraction
- units :
- 1
march_ice.plot(cmap="Blues", vmin=0, vmax=1)
<matplotlib.collections.QuadMesh at 0x15450cfef690>
Anomalies#
Subtract the climatological monthly mean to isolate interannual or seasonal variability.
import matplotlib.pyplot as plt
# Climatological monthly mean
clim = ds['temp'].isel(k=0).groupby('time.month').mean()
# Anomaly: each time step minus its climatological month
anom = ds['temp'].isel(k=0).groupby('time.month') - clim
# Plot the anomaly for one time step
anom.isel(time=0).compute().plot(cmap='RdBu_r', center=0)
plt.title('SST anomaly (first month)');
Mixed layer depth#
mix_dpth is stored in Pa — divide by ~9806 to convert to metres. (With
postprocess=True this conversion is done for you, so ds_pp["mix_dpth"] is
already in metres and the manual / 9806.0 below is unnecessary.)
# Mixed layer depth in metres, time series averaged over the domain
mld_m = (ds['mix_dpth'] / 9806.0).mean(dim=['y', 'x']).compute()
mld_m.attrs['units'] = 'm'
mld_m.plot()
plt.ylabel('Mixed layer depth (m)')
plt.gca().invert_yaxis() # depth increases downward
plt.title('Domain-mean mixed layer depth');
Saving a subset to NetCDF#
Use to_netcdf() to write a subset of variables or time steps to a file for sharing or use with tools that do not read .ab format directly.
# Write the top 10 layers of T and S for the first 12 time slices
subset = ds[['temp', 'salin']].isel(time=slice(0, 12))
subset.compute().to_netcdf('hycom_TS_2020.nc')
print('Saved hycom_TS_2020.nc')
Saved hycom_TS_2020.nc
Plotting#
sss = ds["salin"].isel(time=0, k=0)
For quick plots, use xarray’s in-built plotting.
sss.plot()
<matplotlib.collections.QuadMesh at 0x15484a74a150>
Because lon and lat are 2-D curvilinear arrays, use pcolormesh directly rather than xarray’s .plot(). U-point and V-point variables carry lon_u/lat_u and lon_v/lat_v coordinates.
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import numpy as np
def ArcticMap():
fig, ax = plt.subplots(
figsize=(8, 8),
subplot_kw={"projection": ccrs.NorthPolarStereo(central_longitude=0.0)},
)
ax.set_extent([-180, 180, 48, 90], crs=ccrs.PlateCarree())
ax.add_feature(cfeature.LAND, facecolor=cfeature.COLORS["land"], edgecolor="grey", zorder=2)
ax.add_feature(cfeature.COASTLINE.with_scale("50m"), edgecolor="grey", linewidth=0.4, zorder=3)
ax.gridlines()
return fig, ax
def pcolormesh_curvilinear(lon, lat, data, ax=None, **kwargs):
proj = ax.projection
pxy = proj.transform_points(ccrs.PlateCarree(), lon, lat)
px, py = pxy[:, :, 0], pxy[:, :, 1]
invalid = ~np.isfinite(px) | ~np.isfinite(py)
px = np.where(invalid, 0.0, px)
py = np.where(invalid, 0.0, py)
data = np.where(invalid, np.nan, data)
return ax.pcolormesh(px, py, data, **kwargs)
fig, ax = ArcticMap()
p = pcolormesh_curvilinear(sss.lon.values, sss.lat.values, sss.values, ax=ax, cmap="RdYlBu_r")
fig.colorbar(p, ax=ax, label=f"{sss.attrs['long_name']} [{sss.attrs['units']}]")
<matplotlib.colorbar.Colorbar at 0x15451b6a2bd0>
u = ds["u-vel."].isel(time=0, k=0)
# U-point variable — use lon_u / lat_u
fig, ax = ArcticMap()
p = pcolormesh_curvilinear(u.lon_u.values, u.lat_u.values, u.values, ax=ax, cmap="RdBu_r")
fig.colorbar(p, ax=ax, label=f"{u.attrs['long_name']} [{u.attrs['units']}]")
<matplotlib.colorbar.Colorbar at 0x1546fceeb410>