Argo finescale estimates#

%load_ext watermark

import argopy
import cf_xarray as cfxr
import dask
import dcpy
import gsw
import matplotlib as mpl
import matplotlib.pyplot as plt
import mixsea
import numpy as np
import pandas as pd
import scipy
import scipy.integrate
import seawater as sw
from dcpy.finestructure import estimate_turb_segment, process_argo_profile
from scipy import signal
from scipy.io import loadmat

import xarray as xr

plt.style.use("bmh")
mpl.rcParams["figure.dpi"] = 140
mpl.rcParams["lines.linewidth"] = 1
dirname = "/home/deepak/datasets/finestructure/"

%watermark -iv
seawater  : 3.3.4
gsw       : 3.4.0
numpy     : 1.20.2
mixsea    : 0.1.0
scipy     : 1.5.3
xarray    : 0.17.1.dev3+g48378c4b1
argopy    : 0.1.7
eddydiff  : 0.1
dask      : 2021.6.2
pandas    : 1.2.3
dcpy      : 0.1
matplotlib: 3.4.1
cf_xarray : 0.4.1.dev21+gab9dc66
from distributed import Client

client = Client(threads_per_worker=7, memory_limit="24GB", processes=False)
client

Client

Client-fe7fad73-e442-11eb-b83d-0028f8270ea7

Connection method: Cluster object Cluster type: LocalCluster
Dashboard: http://192.168.0.10:8787/status

Cluster Info

NATRE region#

import glob

dsets = [xr.open_dataset(file) for file in glob.glob("./argo_natre_*.nc")]
argo = (
    xr.concat(dsets, dim="N_POINTS").load().argo.point2profile().set_coords("PRES")
)  # .isel(N_POINTS=slice(10000))
argo.PRES.attrs["standard_name"] = "sea_water_pressure"
argo.PRES.attrs["positive"] = "down"
argo.TIME.groupby(argo.TIME.dt.year).count().plot()
plt.gcf().set_size_inches((8, 2))
plt.gca().set_ylabel("N_OBS")
Text(0, 0.5, 'N_OBS')
_images/6706a2be2a47340a97139428eed8bf62fe634ff50f01f3802090f90af7039ca9.png
import dask

argo_good = argo.query({"N_PROF": "DIRECTION == 'A' & DATA_MODE == 'D'"})

# doesn't do anything
# too_coarse = (argo_good.PRES.diff("N_LEVELS") > 20).all("N_LEVELS")
# argo_good = argo_good.isel(N_PROF=~too_coarse)

tasks = [
    dask.delayed(argomix.process_profile)(argo_good.isel(N_PROF=idx))
    for idx in range(argo_good.sizes["N_PROF"])
]
len(tasks)
results = dask.compute(tasks, scheduler=client)
distributed.comm.inproc - WARNING - Closing dangling queue in <InProc  local=inproc://192.168.0.10/1554493/1 remote=inproc://192.168.0.10/1554493/8>
/home/deepak/work/python/dcpy/dcpy/finestructure.py:86: RuntimeWarning: invalid value encountered in sqrt
  N = np.sqrt(N2fit.mean()).item()
def set_index(ds, dim):
    ds = ds.assign_coords({dim: np.arange(ds.sizes[dim])})
    ds["pressure"] = ds.variables["pressure"].to_base_variable()
    return ds


renamed = [
    ds.rename_dims({"pressure": "pressure_"})
    .pipe(set_index, "pressure_")
    .expand_dims("profile")
    for ds in results[0]
    if isinstance(ds, xr.Dataset)
]
combined = xr.concat(renamed, dim="profile", join="outer")
combined.pressure.attrs["positive"] = "down"
combined
<xarray.Dataset>
Dimensions:                (pressure_: 20, profile: 3583, nbnds: 2)
Coordinates: (12/13)
  * pressure_              (pressure_) int64 0 1 2 3 4 5 6 ... 14 15 16 17 18 19
    flag                   (profile, pressure_) float64 -1.0 -1.0 ... -1.0 nan
    pressure               (profile, pressure_) float64 nan nan nan ... nan nan
    npts                   (profile, pressure_) float64 0.0 0.0 0.0 ... 0.0 nan
    γmean                  (profile, pressure_) float64 nan nan nan ... nan nan
    latitude               (profile) float64 23.08 23.79 23.11 ... 26.0 27.96
    ...                     ...
    γ_bounds               (profile, pressure_, nbnds) float64 nan nan ... nan
    p_bounds               (profile, pressure_, nbnds) float64 nan nan ... nan
    CONFIG_MISSION_NUMBER  (profile) int64 1 1 1 1 1 1 1 1 1 ... 5 4 2 5 2 2 5 2
    PLATFORM_NUMBER        (profile) int64 1900073 1900072 ... 4901585 6902572
    CYCLE_NUMBER           (profile) int64 103 104 104 105 ... 180 181 229 182
    DIRECTION              <U1 'A'
Dimensions without coordinates: profile, nbnds
Data variables: (12/14)
    ε                      (profile, pressure_) float64 nan nan nan ... nan nan
    Kρ                     (profile, pressure_) float64 nan nan nan ... nan nan
    N2mean                 (profile, pressure_) float64 nan nan nan ... nan nan
    ξvar                   (profile, pressure_) float64 nan nan nan ... nan nan
    ξvargm                 (profile, pressure_) float64 nan nan nan ... nan nan
    Tzlin                  (profile, pressure_) float64 nan nan nan ... nan nan
    ...                     ...
    Tmld                   (profile) float64 112.4 95.1 112.3 ... 77.88 89.6
    σmld                   (profile) float64 92.4 95.1 112.3 ... 80.2 77.88 89.6
    Tmode                  (profile) float64 132.5 135.3 132.2 ... 79.96 99.7
    σmode                  (profile) float64 132.5 115.1 132.2 ... 79.96 99.7
    χ                      (profile, pressure_) float64 nan nan nan ... nan nan
    KtTz                   (profile, pressure_) float64 nan nan nan ... nan nan
combined.to_zarr("./argomix_natre.zarr")
distributed.utils_perf - WARNING - full garbage collections took 29% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
<xarray.backends.zarr.ZarrStore at 0x7f91ccb2d6d0>
distributed.utils_perf - WARNING - full garbage collections took 30% CPU time recently (threshold: 10%)
combined.to_netcdf("argomix_natre_all_latest.nc")
# combined = xr.open_dataset("argomix_natre_all.nc")
combined = xr.open_zarr("./argomix_natre.zarr").load()
bins = [
    26.692,
    26.876,
    27.039,
    27.163,
    27.288,
    27.406,
    27.516,
    27.605,
    27.683,
    27.742,
    27.794,
    27.835,
    27.872,
    27.898,
    27.921,
    27.94,
    27.958,
    29,
]
combined.coords["γ_vertices"] = cfxr.bounds_to_vertices(
    combined.γ_bounds, bounds_dim="nbnds", core_dims=["pressure_"]
)
combined.coords["p_vertices"] = cfxr.bounds_to_vertices(
    combined.p_bounds, bounds_dim="nbnds", core_dims=["pressure_"]
)
good_data = combined.npts > 40
combined.ε.cf.plot(
    hue="profile",
    y="pressure",
    xscale="log",
    ls="none",
    marker="x",
    add_legend=False,
    yincrease=False,
);
_images/77ac780aac837a18d35254d0dfaff1d333daa7684d8eed3364bd52cc1c31c753.png
combined.reset_coords("pressure").groupby_bins("γmean", bins=bins).mean().set_coords(
    "pressure"
).χ.plot(y="pressure", marker="x", xscale="log", yincrease=False)
combined.where(combined.npts > 20).reset_coords("pressure").groupby_bins(
    "γmean",
    bins=bins,
).mean().set_coords("pressure").χ.plot(
    y="pressure", marker="x", xscale="log", yincrease=False
)
plt.legend(["onlyε", "npts > 30"])
plt.grid(True)
_images/c1f3318b1628aeab224e89f8033e5d78858e0d5d5bd7c602055405e0333a49bf.png

Experiment with conservative interpolation of ε#

profile = combined.isel(profile=1950)
profile.ε.plot(x="pressure")
[<matplotlib.lines.Line2D at 0x7f1f4b11ddf0>]
_images/2dc8158dbe8a17beea1d644747241047db5c8e88abb8b916506a0cb6e8f77315.png
mask = profile.ε.notnull().data
mask_outer = profile.γ_vertices.notnull().data
bins = np.array(bins)

eps_ext = transform.interp_1d_conservative(
    (profile.ε * profile.γmean * profile.pressure).data[mask][:-1],
    profile.γ_vertices.data[mask_outer],
    target_theta_bins=np.asarray(bins),
)
mass_ext = transform.interp_1d_conservative(
    (profile.γmean * profile.pressure).data[mask][:-1],
    profile.γ_vertices.data[mask_outer],
    target_theta_bins=bins,
)

plt.plot((bins[:-1] + bins[1:]) / 2, eps_ext / mass_ext)
plt.plot(profile.γmean, profile.ε)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-78-d6bce3b0d837> in <module>
      1 bins = np.array(bins)
      2 
----> 3 eps_ext = transform.interp_1d_conservative(
      4     (profile.ε * profile.γmean * profile.pressure).data[mask][:-1],
      5     profile.γ_vertices.data[mask_outer],

NameError: name 'transform' is not defined

Do variance budget terms#

This does not work so well or too well actually. It looks like χ/2 matches the local turbulent stirring production exactly!

I think the 200m averaging scale in the finestructure estimate is the problem. It matches the vertical scale for our ‘large-scale’ vertical bins (I think the spacing between γ surfaces, but should check).

Another option is to do the Ferrari & Polzin (2005) thing where they set microscale stirring production \(= Γ⟨ε⟩/N^2_m θ^m_z\); so I could bin-average fine structure ε to get \(⟨ε⟩\) and use the climatology to get the gradient terms.

Another option is to calculate the estimates in 200m bins and then average all estimates in those bins; this would avoid some extra averaging I think (!)

  • Why has no one done this before?

import cf_xarray
import dcpy

argoclim = dcpy.oceans.read_argo_clim().sel(
    lat=slice(24, 28), lon=slice(360 - 31, 360 - 26)
)
argoclim["γ"] = dcpy.oceans.neutral_density(argoclim[["Tmean", "Smean"]])
argoclim.load()
argoclim.cf
Coordinates:
- CF Axes: * X: ['lon']
           * Y: ['lat']
           * Z: ['pres']
           * T: ['time']

- CF Coordinates: * longitude: ['lon']
                  * latitude: ['lat']
                  * vertical: ['pres']
                  * time: ['time']

- Cell Measures:   area, volume: n/a

- Standard Names: * sea_water_pressure: ['pres']

- Bounds:   n/a

Data Variables:
- Cell Measures:   area, volume: n/a

- Standard Names:   neutral_density: ['γ']
                    sea_water_potential_temperature: ['theta_mean']
                    sea_water_salinity: ['S', 'Smean']
                    sea_water_temperature: ['T', 'Tmean']

- Bounds:   n/a

density bin averaged#

bins = np.array(
    [
        26.69,
        26.88,
        27.04,
        27.16,
        27.29,
        27.41,
        27.52,
        27.6,
        27.68,
        27.74,
        27.79,
        27.84,
        27.87,
        27.9,
        27.92,
        27.94,
        27.96,
        27.97,
    ]
)
# bins = np.arange(26.5, 28.1, 0.15)

combined["KtTz_seg"] = combined. * combined.mean_dTdz_seg
binned_argo_fs = (
    combined.reset_coords("pressure")  # .where(good_data & (combined.npts > 30))
    .groupby_bins(
        "γmean",
        bins=bins,
    )
    .mean()
    .set_coords("pressure")
)


# totally fine
Tz_m_argo = (
    argoclim.theta_mean.cf.differentiate("pres", positive_upward=True)
    .compute()
    .mean(["lat", "lon"])
    .interp(pres=binned_argo_fs.pressure)
)
N2_m_argo = (
    -9.81
    / 1025
    * (
        argoclim.γ.cf.differentiate("pres", positive_upward=True)
        .compute()
        .mean(["lat", "lon"])
        .interp(pres=binned_argo_fs.pressure)
    )
)


f, ax = plt.subplots(1, 2, sharey=True)

binned_argo_fs.ε.cf.plot(marker="x", y="pressure", ax=ax[0])

(binned_argo_fs.χ / 2).plot(
    ax=ax[1], y="pressure", marker="x", xscale="log", yincrease=False
)
(binned_argo_fs.KtTz * Tz_m_argo).plot(ax=ax[1], y="pressure", marker="x")
# (binned_argo_fs.KtTz_seg * Tz_m_argo).plot(ax=ax[1], y="pressure", marker="o")
(0.2 * binned_argo_fs.ε / N2_m_argo * Tz_m_argo**2).plot(
    ax=ax[1], y="pressure", marker="x"
)
plt.legend(["$⟨χ⟩$/2", "$⟨K_ρ θ_z⟩ θ_z^m$", "$Γ⟨ε⟩/N^2_m (θ^m_z)^2$"])
plt.gcf().set_size_inches((7, 6))
plt.grid(True)
_images/cca91815d217843c1f6598e7df2ed51c0aee59db9e71a606532439ca192a4844.png
(0.2 * binned_argo_fs.ε / N2_m_argo * Tz_m_argo**2).plot(y="pressure")
(binned_argo_fs. * Tz_m_argo**2).plot(y="pressure", xscale="log")
(binned_argo_fs.KtTz * Tz_m_argo).plot(y="pressure", xscale="log")
(binned_argo_fs. * binned_argo_fs.Tzmean * Tz_m_argo).plot(y="pressure", xscale="log")
[<matplotlib.lines.Line2D at 0x7f1f4a81b1c0>]
_images/674a96acbc28a448549ea7270390416095b88ffe4c8a04e8704821cd9549beac.png

pressure bin averaged#

binned = combined.groupby_bins("pressure", np.arange(250, 2050, 200)).mean()
centers = [p.data.item().mid for p in binned.pressure_bins]
Tz_m_argo = (
    argoclim.theta_mean.cf.differentiate("pres", positive_upward=True)
    .compute()
    .mean(["lat", "lon"])
    .interp(pres=centers)
    .rename(pres="pressure_bins")
)

(binned.χ / 2).plot.step(y="pressure_bins", xscale="log", yincrease=False)
(binned.KtTz_seg * Tz_m_argo.data).plot.step(
    y="pressure_bins", xscale="log", yincrease=False
)
[<matplotlib.lines.Line2D at 0x7f1f4821d370>]
_images/f41db655681df42a5501132f6e990e173a4d48bc9ee15bc7f940c4e232117215.png

Debugging profile estimates#

  • [x] check MLD for N_PROF=100

  • [ ] change axes tick colors for T,S,γ

  • [ ] Throw out estimates when number of points is small. This is causing the drop near 1000m; below this data spacing is usually coarse. I need to be more careful about bins near 1000m

profile = argo.isel(N_PROF=120)
result = process_argo_profile(profile, debug=True)
 104 —  294dbar: ξgmvar: 0.103, ξvar: 0.114, N2: 3.61e-05 K: 5.33e-06, ε: 9.45e-10
 204 —  385dbar: ξgmvar: 0.096, ξvar: 0.033, N2: 2.28e-05 K: 4.97e-07, ε: 5.56e-11
_images/b7e3b955a4a8c034db9a9c591b478c2cddcceab4c1595086dcba34fbc8866d3e.png
profile = argo.query(
    {"N_PROF": "PLATFORM_NUMBER == 6900695 & CYCLE_NUMBER == 160"}
).squeeze()
result = process_argo_profile(profile, debug=True)
 211 —  371dbar: ξgmvar: 0.095, ξvar: 0.032, N2: 2.25e-05 K: 4.48e-07, ε: 4.94e-11
 316 —  476dbar: ξgmvar: 0.039, ξvar: 0.025, N2: 1.88e-05 K: 1.52e-06, ε: 1.41e-10
 416 —  586dbar: ξgmvar: 0.104, ξvar: 0.003, N2: 1.59e-05 K: 3.60e-09, ε: 2.81e-13
 511 —  691dbar: ξgmvar: 0.104, ξvar: 0.178, N2: 1.42e-05 K: 1.12e-05, ε: 7.80e-10
 611 —  791dbar: ξgmvar: 0.105, ξvar: 0.058, N2: 1.29e-05 K: 1.16e-06, ε: 7.31e-11
 711 —  891dbar: ξgmvar: 0.105, ξvar: 0.083, N2: 1.06e-05 K: 2.32e-06, ε: 1.20e-10
 811 —  991dbar: ξgmvar: 0.101, ξvar: 0.140, N2: 7.99e-06 K: 6.95e-06, ε: 2.72e-10
 911 — 1091dbar: ξgmvar: 0.107, ξvar: 0.053, N2: 7.61e-06 K: 8.85e-07, ε: 3.30e-11
1012 — 1191dbar: ξgmvar: 0.107, ξvar: 0.099, N2: 6.11e-06 K: 2.96e-06, ε: 8.87e-11
1111 — 1291dbar: ξgmvar: 0.102, ξvar: 0.071, N2: 5.59e-06 K: 1.67e-06, ε: 4.56e-11
1211 — 1391dbar: ξgmvar: 0.102, ξvar: 0.095, N2: 5.20e-06 K: 2.94e-06, ε: 7.50e-11
1311 — 1492dbar: ξgmvar: 0.103, ξvar: 0.054, N2: 4.52e-06 K: 9.23e-07, ε: 2.04e-11
1411 — 1571dbar: ξgmvar: 0.102, ξvar: 0.080, N2: 3.55e-06 K: 2.02e-06, ε: 3.52e-11
_images/37339960073334fba7b666679fa88a70cfb2f8d25d56e4a1fb9f99d5d375eff9.png
profile = argo.isel(N_PROF=2100)
result = process_argo_profile(profile, debug=True)
 203 —  399dbar: ξgmvar: 0.315, ξvar: 0.216, N2: 2.23e-05 K: 1.97e-06, ε: 2.16e-10
 303 —  499dbar: ξgmvar: 0.231, ξvar: 0.200, N2: 1.71e-05 K: 3.08e-06, ε: 2.58e-10
 403 —  599dbar: ξgmvar: 0.189, ξvar: 0.207, N2: 1.60e-05 K: 4.87e-06, ε: 3.83e-10
 503 —  699dbar: ξgmvar: 0.250, ξvar: 0.217, N2: 1.47e-05 K: 3.04e-06, ε: 2.19e-10
 603 —  799dbar: ξgmvar: 0.286, ξvar: 0.219, N2: 1.37e-05 K: 2.35e-06, ε: 1.58e-10
 703 —  899dbar: ξgmvar: 0.146, ξvar: 0.191, N2: 1.29e-05 K: 6.82e-06, ε: 4.31e-10
 803 —  987dbar: ξgmvar: 0.256, ξvar: 0.200, N2: 9.84e-06 K: 2.36e-06, ε: 1.14e-10
 903 — 1073dbar: ξgmvar: 0.460, ξvar: 0.169, N2: 8.63e-06 K: 5.15e-07, ε: 2.18e-11
_images/a0e93b73bcfd26bce644e51250ba5c27999dec770d0748942a066e18c1aadf04.png
profile = argo.query(
    {"N_PROF": "PLATFORM_NUMBER == 4901588 & CYCLE_NUMBER == 23"}
).squeeze()
result = process_argo_profile(profile, debug=True)
 201 —  397dbar: ξgmvar: 0.269, ξvar: 0.217, N2: 1.73e-05 K: 2.92e-06, ε: 2.47e-10
 303 —  497dbar: ξgmvar: 0.137, ξvar: 0.219, N2: 1.57e-05 K: 1.14e-05, ε: 8.78e-10
 401 —  597dbar: ξgmvar: 0.136, ξvar: 0.215, N2: 1.43e-05 K: 1.11e-05, ε: 7.77e-10
 501 —  699dbar: ξgmvar: 0.131, ξvar: 0.208, N2: 1.42e-05 K: 1.11e-05, ε: 7.72e-10
 601 —  799dbar: ξgmvar: 0.216, ξvar: 0.219, N2: 1.46e-05 K: 4.58e-06, ε: 3.27e-10
 701 —  897dbar: ξgmvar: 0.145, ξvar: 0.207, N2: 1.44e-05 K: 9.05e-06, ε: 6.40e-10
 803 —  997dbar: ξgmvar: 0.236, ξvar: 0.209, N2: 1.23e-05 K: 3.38e-06, ε: 2.04e-10
 901 — 1099dbar: ξgmvar: 0.038, ξvar: 0.175, N2: 9.35e-06 K: 8.93e-05, ε: 4.09e-09
1001 — 1197dbar: ξgmvar: 0.087, ξvar: 0.201, N2: 8.07e-06 K: 2.19e-05, ε: 8.66e-10
1103 — 1299dbar: ξgmvar: 0.099, ξvar: 0.204, N2: 7.22e-06 K: 1.75e-05, ε: 6.19e-10
1201 — 1399dbar: ξgmvar: 0.051, ξvar: 0.200, N2: 5.85e-06 K: 6.25e-05, ε: 1.79e-09
1303 — 1499dbar: ξgmvar: 0.199, ξvar: 0.216, N2: 4.83e-06 K: 4.62e-06, ε: 1.09e-10
1403 — 1599dbar: ξgmvar: 0.113, ξvar: 0.213, N2: 3.57e-06 K: 1.33e-05, ε: 2.33e-10
1503 — 1699dbar: ξgmvar: 0.053, ξvar: 0.108, N2: 3.34e-06 K: 1.57e-05, ε: 2.57e-10
1601 — 1799dbar: ξgmvar: 0.040, ξvar: 0.137, N2: 3.21e-06 K: 4.29e-05, ε: 6.76e-10
1701 — 1899dbar: ξgmvar: 0.211, ξvar: 0.218, N2: 2.33e-06 K: 3.80e-06, ε: 4.35e-11
1803 — 1999dbar: ξgmvar: 0.078, ξvar: 0.209, N2: 1.81e-06 K: 2.49e-05, ε: 2.20e-10
1901 — 1999dbar: ξgmvar: 0.060, ξvar: 0.181, N2: 1.51e-06 K: 3.09e-05, ε: 2.28e-10
_images/ecb4607565803f8382abca066f8752097355186ce2f4bfcff3a6c91ff8695d23.png

Bad profiles#

I found some bad profiles; all for the same float 6900695; and cycle numbers 160, 170 ,171, 175.

Changing from the mixsea psd to my psd fixed it :/. The input data were fine; whatever funny interpolation is done with mixsea screws things

mask = (combined.ε > 1).any("pressure_")
combined.isel(profile=mask)
<xarray.Dataset>
Dimensions:                (pressure_: 19, profile: 4, nbnds: 2)
Coordinates: (12/13)
  * pressure_              (pressure_) int64 0 1 2 3 4 5 6 ... 13 14 15 16 17 18
    flag                   (profile, pressure_) float64 5.0 5.0 5.0 ... -2.0 nan
    pressure               (profile, pressure_) float64 282.7 414.5 ... nan nan
    npts                   (profile, pressure_) float64 15.0 13.0 ... 4.0 nan
    γmean                  (profile, pressure_) float64 26.71 26.92 ... nan nan
    latitude               (profile) float64 23.04 23.05 23.17 23.56
    ...                     ...
    γ_bounds               (profile, pressure_, nbnds) float64 26.5 ... nan
    p_bounds               (profile, pressure_, nbnds) float64 206.0 ... nan
    CONFIG_MISSION_NUMBER  (profile) int64 2 2 2 2
    PLATFORM_NUMBER        (profile) int64 6900695 6900695 6900695 6900695
    CYCLE_NUMBER           (profile) int64 160 170 171 175
    DIRECTION              (profile) <U1 'A' 'A' 'A' 'A'
Dimensions without coordinates: profile, nbnds
Data variables: (12/13)
    ε                      (profile, pressure_) float64 2.364e-11 ... nan
    Kρ                     (profile, pressure_) float64 2.215e-07 ... nan
    N2mean                 (profile, pressure_) float64 2.177e-05 ... nan
    ξvar                   (profile, pressure_) float64 0.03379 ... nan
    ξvargm                 (profile, pressure_) float64 0.1436 0.05839 ... nan
    Tzlin                  (profile, pressure_) float64 0.02425 0.01908 ... nan
    ...                     ...
    Tmld                   (profile) float64 96.0 56.0 46.0 45.0
    σmld                   (profile) float64 36.0 46.0 46.0 36.0
    Tmode                  (profile) float64 146.0 66.0 56.0 55.0
    σmode                  (profile) float64 106.0 66.0 56.0 55.0
    χ                      (profile, pressure_) float64 2.333e-10 ... nan
    KtTz                   (profile, pressure_) float64 5.082e-09 ... nan