A quick look at ECCO data
ClimaOcean can download and utilize data from the "ECCO" state estimate, which stands for "Estimating the Circulation and Climate of the Ocean" –- two!
This example shows how to download three-dimensional temperature and salinity fields from ECCO, and makes a short animation to showcase the fields' content.
For this example we need Oceananigans for Field utilities, CairoMakie for plotting, Printf for nice labeling, and of course ClimaOcean to actually download and construct the ECCO fields.
using Oceananigans
using CairoMakie
using Printf
using ClimaOcean.DataWrangling.ECCO: ECCO_field
The function ECCO_field
provided by ClimaOcean.DataWrangling.ECCO
automatically downloads ECCO data, if the data doesn't already exist at the default location.
T = ECCO_field(:temperature)
S = ECCO_field(:salinity)
720×360×50 Field{Oceananigans.Grids.Center, Oceananigans.Grids.Center, Oceananigans.Grids.Center} on Oceananigans.Grids.LatitudeLongitudeGrid on Oceananigans.Architectures.CPU
├── grid: 720×360×50 LatitudeLongitudeGrid{Float64, Oceananigans.Grids.Periodic, Oceananigans.Grids.Bounded, Oceananigans.Grids.Bounded} on Oceananigans.Architectures.CPU with 7×7×3 halo and with precomputed metrics
├── boundary conditions: FieldBoundaryConditions
│ └── west: Periodic, east: Periodic, south: ZeroFlux, north: ZeroFlux, bottom: ZeroFlux, top: ZeroFlux, immersed: ZeroFlux
└── data: 734×374×56 OffsetArray(::Array{Float64, 3}, -6:727, -6:367, -2:53) with eltype Float64 with indices -6:727×-6:367×-2:53
└── max=40.6433, min=0.0, mean=18.3173
Next, we massage the ECCO data by inserting NaNs in "land cells", which are diagnosed by having an unphysically low temperature.
Tp = parent(T)
Sp = parent(S)
Sp[Tp .< -10] .= NaN
Tp[Tp .< -10] .= NaN
0-element view(::Vector{Float64}, Int64[]) with eltype Float64
Plotting ECCO data
We're ready to plot. We'll make an animation that depicts how the ECCO data changes with depth.
fig = Figure(size=(900, 1050))
axT = Axis(fig[1, 1])
axS = Axis(fig[2, 1])
Axis with 0 plots:
To make an animation that scrolls through the 3D temperature and salinity fields, we make an Observable for the vertical index, and then construct slices of T, S using the Observable, k
.
grid = T.grid
Nz = size(grid, 3)
k = Observable(Nz)
Tk = @lift view(T, :, :, $k)
Sk = @lift view(S, :, :, $k)
Observable(720×360×1 Field{Oceananigans.Grids.Center, Oceananigans.Grids.Center, Oceananigans.Grids.Center} on Oceananigans.Grids.LatitudeLongitudeGrid on Oceananigans.Architectures.CPU
├── grid: 720×360×50 LatitudeLongitudeGrid{Float64, Oceananigans.Grids.Periodic, Oceananigans.Grids.Bounded, Oceananigans.Grids.Bounded} on Oceananigans.Architectures.CPU with 7×7×3 halo and with precomputed metrics
├── boundary conditions: FieldBoundaryConditions
│ └── west: Periodic, east: Periodic, south: ZeroFlux, north: ZeroFlux, bottom: Nothing, top: Nothing, immersed: ZeroFlux
├── indices: (:, :, 50:50)
└── data: 734×374×1 OffsetArray(view(::Array{Float64, 3}, :, :, 53:53), -6:727, -6:367, 50:50) with eltype Float64 with indices -6:727×-6:367×50:50
└── max=40.2086, min=0.0, mean=22.4172)
Finally, we make a nice plot with a label that displays depth, colorbars, and light gray within land cells.
hmT = heatmap!(axT, Tk, nan_color=:lightgray, colorrange=(-2, 30), colormap=:thermal)
hmS = heatmap!(axS, Sk, nan_color=:lightgray, colorrange=(31, 37), colormap=:haline)
Colorbar(fig[1, 2], hmT, label="Temperature (ᵒC)")
Colorbar(fig[2, 2], hmS, label="Salinity (psu)")
z = znodes(grid, Center())
depth_str = @lift @sprintf("%.1f meters depth", -z[$k])
text!(axT, 50, 50, text=depth_str, color=:lemonchiffon, justification=:center, fontsize=20)
text!(axS, 50, 50, text=depth_str, color=:lemonchiffon, justification=:center, fontsize=20)
MakieCore.Text{Tuple{Vector{GeometryBasics.Point{2, Float64}}}}
Making the animation
This animation is a little fancy. We start by displaying the surface field, then we scroll through depth to the bottom and pause there. Next, we scroll back to the surface and pause.
stillframes = 10
movingframes = Nz
record(fig, "ECCO_temperature_salinity.mp4", framerate=4) do io
[recordframe!(io) for _ = 1:stillframes]
for kk in Nz:-2:1
k[] = kk
recordframe!(io)
end
[recordframe!(io) for _ = 1:stillframes]
for kk in 1:2:Nz
k[] = kk
recordframe!(io)
end
[recordframe!(io) for _ = 1:stillframes]
end
This page was generated using Literate.jl.