API reference

Entry points

The two functions most users need. Everything else on this page is the toolbox they are built from.

glidertest.reports.report(ds: xr.Dataset, outdir: Path | str, *, navigator: bool = True, mission_id: str | None = None, layout: str = 'root', config: str | Path | Mapping | None = None) → Path[source]

Write a self-contained HTML report for ds under outdir and return the landing page path.

With layout "root" (the default) outdir is treated as a root: the report is written into <outdir>/<mission_id>/ (created if absent), so a root can hold many missions side by side. With layout "flat" the pages are written directly into outdir and no navigator is built (navigator is ignored) — one mission, one self-contained folder.

The mission_id subdirectory name is the OG1 id attribute when present, else the source file stem (see glidertest.reports._mission.mission_id()); pass mission_id to override it (run through the same directory-name sanitising). Each applicable page in glidertest.reports._mission.PAGES is written to <page>.html; the pages share one figures/ with page-prefixed slugs (<page>_<panel>.png) and a cross-page nav. A machine-readable report.json manifest is written beside the landing page.

With navigator True (the default, root layout only), <outdir>/index.html — a fleet navigator over every <outdir>/*/report.json — is rebuilt after the mission is written (see navigator()). The rebuild redraws the fleet track map, so for a batch pass navigator=False in the loop and call navigator() once at the end rather than rebuilding on every mission.

Figures are rendered under the non-interactive Agg backend for the duration of the build, then the caller’s backend is restored. glidertest’s plotters call plt.show() when they draw their own figure, which would pop a window per panel on an interactive backend (e.g. macosx); Agg makes that a no-op. Switching the backend closes any figures the caller had open.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset.

  • outdir (pathlib.Path or str) – The root directory (layout="root") or the mission’s own directory (layout="flat").

  • navigator (bool, default True) – Rebuild <outdir>/index.html (the fleet navigator) after writing the mission. Ignored when layout="flat".

  • mission_id (str, optional) – Subdirectory name for this mission, overriding the name derived from ds; run through the same sanitising as the derived name. Must not be combined with layout="flat" (there is no subdirectory to name) — doing so raises ValueError.

  • layout ({"root", "flat"}, default "root") – "root" writes the mission into <outdir>/<mission_id>/; "flat" writes the pages directly into outdir and builds no navigator.

  • config (str or pathlib.Path or Mapping, optional) – A report config (a YAML file path or an already-parsed mapping) whose qc: block overrides the built-in QC thresholds per variable and test; see glidertest.config.loader. It is validated before any figure is drawn, raising ConfigError on an error. None (the default) uses the built-in thresholds, so the output is unchanged. When given, the config is saved beside report.json as report-config.yaml so a re-run can consume it (config=<missiondir>/report-config.yaml): a file is copied verbatim, a dict is dumped (and so carries no comments).

Returns:

The path to the written landing page (<outdir>/<mission_id>/index.html for root layout, <outdir>/index.html for flat).

Return type:

pathlib.Path

glidertest.reports.navigator(root: Path | str, title: str | None = None) → Path[source]

Rebuild <root>/index.html — a fleet navigator over every <root>/*/report.json.

Reads only the per-mission manifests (never a NetCDF file, never a mission’s HTML), so it is a fast, idempotent re-index of whatever missions a root currently holds.

Parameters:
  • root (pathlib.Path or str) – A root directory holding <mission_id>/report.json subdirectories.

  • title (str, optional) – The navigator’s masthead title; defaults to the root directory name.

Returns:

The path to the written <root>/index.html.

Return type:

pathlib.Path

Raises:
  • FileNotFoundError – If root is not an existing directory.

  • ValueError – If root is itself a mission report directory (it holds a top-level report.json, as a layout="flat" report does); indexing it would find no missions and overwrite its landing page. Pass the parent directory instead.

Modules

glidertest.tools.add_sigma_1(ds: Dataset, var_sigma_1: str = 'SIGMA_1') → Dataset[source]

Computes the potential density anomaly (sigma_1) referenced to 1000 dbar and adds it to the dataset if not already present.

Parameters:
  • ds (xr.Dataset) – OG1-format dataset with required variables: DEPTH, TEMP, PSAL, LATITUDE, LONGITUDE.

  • var_sigma_1 (str, optional) – Name of the variable to be added to the dataset. Default is “SIGMA_1”.

Returns:

Dataset with the additional variable var_sigma_1.

Return type:

xr.Dataset

Notes

Original author: Till Moritz

glidertest.tools.calc_w_meas(ds)[source]

Calculates the vertical velocity of a glider using changes in pressure with time.

Parameters:

ds (xarray.Dataset) – Dataset containing DEPTH and TIME.

Returns:

ds – Containing the new variable GLIDER_VERT_VELO_DZDT (array-like), with vertical velocities calculated from dz/dt

Return type:

xarray.Dataset

Notes

Original Author: Eleanor Frajka-Williams

glidertest.tools.calc_w_sw(ds)[source]

Calculate the vertical seawater velocity and add it to the dataset.

Parameters:

ds (xarray.Dataset) – Dataset containing VERT_GLIDER_SPEED and VERT_SPEED_DZDT.

Returns:

ds – Dataset with the new variable VERT_SW_SPEED, which is the inferred vertical seawater velocity.

Return type:

xarray.Dataset

Notes

  • This could be bundled with calc_glider_w_from_depth, but keeping them separate allows for some extra testing/flexibility for the user.

Original Author: Eleanor Frajka-Williams

glidertest.tools.calculate_CR_for_all_depth(profile)[source]

Calculate CR for all depths in the profile.

Parameters:
  • profile (xarray.Dataset or pandas.DataFrame) – Profile data containing depth and SIGMA_1.

  • use_bins (bool, optional) – If True, bins the data before computation. Default is False.

  • binning (float, optional) – Bin size for binning. Default is 10.

Returns:

DataFrame with columns: DEPTH, CR.

Return type:

pd.DataFrame

Notes

Original Author: Till Moritz

glidertest.tools.check_monotony(da)[source]

Checks whether the selected variable is monotonically increasing throughout the mission. This function is particularly designed to check profile numbers to ensure they are assigned correctly. If the profile number is not monotonically increasing, it may indicate misassignment due to an error in data processing.

Parameters:

da (xarray.DataArray) – DataArray in OG1 format. Data should not be gridded.

Returns:

True if the variable is monotonically increasing, else False. Additionally, a message is _log.infoed indicating the result.

Return type:

bool

Notes

Original Author: Chiara Monforte

glidertest.tools.compute_CR(profile, h: float) → float[source]

Compute the CR (density anomaly integral) up to the reference depth h.

Parameters:
  • profile (xarray.Dataset or pandas.DataFrame) – Profile data containing ‘DEPTH’ and ‘SIGMA_1’.

  • h (float) – Reference depth up to which CR is computed.

Returns:

Computed CR up to the depth h, or NaN if insufficient data.

Return type:

float

Notes

Original Author: Till Moritz

glidertest.tools.compute_daynight_avg(ds, variable='CHLA', start_time=None, end_time=None, start_prof=None, end_prof=None)[source]

Computes day and night averages for a selected variable over a specified time period or range of dives. Day and night are determined based on sunrise and sunset times from the compute_sunset_sunrise function in GliderTools. A sufficient number of dives is required to ensure both day and night data are present; otherwise, the function will not run.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, DEPTH, LATITUDE, LONGITUDE, and the selected variable. Data should not be gridded.

  • variable (str, optional, default='CHLA') – The variable for which day and night averages will be computed.

  • start_time (str or datetime-like, optional) – The start date for data selection. - If not specified, defaults to the central week of the deployment. - Selecting a smaller section (a few days to weeks) is recommended for better visualization of NPQ effects.

  • end_time (str or datetime-like, optional) – The end date for data selection. - If not specified, defaults to the central week of the deployment.

  • start_prof (int, optional) – The starting profile number for data selection. - If not specified, the function uses start_time or defaults to the central week of deployment. - A sufficient number of dives is required for valid day and night separation.

  • end_prof (int, optional) – The ending profile number for data selection. - If not specified, the function uses end_time or defaults to the central week of deployment.

Returns:

  • day_av (pandas.DataFrame) – DataFrame containing daytime averages of the selected variable with the following columns: - batch : Integer representing the grouped day-night cycles (e.g., chronological day number). - depth : Depth values for the average calculation. - dat : Average value of the selected variable. - date : Actual date corresponding to the batch.

  • night_av (pandas.DataFrame) – DataFrame containing nighttime averages of the selected variable with the same columns as for day_av

Notes

Original Author: Chiara Monforte

glidertest.tools.compute_global_range(ds: Dataset, variable='DOXY', min_val=-5, max_val=600)[source]

Applies a gross filter to the dataset by removing observations outside the specified global range.

This function checks if any values of the specified variable (var) fall outside the provided range [min_val, max_val]. If a value is out of the specified range, it is excluded from the output. The function returns the filtered dataset with the out-of-range values removed.

Parameters:
  • ds (xarray.Dataset) – Dataset containing the variable to be filtered.

  • variable (str, optional, default='DOXY') – The name of the variable to apply the range filter on.

  • min_val (float, default = -5) – The minimum allowable value for the variable.

  • max_val (float, default = 600) – The maximum allowable value for the variable.

Returns:

A filtered DataArray containing only the values of the specified variable within the range [min_val, max_val]. Values outside this range are dropped.

Return type:

xarray.DataArray

Notes

Original Author: Chiara Monforte

glidertest.tools.compute_hyst_stat(ds: Dataset, variable='DOXY', v_res=1)[source]

This function computes some basic statistics for the differences between climb and dive data

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least DEPTH, PROFILE_NUMBER, and the selected variable. Data should not be gridded.

  • variable (str, optional, default='DOXY') – Selected variable

  • v_res (float) – Vertical resolution for the gridding

Returns:

  • diff (array-like) – Difference between upcast and downcast values.

  • err_range (array-like) – Percentage error of the dive-climb difference based on the range of values, computed for each depth step.

  • err_mean (array-like) – Percentage error of the dive-climb difference based on the mean values, computed for each depth step.

  • rms (float) – Root Mean Square (RMS) of the difference in values between dive and climb.

  • df (pandas.DataFrame) – DataFrame containing: - Dive and climb averages over depth for the selected variable. - Depth values in a separate column.

Notes

Original Author: Chiara Monforte

glidertest.tools.compute_mld(ds: Dataset, variable, method: str = 'threshold', threshold=0.03, ref_depth=10, use_bins: bool = True, binning: float = 10)[source]

Computes the mixed layer depth (MLD) for each profile in the dataset. Two methods are available: 1. Threshold Method: Computes MLD based on a density threshold (default is 0.03 kg/m³). 2. Convective Resistance (CR) Method: Computes MLD based on the CR method. Values close to 0 indicate a well-mixed layer, while values below 0 indicate a stratified layer. For the threshold, a value of -2 is recommended.

Parameters:
  • ds (xr.Dataset) – The dataset containing the profiles.

  • variable (str) – Variable used for the MLD calculation. For the CR method use density anomaly with reference to 1000 dbar (‘SIGMA_1’).

  • method (str, optional) – The method to use for MLD calculation. Options are ‘threshold’ or ‘CR’. Default is ‘threshold’.

  • threshold (float, optional) – If using ‘threshold’, this is the density threshold for MLD calculation. Default is 0.03 kg/m³. If using ‘CR’, this is the CR threshold for the convective resistance. A value of -2 is recommended.

  • use_bins (bool, optional) – Whether to use binned data for MLD calculation. Default is True.

  • binning (float, optional) – The binning resolution in meters. Default is 10m.

Returns:

mld_values – A DataFrame containing the MLD values for each profile, along with the mean time for each profile. The DataFrame has columns: ‘PROFILE_NUMBER’, ‘MLD’ and ‘TIME’.

Return type:

pd.DataFrame

Notes

Original Author: Till Moritz Based on the convective resistance caluclation, following the method described in FW2014 (https://doi.org/10.1175/JPO-D-13-069.1))

glidertest.tools.compute_prof_duration(ds: Dataset)[source]

This function computes some basic statistics for the differences between climb and dive data.

Parameters:

ds (xarray.Dataset) – Dataset in OG1 format, containing at least DEPTH, PROFILE_NUMBER, and the selected variable. Data should not be gridded.

Returns:

df – Dataframe containing the profile number and the duration of that profile in minutes

Return type:

pandas.DataFrame

Notes

Original Author: Chiara Monforte

glidertest.tools.find_outlier_duration(df: DataFrame, rolling=20, std=2)[source]

Identifies outlier profile durations based on a rolling mean and standard deviation threshold. This helps detect profiles with significantly longer or shorter durations compared to surrounding profiles.

Parameters:
  • df (pandas.DataFrame) – Dataframr containing the profile number and the duration of that profile in minutes

  • rolling (int, default = 20) – Window size for the rolling mean

  • std (int, default = 2) – Number of standard deviations to use for ‘odd’ profile duration

Returns:

  • rolling_mean (pandas.Series) – Rolling mean of profile duration computed using the specified window size.

  • overt_prof (numpy.ndarray) – Array of profile numbers where the duration exceeds the rolling mean by more than the set standard deviation threshold. - If outliers are found, a message is _log.infoed recommending further investigation.

Notes

Original Author: Chiara Monforte

glidertest.tools.linear_interpolation(x, y, x_new)[source]

Linearly interpolates y over x to estimate y at x_new.

glidertest.tools.max_depth_per_profile(ds: Dataset)[source]

This function computes the maximum depth for each profile in the dataset

Parameters:

ds (xarray.Dataset) – Dataset in OG1 format, containing at least DEPTH, PROFILE_NUMBER, and the selected variable. Data should not be gridded.

Returns:

max_depths

Return type:

pandas dataframe containing the profile number and the maximum depth of that profile

Notes

Original Author: Till Moritz

glidertest.tools.mean_profile(ds, variable='TEMP', v_res=1)[source]

This function computes the mean vertical profile for a specific variable.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least PROFILE_NUMBER, DEPTH, and the selected variable. Data should not be gridded.

  • variable (str, optional, default='PSAL') – Selected variable to average.

  • v_res (float) – Vertical resolution in meters for binning the profile.

Returns:

df – DataFrame containing the mean profile and corresponding depth bins.

Return type:

pandas.DataFrame

Notes

Original Author: Till Moritz

glidertest.tools.mld_profile_CR(profile, threshold: float = -2, use_bins: bool = True, binning: float = 10) → float[source]

Calculate the mixed layer depth (MLD) using the Convective Resistance (CR) method. Returns NaN if no valid depth data below 10m is available or no CR values meet the threshold.

Parameters:
  • profile (xarray.Dataset or pandas.DataFrame) – Profile data containing ‘DEPTH’ and ‘SIGMA_1’.

  • threshold (float, optional) – CR threshold for determining MLD. Default is -2.

  • use_bins (bool, optional) – Whether to apply depth binning. Default is False.

  • binning (float, optional) – Bin size for depth binning, in meters. Default is 10.

Returns:

Computed MLD in meters, or NaN if criteria are not met.

Return type:

float

Notes

Original author: Till Moritz

glidertest.tools.mld_profile_treshhold(profile, variable: str = 'SIGMA_T', threshold: float = 0.03, ref_depth: float = 10, use_bins: bool = False, binning: float = 10) → float[source]

Computes the mixed layer depth (MLD) from a profile dataset based on the density profile, using a threshold of 0.03 kg/m³

Parameters:
  • profile (pd.DataFrame or xr.Dataset) – Dataset or DataFrame containing depth and density columns.

  • variable (str) – The name of the variable to use for the threshold calculation (default is ‘SIGMA_T’).

  • threshold (float) – Density threshold for MLD estimation (default is 0.03 kg/m³).

  • ref_depth (float) – Reference depth for MLD estimation (default is 10m).

  • use_bins (bool) – Whether to bin the profile data before computing MLD.

  • binning (float) – Bin resolution in meters if use_bins is True.

Returns:

Estimated mixed layer depth, or NaN if it cannot be determined.

Return type:

float

Notes

Original Author: Till Moritz

glidertest.tools.quant_binavg(ds, variable='VERT_CURR', zgrid=None, dz=None)[source]

Calculate the bin average of vertical velocities within specified depth ranges. This function computes the bin average of all vertical velocities within depth ranges, accounting for the uneven vertical spacing of seaglider data in depth (but regular in time). It uses the pressure data to calculate depth and then averages the vertical velocities within each depth bin.

Parameters:
  • ds (xarray.Dataset) – Dataset containing the variables PRES and VERT_SW_SPEED

  • zgrid (array-like, optional) – Depth grid for binning. If None, a default grid is created.

  • dz (float, optional) – Interval for creating depth grid if zgrid is not provided.

Returns:

meanw – Bin-averaged vertical velocities for each depth bin.

Return type:

array-like

Notes

Original Author: Eleanor Frajka-Williams

glidertest.tools.quant_hysteresis(ds: Dataset, variable='DOXY', v_res=1)[source]

This function computes up and downcast averages for a specific variable

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least DEPTH, PROFILE_NUMBER, and the selected variable. Data should not be gridded.

  • variable (str, optional, default='DOXY') – Selected variable

  • v_res (float) – Vertical resolution for the gridding in meters.

Returns:

df – Dataframe containing dive and climb average over depth for the selected variable. A third column contains the depth values

Return type:

pandas.DataFrame

Notes

Original Author: Chiara Monforte

glidertest.tools.quant_updown_bias(ds, variable='PSAL', v_res=1)[source]

This function computes up and downcast averages for a specific variable and their standard errors for each depth bin

Parameters:
  • ds (Dataset.xarray) – Dataset in OG1 format, containing at least TIME, DEPTH, LATITUDE, LONGITUDE, and the selected variable. Data should not be gridded.

  • variable (str, optional, default='PSAL') – Selected variable.

  • v_res (float) – Vertical resolution for the gridding in meters.

Returns:

df – Dataframe containing: dc, cd : Mean Dive-Climb and Climb-Dive differences dc_se, cd_se : Standard errors of the mean differences dc_n, cd_n : Number of valid differences per depth bin depth : Depth-bin centers/coordinates

Return type:

pandas.DataFrame

Notes

Original Author: Chiara Monforte

glidertest.plots.check_temporal_drift(ds: ~xarray.core.dataset.Dataset, variable: str, ax: ~matplotlib.axes._axes.Axes = None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Assesses potential temporal drift in a selected variable by generating a figure with two subplots: 1. Time series scatter plot of the variable. 2. Depth profile scatter plot, colored by date.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, DEPTH, and the selected variable. Data should not be gridded.

  • variable (str, optional) – Selected variable to analyze.

  • ax (matplotlib.axes.Axes, optional) – Axis to plot the data. If None, a new figure and axis will be created.

  • **kw (dict) – Additional keyword arguments for customization.

Returns:

  • fig (matplotlib.figure.Figure) – The generated figure.

  • ax (matplotlib.axes.Axes) – Axes containing the plots.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_CR(ds: Dataset, profile_num: int, use_bins: bool = False, binning: float = 2, ax=None)[source]

Plots the convective resistance (CR) of a profile against depth based on calculate_CR_for_all_depth function. For the calculation, the density anomaly with reference to 1000 kg/m3 is used (‘SIGMA_1’)

Parameters:
  • ds (xarray.Dataset) – Xarray dataset in OG1 format with at least PROFILE_NUMBER, DEPTH, SIGMA_1.

  • profile_num (int) – The profile number to plot.

  • use_bins (bool) – If True, use binned data instead of raw data.

  • binning (int) – The depth resolution for binning.

Returns:

  • fig (matplotlib.figure.Figure) – The figure object containing the plot.

  • ax (matplotlib.axes.Axes) – The axis object containing the primary plot.

Notes

Original Author: Till Moritz

glidertest.plots.plot_basic_vars(ds: Dataset, v_res=1, start_prof=0, end_prof=-1, ax=None)[source]

This function plots the basic oceanographic variables temperature, salinity and density. A second plot is created and filled with oxygen and chlorophyll data if available.

Parameters:
  • ds (xarray) – Dataset in OG1 format, containing at least PROFILE_NUMBER, DEPTH, TEMP, PSAL, LATITUDE, LONGITUDE, and the selected variable.

  • v_res (float, default = 1) – Vertical resolution for the gridding. Horizontal resolution (by profile) is assumed to be 1

  • start_prof (int) – Start profile used to compute the means that will be plotted. This can vary in case the dataset spread over a large timescale or region and subsections want to be plotted-1

  • end_prof (int) – End profile used to compute the means that will be plotted. This can vary in case the dataset spread over a large timescale or region and subsections want to be plotted-1

  • **kw (dict, optional) – Additional keyword arguments passed to matplotlib.pyplot.plot().

Returns:

  • fig (matplotlib.figure.Figure) – Figure object containing the generated plot.

  • ax (matplotlib.axes.Axes) – Axes object with the plotted variables temperature, salinity and density over depth.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_combined_velocity_profiles(ds_out_dives: Dataset, ds_out_climbs: Dataset, ax: Axes = None)[source]

Plots combined vertical velocity profiles for dives and climbs.

Replicates Fig 3 in Frajka-Williams et al. 2011, but using an updated dataset from Jim Bennett (2013), now in OG1 format as sg014_20040924T182454_delayed.nc. Note that flight model parameters may differ from those in the paper.

The function converts vertical velocities from m/s to cm/s, plots the mean vertical velocities and their ranges for both dives and climbs, and customizes the plot with labels, legends, and axis settings.

Parameters:
  • ds_out_dives (xarray.Dataset) – Dataset containing dive profiles with variables: - ‘zgrid’: Depth grid (meters) - ‘meanw’: Mean vertical velocity (m/s) - ‘w_lower’: Lower bound of velocity range (m/s) - ‘w_upper’: Upper bound of velocity range (m/s)

  • ds_out_climbs (xarray.Dataset) – Dataset containing climb profiles with the same variables as ds_out_dives.

  • ax (matplotlib.axes.Axes, optional) – Axes to plot the data. If not provided, a new figure and axes are created.

Returns:

  • fig (matplotlib.figure.Figure) – The figure object for the plot.

  • ax (matplotlib.axes._subplots.AxesSubplot) – The axes object for the plot.

Notes

  • Assumes that the vertical velocities are in m/s and the depth grid is in meters.

Original Author: Eleanor Frajka-Williams

glidertest.plots.plot_daynight_avg(ds, variable='PSAL', ax: ~matplotlib.axes._axes.Axes = None, sel_day=None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

This function can be used to plot the day and night averages computed with the day_night_avg function

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, DEPTH, and the selected variable.

  • variable (str, optional, default='PSAL') – Selected variable

  • ax (matplotlib.axes.Axes, default = None) – Axis to plot the data

  • sel_day (str or None, optional, default = None) – The specific day to plot. If None, the function selects the median day in the dataset.

Returns:

  • fig (matplotlib.figure.Figure) – The generated figure containing the plot.

  • ax (matplotlib.axes.Axes) – The axes object with the plotted data.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_glider_track(ds: ~xarray.core.dataset.Dataset, ax: ~matplotlib.axes._axes.Axes = None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Plots the glider track on a map, with latitude and longitude colored by time.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, LATITUDE, and LONGITUDE.

  • ax (matplotlib.axes.Axes, optional) – Axis to plot the data. If None, a new figure and axis will be created.

  • **kw (dict) – Additional keyword arguments for the scatter plot.

Returns:

  • fig (matplotlib.figure.Figure) – The generated figure.

  • ax (matplotlib.axes.Axes) – Axes containing the plot.

Notes

Original Author: Eleanor Frajka-Williams

glidertest.plots.plot_global_range(ds, variable='DOXY', min_val=-5, max_val=600, ax=None)[source]

This function creates a histogram of the selected variable (var) from the dataset (ds), allowing for visual inspection of its distribution. It overlays vertical lines at the specified minimum (min_val) and maximum (max_val) values to indicate the global range, helping identify whether values fall within expected limits.

Parameters:
  • ds (xarray.Dataset) – The dataset containing the variable to be plotted.

  • variable (str, default = 'DOXY') – The name of the variable to be plotted in the histogram.

  • min_val (float, default = -5) – The minimum value of the global range to highlight on the plot.

  • max_val (float, default = 600) – The maximum value of the global range to highlight on the plot.

  • ax (matplotlib.axes.Axes, optional) – The axes on which to plot the histogram. If None, a new figure and axes are created.

Returns:

  • fig (matplotlib.figure.Figure) – The figure object containing the histogram plot.

  • ax (matplotlib.axes.Axes) – The axes object containing the histogram plot.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_grid_spacing(ds: ~xarray.core.dataset.Dataset, ax: ~matplotlib.axes._axes.Axes = None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Plots histograms of the grid spacing, showing depth and time differences while excluding the outer 1% of values.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME and DEPTH.

  • ax (matplotlib.axes.Axes, optional) – Axis to plot the data. If None, a new figure and axis will be created.

  • **kw (dict) – Additional keyword arguments for the histograms.

Returns:

  • fig (matplotlib.figure.Figure) – The generated figure.

  • ax (matplotlib.axes.Axes) – Axes containing the histograms.

Notes

Original Author: Eleanor Frajka-Williams

glidertest.plots.plot_hysteresis(ds, variable='DOXY', v_res=1, threshold=2, ax=None)[source]

This function creates 4 plots which can help the user visualize any possible hysteresis present in their dataset for a specific variable

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format containing at least DEPTH, PROFILE_NUMBER and the selected variable. Data should not be gridded.

  • variable (str, optional, default = 'DOXY') – The variable to analyze for hysteresis effects

  • v_res (int, default = 1) – Vertical resolution for gridding the data

  • threshold (float, default = 2) – Percentage error threshold for plotting a reference vertical line

  • ax (matplotlib.axes.Axes, default = None) – Specific axes for plotting if adding to an existing figure

Returns:

  • fig (matplotlib.figure.Figure) – The figure object containing the plots.

  • ax (list of matplotlib.axes.Axes) – The list of axes corresponding to the four generated subplots.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_ioosqc(data, suspect_threshold=[25], fail_threshold=[50], title='', ax=None)[source]

This function generates a scatter plot of the results from an IOOS QC test, labeling data points with quality control categories (‘GOOD’, ‘UNKNOWN’, ‘SUSPECT’, ‘FAIL’, ‘MISSING’). It also overlays threshold-based markers to visualize suspect and fail ranges, aiding in the interpretation of data quality.

Parameters:
  • data (array-like) – The results from the IOOS QC test, representing numerical data points to be plotted.

  • suspect_threshold (list, optional, default = [25]) – A list containing one or two numerical values defining the thresholds for suspect values. If one value is provided, it applies to both lower and upper bounds. If two values are given, they define distinct lower and upper suspect limits.

  • fail_threshold (list, optional, default = [50]) – A list containing one or two numerical values defining the thresholds for fail values. The structure follows the same logic as suspect_threshold.

  • title (str, optional, default = '') – The title to display at the top of the plot.

  • ax (matplotlib.axes.Axes, optional) – The axes object on which to plot the results. If None, a new figure and axis are created.

Returns:

  • fig (matplotlib.figure.Figure) – The figure object containing the QC results plot.

  • ax (matplotlib.axes.Axes) – The axes object used for plotting.

Notes

  • The plot uses two y-axes: one for labeling data points as ‘GOOD’, ‘UNKNOWN’, ‘SUSPECT’, ‘FAIL’, or ‘MISSING’ based on thresholds, and another for marking specific suspect and fail ranges.

Original Author: Chiara Monforte

glidertest.plots.plot_max_depth_per_profile(ds: ~xarray.core.dataset.Dataset, bins=20, ax=None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Plots the maximum depth of each profile in a dataset.

This function generates two plots: one showing the maximum depth of each profile and another histogram illustrating the distribution of maximum depths. It provides a visual representation of profile depth variations.

Parameters:
  • ds (xarray.Dataset) – An xarray dataset in OG1 format containing profile numbers and corresponding maximum depths.

  • bins (int, optional, default = 20) – The number of bins to use for the histogram of maximum depths.

  • ax (matplotlib.axes.Axes, optional) – The axes object on which to plot the results. If None, a new figure with two subplots is created.

  • **kw (dict, optional) – Additional keyword arguments passed to the plotting function for customization.

Returns:

  • fig (matplotlib.figure.Figure) – The figure object containing the plots.

  • ax (matplotlib.axes.Axes) – A 1x2 array of axes used for the two subplots.

Notes

Original Author: Till Moritz

glidertest.plots.plot_outlier_duration(ds: Dataset, rolling_mean: Series, overtime, std=2, ax=None)[source]

Generates two plots to visualize profile durations and highlight outliers. This helps identify profiles with abnormal durations by comparing the actual profile durations to a rolling mean, and by visualizing the shape and depth of the selected outlier profiles.

Parameters:
  • ds (xarray.Dataset) – Dataset containing at least TIME, DEPTH, and PROFILE_NUMBER

  • rolling_mean (pandas.Series) – A series representing the rolling mean of profile durations, used to define the range of normal durations.

  • overtime (list) – A list of profile numbers identified as outliers based on abnormal durations.

  • std (float, default = 2) – The number of standard deviations around the rolling mean used to classify outliers.

  • ax (matplotlib.axes.Axes, default = None) – Axes object for plotting. If None, a new figure with two subplots is created.

Returns:

  • fig (matplotlib.figure.Figure) – The figure containing the generated plots

  • ax (list of matplotlib.axes.Axes) – A list of axes corresponding to the two generated subplots.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_prof_monotony(ds: ~xarray.core.dataset.Dataset, ax: ~matplotlib.axes._axes.Axes = None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Checks for potential issues with the assigned profile index by plotting its progression over time. If no issues are detected, only the profile-number plot is shown. Otherwise, a second plot highlights the depths where issues occur.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, DEPTH, and PROFILE_NUMBER. Data should not be gridded.

  • ax (matplotlib.axes.Axes, optional) – Axis to plot the data. If None, a new figure and axis will be created.

  • **kw (dict) – Additional keyword arguments for customization.

Returns:

  • fig (matplotlib.figure.Figure) – The generated figure.

  • ax (matplotlib.axes.Axes) – Axes containing the one or two plots. - 1. One line plot with the profile number over time (expected to be always increasing). - 2. If there are issues, a scatter plot is created showing at which depth over time there was a profile index where the difference was neither 0 nor 1 (meaning there are possibly issues with how the profile index was assigned).

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_profile(ds: Dataset, profile_num: int = None, variables: list = ['TEMP', 'PSAL', 'DENSITY'], use_bins: bool = False, binning: float = 2, ax=None)[source]

Plots the specified variables against depth for a given profile number from an OG1-format dataset. If no profile number is provided, it plots the mean profile for the specified variables.

Parameters:
  • ds (xarray.Dataset) – Xarray dataset in OG1 format with at least PROFILE_NUMBER, DEPTH and the specified variables.

  • profile_num (int or None) – Profile number to plot. If None, plots mean profile.

  • variables (list) – Variables to plot. Default is [‘TEMP’,’PSAL’,’DENSITY’].

  • use_bins (bool) – Whether to bin the data vertically.

  • binning (float) – Bin size in meters if use_bins is True.

Returns:

  • fig (matplotlib.figure.Figure) – The figure object containing the plot.

  • ax1 (list of matplotlib.axes.Axes) – The axis objects containing the subplots.

Notes

Original Author: Till Moritz

glidertest.plots.plot_quench_assess(ds: ~xarray.core.dataset.Dataset, variable: str, ax: ~matplotlib.axes._axes.Axes = None, start_time=None, end_time=None, start_prof=None, end_prof=None, ylim=35, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Generates a section plot of the selected variable over time and depth, with sunrise and sunset times marked to assess potential Non-Photochemical Quenching (NPQ) effects.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, DEPTH, LATITUDE, LONGITUDE, and the selected variable. Data should not be gridded.

  • variable (str) – The selected variable to plot.

  • ax (matplotlib.axes.Axes, optional, default = None) – Axis on which to plot the data. If None, a new figure and axis will be created.

  • start_time (str or None, optional, default = None) – Start date for the data selection (‘YYYY-MM-DD’). - If None, defaults to 2 days before the dataset’s median date.

  • end_time (str or None, optional, default = None) – End date** for the data selection (‘YYYY-MM-DD’). - If None, defaults to 2 days after the dataset’s median date.

  • start_prof (int or None, optional, default = None) – Start profile number for data selection

  • end_prof (int or None, optional, default = None) – End profile number for data selection

  • ylim (float, optional, default = 35) – Maximum depth limit for the y-axis. The minimum limit is automatically set as ylim / 30.

Returns:

  • fig (matplotlib.figure.Figure) – The generated figure containing the plot.

  • ax (matplotlib.axes.Axes) – The axes object with the plotted data.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_sampling_period(ds: Dataset, ax: Axes = None, variable='TEMP', annotation_fontsize=20)[source]

Plots a histogram of the sampling period for a selected variable after removing NaN values.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format.

  • ax (matplotlib.axes.Axes, optional) – Axis to plot the data. If not provided, a new figure and axis are created.

  • variable (str, default='TEMP') – Variable for which the sampling period is displayed.

Returns:

ax – Axis containing the histogram.

Return type:

matplotlib.axes.Axes

Notes

Original Author: Louis Clement

glidertest.plots.plot_sampling_period_all(ds: ~xarray.core.dataset.Dataset, ax: ~matplotlib.axes._axes.Axes = None) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Plots histograms of the sampling period for multiple variables. By default, it includes TEMP and PSAL, with DOXY and CHLA added if present in the dataset.

Parameters:

ds (xarray.Dataset) – Dataset in OG1 format.

Returns:

  • fig (matplotlib.figure.Figure) – The generated figure.

  • ax (matplotlib.axes.Axes) – Axes containing the histograms.

Notes

Original Author: Louis Clement

glidertest.plots.plot_section(ds: Dataset, variables: list = ['TEMP', 'PSAL', 'DENSITY'], v_res=2, start=None, end=None, show_time_axis=True, method='pcolormesh', log_scale=False, ax=None, **kw)[source]

Plots a section of the specified variable from the dataset ds against depth and profile number.

Parameters:
  • ds (xarray.Dataset) – The dataset containing the variable to be plotted.

  • variables (str or list of str) – Variable(s) to plot

  • ax (matplotlib.axes.Axes, optional) – The axes on which to plot. If None, a new figure and axes will be created.

  • v_res (float, optional) – The vertical resolution for the grid. Default is 2.

  • start (int, optional) – The starting profile number for the section. If None, it defaults to the minimum profile number in the dataset.

  • end (int, optional) – The ending profile number for the section. If None, it defaults to the maximum profile number in the dataset.

  • show_time_axis (bool, optional) – Whether to show a secondary x-axis with time corresponding to the profile numbers. Default is True.

  • method (str, optional) – The method to use for plotting. Options are “contourf” for filled contour plot and “pcolormesh” for a pseudocolor plot. Default is “pcolormesh”.

  • log_scale (bool, optional) – Whether to use a logarithmic scale for the color mapping. Default is False.

  • **kw – Additional keyword arguments to pass to the plotting function (e.g., cmap, vmin, vmax, levels).

Returns:

  • ax (matplotlib.axes.Axes) – The axes on which the section plot was created.

  • cbar (matplotlib.colorbar.Colorbar) – The colorbar associated with the plot.

  • time_ax (matplotlib.axes.Axes or None) – The secondary x-axis for time, if show_time_axis is True; otherwise, None.

Notes

Original Author: Till Moritz

glidertest.plots.plot_ts(ds: ~xarray.core.dataset.Dataset, percentile: list = [0.5, 99.5], ax: ~matplotlib.axes._axes.Axes = None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

Plots temperature and salinity distributions using histograms and a 2D density plot.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least DEPTH, LONGITUDE, LATITUDE, TEMP and PSAL.

  • percentile (list, optional) – The percentiles to use for filtering the data. Default is [0.5, 99.5].

  • ax (matplotlib.axes.Axes, optional) – Axes to plot the data. If not provided, a new figure and axes are created.

  • kw (dict, optional) – Additional keyword arguments for the histograms.

Returns:

  • fig (matplotlib.figure.Figure) – Figure containing the plots.

  • ax (matplotlib.axes.Axes) – Axes containing the histograms. - Three plots are created:

    1. Histogram of Conservative Temperature (middle 99%)

    2. Histogram of Absolute Salinity (middle 99%)

    3. 2D Histogram of Salinity vs. Temperature with density contours

Notes

Original Author: Eleanor Frajka-Williams

glidertest.plots.plot_updown_bias(ds: ~xarray.core.dataset.Dataset, variable='TEMP', v_res=1, ax: ~matplotlib.axes._axes.Axes = None, **kw: dict) -> (<class 'matplotlib.figure.Figure'>, <class 'matplotlib.axes._axes.Axes'>)[source]

This function can be used to plot the up and downcast differences computed with the updown_bias function

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, DEPTH, LATITUDE, LONGITUDE, and the selected variable. Data should not be gridded.

  • variable (str, optional, default='TEMP') – Selected variable

  • v_res (float, default = 1) – Vertical resolution for the gridding

  • ax (matplotlib.axes.Axes, default = None) – Axis to plot the data

  • **kw (dict, optional)

  • matplotlib.pyplot.plot(). (Additional keyword arguments passed to)

Returns:

  • fig (matplotlib.figure.Figure) – Figure object containing the generated plot.

  • ax (matplotlib.axes.Axes) – Axes object with the plotted climb vs. dive differences over depth.

Notes

Original Author: Chiara Monforte

glidertest.plots.plot_vertical_speeds_with_histograms(ds, start_prof=None, end_prof=None, ax: Axes = None)[source]

Plots vertical glider speeds with histograms for diagnostic purposes.

This function generates a diagnostic plot for vertical velocity calculations, comparing: 1. Modeled glider vertical speed (flight model) 2. Computed glider speed (from dz/dt, pressure sensor) 3. Implied seawater velocity (difference between the two)

The histograms allow for identifying biases, and the median of the seawater velocity should be close to zero if: - A large enough sample of dives is used. - The glider flight model is well-tuned.

Parameters:
  • ds (xarray.Dataset) – Dataset containing vertical speed data with required variables: - VERT_GLIDER_SPEED: Modeled glider speed - VERT_SPEED_DZDT: Computed glider speed from pressure sensor - VERT_SW_SPEED: Implied seawater velocity

  • start_prof (int, optional) – Starting profile number for subsetting. Defaults to the first profile number.

  • end_prof (int, optional) – Ending profile number for subsetting. Defaults to the last profile number.

  • ax (matplotlib.axes.Axes, optional) – Axes to plot the data. If not provided, a new figure and axes are created.

Returns:

  • fig (matplotlib.figure.Figure) – The figure containing the plots.

  • ax (tuple(matplotlib.axes.Axes)) – The axes objects for the plots.

Notes

Original Author: Eleanor Frajka-Williams

glidertest.plots.process_optics_assess(ds, variable='CHLA')[source]

Function to assess visually any drift in deep optics data and the presence of any possible negative data. This function returns both plots and text

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing at least TIME, DEPTH, and the selected variable.

  • variable (str, optional, default='CHLA') – Selected variable

Returns:

  • fig (matplotlib.figure.Figure) – Figure object containing the generated plot.

  • ax (matplotlib.axes.Axes) – Axes object with the plotted data.

  • text_output (str) – Text displaying where and when negative values are present in the dataset.

Returns:

  • fig, ax (matplotlib.axes.Axes) – Axes object with

  • text_output (str) – Text giving info on where and when negative data was observed

Notes

Original Author: Chiara Monforte

QC diagnostic plots: where glidertest’s QC tests fire, and whether a test fits the sampling.

These answer the two questions a flag count cannot: where the flagged samples fall (on the data, so a reader can tell outliers from a water mass or a dark count) and why a test fired — whether its thresholds suit the platform’s sampling or the data are genuinely bad. They back the per-test sections of the qc.html report page; each is also callable in a notebook.

Figures are born at the report slot width (width_in) under the active style, via glidertest.plots._ax(), so the report shows them at the width they were drawn at with no rescaling — see feat-qc-page-plan.md “Sizing”. The flag arrays come from glidertest.qc.sample_tests() (one computation, the same the delivered-vs-glidertest matrix uses); pass them in via flags to avoid recomputing across the panels of one page.

Original Author: Eleanor Frajka-Williams (glidertest).

glidertest.plots_qc.QC_MARKER: dict[int, dict] = {3: {'color': '#E69F00', 'linewidths': 0.8, 'marker': '+', 'rasterized': True, 's': 15, 'zorder': 3}, 4: {'color': '#D55E00', 'linewidths': 0.8, 'marker': '+', 'rasterized': True, 's': 15, 'zorder': 4}}

Delivered-flag overlay markers (suspect/fail only), keyed by flag value — small “+” in the flag colour, rasterized so the overlay is cheap even at 10^6 samples.

glidertest.plots_qc.TEST_MARKER: dict[str, dict] = {'flat_line': {'linewidths': 0.0, 'marker': 's', 'rasterized': True, 's': 10, 'zorder': 5}, 'gross_range': {'linewidths': 1.0, 'marker': 'x', 'rasterized': True, 's': 20, 'zorder': 5}, 'spike': {'linewidths': 0.0, 'marker': '^', 'rasterized': True, 's': 18, 'zorder': 5}}

Per-test hit markers for the “where it fires” overlay. A multi-sample flat run is drawn as a shaded span (an interval); a lone flat sample has no width, so it uses this square marker.

glidertest.plots_qc.plot_flag_profile(ds: xr.Dataset, var: str, *, flags: tuple | None = None, config: Mapping | None = None, width_in: float = 4.5, ax: Axes | None = None) → tuple[Figure, Axes][source]

Plot var against depth — a profile — with glidertest’s QC hits overlaid, “where it fires”.

Every finite sample is a small grey point at its (value, depth); gross-range, spike and flat-line hits are overlaid in the per-test colours. The y-axis is depth (deepest at the bottom), so a reader sees at what depth each flag falls — surface, a water mass, or the deep — which is what matters for a depth-structured sensor (optics, oxygen). The base is grey, not value-coloured. Requires DEPTH.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset carrying DEPTH and var.

  • var (str) – The variable whose QC hits to place against depth (e.g. "CHLA").

  • flags (tuple, optional) – The (gross, spike, flat) flag arrays from glidertest.qc.sample_tests(); computed on demand when None.

  • config (Mapping, optional) – Resolved per-variable thresholds (glidertest.config.loader.resolve_qc()); None uses the built-in defaults.

  • width_in (float, default glidertest.reports._vendored.design_tokens.W_HALF) – Figure width in inches; the height is derived from it.

  • ax (matplotlib.axes.Axes, optional) – Draw into this axis instead of creating a figure.

Returns:

The figure and axis drawn into.

Return type:

tuple of (matplotlib.figure.Figure, matplotlib.axes.Axes)

Notes

Original Author: Eleanor Frajka-Williams (glidertest).

glidertest.plots_qc.plot_flat_change(ds: xr.Dataset, var: str, *, flags: tuple | None = None, config: Mapping | None = None, width_in: float = 4.5, ax: Axes | None = None) → tuple[Figure, Axes][source]

Histogram the start-to-end value change of each multi-sample flat run, against the tolerance.

The flat-line test is meant to catch a stuck sensor — a run whose values are near-identical, so its start-to-end change falls within the test tolerance. A run whose total change far exceeds the tolerance is a slowly-varying real signal the test caught only because its short window (not the whole run) stayed within tolerance — a sign the window is too short for the sampling, not a stuck sensor. The count split at the tolerance line is the guess at how many flagged runs are genuinely flat: left of the line, stuck-like; right of it, the data moved.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset.

  • var (str) – The variable to assess.

  • flags (tuple, optional) – The (gross, spike, flat) flag arrays; computed on demand when None.

  • config (Mapping, optional) – Resolved per-variable thresholds (glidertest.config.loader.resolve_qc()); None uses the built-in defaults.

  • width_in (float, default glidertest.reports._vendored.design_tokens.W_HALF) – Figure width in inches.

  • ax (matplotlib.axes.Axes, optional) – Draw into this axis instead of creating a figure.

Returns:

The figure and axis drawn into.

Return type:

tuple of (matplotlib.figure.Figure, matplotlib.axes.Axes)

Raises:

ValueError – When var has no multi-sample flat run (e.g. an off-phase sensor whose flat flags are all isolated single samples), so there is no start-to-end change to measure.

Notes

Original Author: Eleanor Frajka-Williams (glidertest).

glidertest.plots_qc.plot_flat_excerpt(ds: xr.Dataset, var: str, *, flags: tuple | None = None, config: Mapping | None = None, width_in: float = 4.5, ax: Axes | None = None) → tuple[Figure, Axes][source]

Plot a zoom around the longest flagged flat run: samples as dots and a ±tolerance band.

Shows what the test called “flat” — often two samples a tolerance apart in genuinely stable water or low signal, not a stuck sensor.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset.

  • var (str) – The variable to assess.

  • flags (tuple, optional) – The (gross, spike, flat) flag arrays; computed on demand when None.

  • config (Mapping, optional) – Resolved per-variable thresholds (glidertest.config.loader.resolve_qc()); None uses the built-in defaults.

  • width_in (float, default glidertest.reports._vendored.design_tokens.W_HALF) – Figure width in inches.

  • ax (matplotlib.axes.Axes, optional) – Draw into this axis instead of creating a figure.

Returns:

The figure and axis drawn into.

Return type:

tuple of (matplotlib.figure.Figure, matplotlib.axes.Axes)

Notes

Original Author: Eleanor Frajka-Williams (glidertest).

glidertest.plots_qc.plot_flat_runs(ds: xr.Dataset, var: str, *, flags: tuple | None = None, config: Mapping | None = None, width_in: float = 4.5, ax: Axes | None = None) → tuple[Figure, Axes][source]

Plot flat-run durations as a histogram with the test windows and the median sampling interval.

This is the plot that shows the flat-line test is misconfigured: if the suspect and fail windows sit left of the median sampling interval, every sample is a “flat run” by construction and the counts are meaningless.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset.

  • var (str) – The variable to assess.

  • flags (tuple, optional) – The (gross, spike, flat) flag arrays; computed on demand when None.

  • config (Mapping, optional) – Resolved per-variable thresholds (glidertest.config.loader.resolve_qc()); None uses the built-in defaults.

  • width_in (float, default glidertest.reports._vendored.design_tokens.W_HALF) – Figure width in inches.

  • ax (matplotlib.axes.Axes, optional) – Draw into this axis instead of creating a figure.

Returns:

The figure and axis drawn into.

Return type:

tuple of (matplotlib.figure.Figure, matplotlib.axes.Axes)

Notes

Original Author: Eleanor Frajka-Williams (glidertest).

glidertest.plots_qc.plot_spike_stat(ds: xr.Dataset, var: str, *, config: Mapping | None = None, width_in: float = 4.5, ax: Axes | None = None) → tuple[Figure, Axes][source]

Plot the spike statistic (|value − neighbour average|) as a histogram with the thresholds.

The suspect and fail thresholds are drawn as vertical lines; if the bulk of the distribution sits past a line the threshold is wrong for this platform, if only a tail does the test is doing its job. The median sampling interval is printed, since a spike threshold assumes a sampling interval.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset.

  • var (str) – The variable to assess.

  • config (Mapping, optional) – Resolved per-variable thresholds (glidertest.config.loader.resolve_qc()); None uses the built-in defaults.

  • width_in (float, default glidertest.reports._vendored.design_tokens.W_HALF) – Figure width in inches.

  • ax (matplotlib.axes.Axes, optional) – Draw into this axis instead of creating a figure.

Returns:

The figure and axis drawn into.

Return type:

tuple of (matplotlib.figure.Figure, matplotlib.axes.Axes)

Notes

Original Author: Eleanor Frajka-Williams (glidertest).

glidertest.plots_qc.plot_test_hits(ds: xr.Dataset, var: str, *, flags: tuple | None = None, config: Mapping | None = None, width_in: float = 9.0, ax: Axes | None = None) → tuple[Figure, Axes][source]

Plot var over the full record with glidertest’s QC test hits overlaid — “where it fires”.

Gross-range hits as ×, spike hits as ▲ (one colour per test), and flat-line runs as shaded spans (a run is an interval). When the file carries <var>_QC, the delivered suspect and fail samples are overlaid as + in the flag colours. Only hits are drawn, so the overlay is cheap even at 10^6 samples.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset.

  • var (str) – The variable to plot (e.g. "TEMP").

  • flags (tuple, optional) – The (gross, spike, flat) flag arrays from glidertest.qc.sample_tests(); computed on demand when None (so a notebook call needs nothing extra; the report passes them in once).

  • config (Mapping, optional) – Resolved per-variable thresholds (glidertest.config.loader.resolve_qc()); None uses the built-in defaults.

  • width_in (float, default glidertest.reports._vendored.design_tokens.W_FULL) – Figure width in inches; the height is derived from it.

  • ax (matplotlib.axes.Axes, optional) – Draw into this axis instead of creating a figure.

Returns:

The figure and axis drawn into.

Return type:

tuple of (matplotlib.figure.Figure, matplotlib.axes.Axes)

Notes

Original Author: Eleanor Frajka-Williams (glidertest).

glidertest.plots_qc.plot_ts_gross_range(ds: xr.Dataset, *, config: Mapping | None = None, width_in: float = 4.5, ax: Axes | None = None) → tuple[Figure, Axes][source]

Plot the T–S cloud with the TEMP×PSAL gross-range suspect and fail spans as nested rectangles.

One glance says whether the limits are regional (the whole cloud hugs an edge) or the points outside are genuine outliers. Requires TEMP and PSAL.

Parameters:
  • ds (xarray.Dataset) – An OG1 glider dataset carrying TEMP and PSAL.

  • config (Mapping, optional) – Resolved per-variable thresholds (glidertest.config.loader.resolve_qc()); None uses the built-in defaults.

  • width_in (float, default glidertest.reports._vendored.design_tokens.W_HALF) – Figure width in inches.

  • ax (matplotlib.axes.Axes, optional) – Draw into this axis instead of creating a figure.

Returns:

The figure and axis drawn into.

Return type:

tuple of (matplotlib.figure.Figure, matplotlib.axes.Axes)

Notes

Original Author: Eleanor Frajka-Williams (glidertest).

Quality-control checks and thresholds, independent of any output format.

Holds the QARTOD threshold configs, the on-the-fly check runner qc_checks, the verdict helpers (fill_str, hysteresis_verdict), the profile sentences (phrase_*_check), and the OceanSITES/QARTOD flag vocabulary (QC_FLAG_CATEGORIES / flag_counts). Kept free of the RST/PDF stack (rstcloth/pypandoc) so the HTML report can use it without that toolchain; summary_sheet imports these names back for the RST summary sheet.

Original Author: Chiara Monforte.

glidertest.qc.HYSTERESIS_PCT_THRESHOLD = 5

Hysteresis verdict thresholds, named so the report table and the verdict rule cannot drift (the table reads these constants, not hysteresis_verdict.__defaults__ by position): a depth bin counts as exceeded above HYSTERESIS_PCT_THRESHOLD percent dive–climb error, and a variable is flagged when more than HYSTERESIS_BIN_THRESHOLD bins exceed it.

glidertest.qc.QC_FLAG_CATEGORIES = ((1, 'good', 'Good'), (3, 'suspect', 'Suspect'), (4, 'fail', 'Fail'), (2, 'not_eval', 'Not evaluated'), (9, 'missing', 'Missing'))

OceanSITES/QARTOD flag value -> (category key, label), in display order (good, suspect, fail, then the non-graded categories). Covers every flag value so counts sum to the array size.

glidertest.qc.configs = {'CHLA': {'flat_line_test': {'fail_threshold': 30, 'suspect_threshold': 10, 'tolerance': 0.01}, 'gross_range_test': {'fail_span': [-1, 20], 'suspect_span': [0, 15]}, 'spike_test': {'fail_threshold': 5, 'suspect_threshold': 1}}, 'DOXY': {'flat_line_test': {'fail_threshold': 4, 'suspect_threshold': 2, 'tolerance': 0.01}, 'gross_range_test': {'fail_span': [0, 500], 'suspect_span': [0, 350]}, 'spike_test': {'fail_threshold': 50, 'suspect_threshold': 10}}, 'PSAL': {'flat_line_test': {'fail_threshold': 4, 'suspect_threshold': 2, 'tolerance': 0.0005}, 'gross_range_test': {'fail_span': [2, 41], 'suspect_span': [5, 38]}, 'spike_test': {'fail_threshold': 0.9, 'suspect_threshold': 0.3}}, 'TEMP': {'flat_line_test': {'fail_threshold': 4, 'suspect_threshold': 2, 'tolerance': 0.0005}, 'gross_range_test': {'fail_span': [-2.5, 40], 'suspect_span': [0, 30]}, 'spike_test': {'fail_threshold': 6.0, 'suspect_threshold': 2.0}}}

Built-in QARTOD thresholds per variable (the layer-1 defaults). A report config’s qc: block is deep-merged over this by glidertest.config.loader.resolve_qc(); the resolved mapping, not this dict, is what the checks and plots read when a config is in play. The location test is driven by a configured region.bbox (no built-in default), so no location_test entry lives here. flat_line_test windows and tolerances are set per variable. The test flags a point when the value’s range (max − min) over the trailing window stays below tolerance — so a tighter tolerance flags fewer points (only a near-constant, genuinely-stuck sensor), and a longer window flags fewer points (the value must stay flat for longer). The tolerance is in each variable’s own stored units, chosen small so real variation is not read as flat: TEMP 0.0005 Celsius, PSAL 0.0005 (practical salinity), DOXY 0.01 mmol m-3, CHLA 0.01 mg m-3. Windows: CHLA 10 s / 30 s (chlorophyll is sampled off-phase at a coarser cadence, so a short window flags nearly every point, #346); TEMP/PSAL/DOXY 2 s / 4 s. These are report defaults, not instrument specifications — adjust per deployment with a qc: override; suggest_flat_line() suggests windows from the sampling.

glidertest.qc.fill_str(strgr, strst, strft, strhy, strdr, ds, var='TEMP')[source]

Populate QC summary strings for a selected variable based on a series of QC checks.

Parameters:
  • strgr (list of str) – Row for Global range test results with X or ✓, structured as [label/test name, TEMP, PSAL, DOXY, CHLA].

  • strst (list of str) – Row for Spike test results with X or ✓, structured as [label/test name, TEMP, PSAL, DOXY, CHLA].

  • strft (list of str) – Row for Flat line test results with X or ✓, structured as [label/test name, TEMP, PSAL, DOXY, CHLA].

  • strhy (list of str) – Row for Hysteresis error (mean) results with X or ✓, structured as [label/test name, TEMP, PSAL, DOXY, CHLA].

  • strdr (list of str) – Row for Hysteresis error (range) results with X or ✓, structured as [label/test name, TEMP, PSAL, DOXY, CHLA].

  • ds (xarray.Dataset) – Dataset in OG1 format, containing the selected variable.

  • var (str, optional, default='TEMP') – Selected variable to evaluate. Must be one of: ‘TEMP’, ‘PSAL’, ‘DOXY’, ‘CHLA’.

Returns:

  • strgr (list of str) – Updated Global range test row.

  • strst (list of str) – Updated Spike test row.

  • strft (list of str) – Updated Flat line test row.

  • strhy (list of str) – Updated Hysteresis error (mean) row.

  • strdr (list of str) – Updated Hysteresis error (range) row.

Notes

  • Input string is filled with ✓. Each list entry is updated with an ‘X’ if a QC issue is detected for the corresponding variable.

  • If the variable is missing in the dataset, all tests for that variable are marked as “No data”.

  • Column indices are mapped as: TEMP=1, PSAL=2, DOXY=3, CHLA=4.

Original Author: Chiara Monforte.

glidertest.qc.flag_counts(flags)[source]

Return a {category_key: count} dict for a QARTOD/OceanSITES flag array.

Counts the five graded/non-graded categories (good=1, suspect=3, fail=4, not-evaluated=2, missing=9) and adds an "other" bucket holding every remaining value — for example OG1’s 0 (“no QC applied”) or any non-standard flag — so the returned counts always sum to the array size and no flagged sample is silently dropped.

Parameters:

flags (array-like) – A QARTOD/OceanSITES integer flag array.

Returns:

Count per category key in QC_FLAG_CATEGORIES order, plus "other"; the values sum to size.

Return type:

dict of str to int

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.qc.flag_labels(da)[source]

Return a {flag_value: label} map read from a QC variable’s flag_values/flag_meanings.

OG1 *_QC variables carry their own flag scale in attributes (for example flag_values = [1, 2, 3, 4, 9] with flag_meanings = "GOOD UNKNOWN SUSPECT FAIL MISSING"), so the label of each flag is read from the file rather than assumed. Flag values the file does not label fall back to the default labels in QC_FLAG_CATEGORIES. Only the label is file-specific; the colour category of a flag stays fixed by its numeric value (1 good, 3 suspect, 4 fail).

Parameters:

da (xarray.DataArray) – A QC flag variable. Only its attrs are read, not its values.

Returns:

Label per flag value, covering at least the values in QC_FLAG_CATEGORIES.

Return type:

dict of int to str

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.qc.flag_scale_mismatch(da)[source]

Return (n_values, n_meanings) when a QC variable’s declared flag scale is inconsistent.

An OG1 *_QC variable should declare flag_values and flag_meanings of equal length. When they differ the file’s flag scale cannot be trusted — a finding a diagnose tool should surface rather than silently use a partial scale.

Parameters:

da (xarray.DataArray) – A QC flag variable. Only its attrs are read.

Returns:

(len(flag_values), len(flag_meanings)) when the two differ, else None (consistent, or one/both attributes absent).

Return type:

tuple of (int, int) or None

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.qc.gross_range_mask(ds, var='TEMP', *, config=None)[source]

Return a boolean per-sample mask of var values outside the gross-range suspect span.

The one definition of “out of range” shared by the diagnostics-matrix count and the QC plots, so the table and the plotted hits cannot diverge. NaN samples are not flagged (the comparison is False for NaN). Returns an all-False mask when var has no gross_range_test suspect span in the thresholds.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing var.

  • var (str, optional, default='TEMP') – Variable to test.

  • config (Mapping, optional) – Resolved per-variable thresholds (see sample_tests()); None uses the built-in configs.

Returns:

Boolean mask, True where the value is below the span minimum or above its maximum.

Return type:

numpy.ndarray

Notes

Original Author: Eleanor Frajka-Williams

glidertest.qc.hysteresis_verdict(err, pct_threshold=5, bin_threshold=5)[source]

Return (n_over, flagged) for a hysteresis dive-climb error array.

The single verdict rule shared by the RST summary (fill_str()) and the HTML report, so the two never disagree. err is indexed by depth bin, not profile.

Parameters:
  • err (array-like) – Per-depth-bin percentage dive-climb error (err_mean or err_range from glidertest.tools.compute_hyst_stat()).

  • pct_threshold (float, optional) – Percentage error above which a depth bin counts as exceeded. Default 5.

  • bin_threshold (int, optional) – A variable is flagged when more than this many depth bins exceed pct_threshold. Default 5.

Returns:

(n_over, flagged) — bins exceeding the threshold, and the flag verdict.

Return type:

tuple of (int, bool)

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.qc.phrase_duration_check(ds)[source]

Check for anomalies in profile duration and return a human-readable message summarizing the result.

Parameters:

ds (xarray.Dataset) – Dataset in OG1 format, containing time information required for computing profile durations.

Returns:

duration_check – A message indicating whether abnormal profile durations have been detected: - If outliers are found: “X profiles have abnormal duration” - Otherwise: “No issues with profile duration have been detected”

Return type:

str

Notes

Original Author: Chiara Monforte.

glidertest.qc.phrase_numberprof_check(ds)[source]

Check the monotonicity of profile numbers and return a human-readable summary of the result.

Parameters:

ds (xarray.Dataset) – Dataset in OG1 format, containing the PROFILE_NUMBER variable.

Returns:

prof_check – A message indicating whether profile numbers increase monotonically: - If monotonic: “No issues detected” - If not monotonic: “Issues with profile number have been detected”

Return type:

str

Notes

Original Author: Chiara Monforte.

glidertest.qc.qc_checks(ds, var='TEMP', *, config=None)[source]

Run a series of basic quality control (global range, spike test, drift and hysteresis) checks on a selected variable in the dataset. We use functions from glidertest.tools as well as ioos qartod.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing the selected variable and time information.

  • var (str, optional, default='TEMP') – Variable to perform QC checks on.

  • config (Mapping, optional) – Resolved per-variable thresholds (see sample_tests()); None uses the built-in configs.

Returns:

  • gr (xarray.DataArray) – Result of the gross range test, identifying values outside the expected physical range.

  • spike (xarray.DataArray) – Result of the spike test, detecting sudden changes in data based on threshold configuration.

  • flat (xarray.DataArray) – Result of the flat line test, identifying segments with little or no variation.

  • err_mean (array-like) – Percentage error of the dive-climb difference based on the mean values, from hysteresis analysis.

  • err_range (array-like) – Percentage error of the dive-climb difference based on the value range, from hysteresis analysis.

Notes

  • Thresholds for QC tests are taken from config when given, else the global configs dictionary.

Original Author: Chiara Monforte

glidertest.qc.region_test(ds, bbox)[source]

Flag each sample by whether its position lies inside the configured region box.

glidertest’s own region check: ioos_qc 3.0.0’s location_test has no bounding box (it checks only the global sane bounds lon [-180, 180], lat [-90, 90]), so the region test lives here. A glider outside the region you declared is a fail, not a suspect — the point of the test is to catch a mission that strayed from, or was mislabelled against, its expected area. Points on the boundary count as inside. Run only when a report config supplies region.bbox; there is no built-in box (a box drawn from the data cannot fail its own test).

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format; reads LONGITUDE and LATITUDE.

  • bbox (sequence of float) – [lon_min, lat_min, lon_max, lat_max] = [west, south, east, north] (GeoJSON / ioos_qc 2.x order).

Returns:

QARTOD flags per sample: 1 inside or on the box, 4 outside, 9 where LONGITUDE or LATITUDE is NaN (position unknown).

Return type:

numpy.ndarray

Notes

Original Author: Eleanor Frajka-Williams

glidertest.qc.sample_tests(ds, var='TEMP', *, config=None)[source]

Run the three sample-wise QARTOD tests (gross range, spike, flat line) on var.

Split out of qc_checks() (which adds the hysteresis statistics) so the report’s QC page plots and the delivered-vs-glidertest matrix share one computation and one set of thresholds.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing var and TIME.

  • var (str, optional, default='TEMP') – Variable to test.

  • config (Mapping, optional) – Resolved per-variable thresholds (as from glidertest.config.loader.resolve_qc()); when None the built-in configs are used, so a bare call is unchanged.

Returns:

  • gr (numpy.ndarray) – Gross-range test flags.

  • spike (numpy.ndarray) – Spike test flags.

  • flat (numpy.ndarray) – Flat-line test flags.

Notes

Original Author: Chiara Monforte

glidertest.qc.suggest_flat_line(ds, var=None, suspect_factor=2, fail_factor=3)[source]

Suggest flat-line windows (seconds) from the sampling interval of var (or the whole record).

A flat-line window set in seconds must span at least a couple of the sensor’s own samples to say anything about flatness. For a sensor sampled off-phase (optics, oxygen — finite only every Nth cycle) the per-variable interval is coarser than the record’s, so basing the window on the record would suggest one too short. Pass var to use that variable’s finite-sample interval; omit it for the whole-record interval. The suggestion is ``suspect_factor``× (default 2) and ``fail_factor``× (default 3) that interval.

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, with TIME (and var when given).

  • var (str, optional) – Variable whose finite-sample interval to use; when None the whole-record interval is used.

  • suspect_factor (int, optional) – Multiples of the sampling interval for the suspect (2) and fail (3) windows.

  • fail_factor (int, optional) – Multiples of the sampling interval for the suspect (2) and fail (3) windows.

Returns:

{dt, suspect, fail, suspect_factor, fail_factor} — the interval and the suggested windows in seconds (dt NaN when there are fewer than two finite samples).

Return type:

dict

Notes

Original Author: Eleanor Frajka-Williams

glidertest.qc.suggest_gross_range(ds, var='TEMP', inner_pct=99.9, suspect_pad=0.01, fail_pad=0.05)[source]

Suggest data-driven gross-range spans for var from this mission’s value distribution.

A diagnostic suggestion, not a fix: it describes where this deployment’s values lie, as a starting point for a mission config — not a universal physical range. The inner inner_pct of the finite values is taken (default the central 99.9%, i.e. the 0.05th–99.95th percentiles), then padded outward by a fraction of that span — suspect_pad and fail_pad — so the margin scales with each variable’s own range rather than with the value (1% of 4 °C is not 1% of 35 psu). The lower bound is clamped at 0 for non-negative variables (_NONNEGATIVE_VARS).

Parameters:
  • ds (xarray.Dataset) – Dataset in OG1 format, containing var.

  • var (str, optional, default='TEMP') – Variable to suggest limits for.

  • inner_pct (float, optional, default=99.9) – Central percentile of the data taken as the core range before padding.

  • suspect_pad (float, optional) – Fractions of the core span added on each side for the suspect (0.01) and fail (0.05) spans.

  • fail_pad (float, optional) – Fractions of the core span added on each side for the suspect (0.01) and fail (0.05) spans.

Returns:

{lo, hi, inner_pct, suspect, fail, suspect_pad, fail_pad} (spans as [min, max], all rounded), or None when var has no finite values.

Return type:

dict or None

Notes

Original Author: Eleanor Frajka-Williams

OG1 global-attribute registry, transcribed from the OceanGliders format user manual.

Source: OG_Format.adoc, “Global attributes” table, OceanGlidersCommunity/OG-format-user-manual. The registry (ATTR_GROUPS) is the single source of truth: it lists all 41 OG1 global attributes, grouped into four categories, each attribute carrying its requirement tier (mandatory / highly desirable / suggested) from the manual. GLOBAL_ATTR_ORDER and MANDATORY_GLOBALS are derived from it.

Presence only — attribute values are not format-checked. A present value is reported as present whatever its content, so the report’s amber marking means one thing: a mandatory attribute is missing. This does not reproduce the full OG1 compliance checker.

The manual states several contributor/institution rows conditionally (“PI name is mandatory”, “Operator role is mandatory”); those are recorded here at the mandatory tier for the PI- and operator-level fields, matching the manual’s minimum-conformance set of 16 mandatory attributes.

glidertest.og1_attrs.ATTR_GROUPS: tuple[tuple[str, tuple[tuple[str, Literal['mandatory', 'highly_desirable', 'suggested']], ...]], ...] = (('Identity & discovery', (('title', 'mandatory'), ('platform', 'mandatory'), ('platform_vocabulary', 'mandatory'), ('id', 'mandatory'), ('naming_authority', 'highly_desirable'), ('institution', 'highly_desirable'), ('internal_mission_identifier', 'highly_desirable'), ('site', 'highly_desirable'), ('site_vocabulary', 'highly_desirable'), ('program', 'highly_desirable'), ('program_vocabulary', 'highly_desirable'), ('project', 'suggested'), ('network', 'suggested'))), ('Spatiotemporal coverage', (('geospatial_lat_min', 'suggested'), ('geospatial_lat_max', 'suggested'), ('geospatial_lon_min', 'suggested'), ('geospatial_lon_max', 'suggested'), ('geospatial_vertical_min', 'suggested'), ('geospatial_vertical_max', 'suggested'), ('time_coverage_start', 'highly_desirable'), ('time_coverage_end', 'highly_desirable'))), ('People & institutions', (('contributor_name', 'mandatory'), ('contributor_email', 'mandatory'), ('contributor_id', 'highly_desirable'), ('contributor_role', 'mandatory'), ('contributor_role_vocabulary', 'mandatory'), ('contributing_institutions', 'mandatory'), ('contributing_institutions_vocabulary', 'highly_desirable'), ('contributing_institutions_role', 'mandatory'), ('contributing_institutions_role_vocabulary', 'mandatory'))), ('Provenance & processing', (('uri', 'suggested'), ('data_url', 'highly_desirable'), ('doi', 'highly_desirable'), ('rtqc_method', 'mandatory'), ('rtqc_method_doi', 'highly_desirable'), ('web_link', 'suggested'), ('comment', 'suggested'), ('start_date', 'mandatory'), ('date_created', 'mandatory'), ('featureType', 'mandatory'), ('Conventions', 'mandatory'))))

the single source of truth for which attributes exist, their category, their canonical order within the category, and their requirement tier. Categories and the order within each are glidertest’s grouping of the manual’s flat table; the tier of each attribute is transcribed from the manual’s “Requirement status” column. GLOBAL_ATTR_ORDER (flat order) and MANDATORY_GLOBALS are derived from this, so they cannot drift from it.

Type:

The OG1 global-attribute registry

glidertest.og1_attrs.GLOBAL_ATTR_ORDER: tuple[str, ...] = ('title', 'platform', 'platform_vocabulary', 'id', 'naming_authority', 'institution', 'internal_mission_identifier', 'site', 'site_vocabulary', 'program', 'program_vocabulary', 'project', 'network', 'geospatial_lat_min', 'geospatial_lat_max', 'geospatial_lon_min', 'geospatial_lon_max', 'geospatial_vertical_min', 'geospatial_vertical_max', 'time_coverage_start', 'time_coverage_end', 'contributor_name', 'contributor_email', 'contributor_id', 'contributor_role', 'contributor_role_vocabulary', 'contributing_institutions', 'contributing_institutions_vocabulary', 'contributing_institutions_role', 'contributing_institutions_role_vocabulary', 'uri', 'data_url', 'doi', 'rtqc_method', 'rtqc_method_doi', 'web_link', 'comment', 'start_date', 'date_created', 'featureType', 'Conventions')

category order, then the canonical order within each category. Derived from ATTR_GROUPS so it is one list, not a second hand-kept copy.

Type:

Canonical order of OG1 global attributes

glidertest.og1_attrs.MANDATORY_GLOBALS: tuple[str, ...] = ('title', 'platform', 'platform_vocabulary', 'id', 'contributor_name', 'contributor_email', 'contributor_role', 'contributor_role_vocabulary', 'contributing_institutions', 'contributing_institutions_role', 'contributing_institutions_role_vocabulary', 'rtqc_method', 'start_date', 'date_created', 'featureType', 'Conventions')

The mandatory OG1 global attributes (tier "mandatory" in ATTR_GROUPS), in canonical order. The manual’s minimum-conformance set.

glidertest.og1_attrs.OTHER_GROUP = 'Other (not in OG1)'

Title for file attributes not named in ATTR_GROUPS (never dropped); shown last.

glidertest.og1_attrs.Tier

Requirement tier of an OG1 global attribute (manual “Requirement status” column).

alias of Literal[‘mandatory’, ‘highly_desirable’, ‘suggested’]

glidertest.og1_attrs.check_globals(ds: xr.Dataset) → list[tuple[str, Status, str]][source]

Check whether ds carries each mandatory OG1 global attribute.

Presence only — attribute values are not format-checked (see the module docstring).

Parameters:

ds (xarray.Dataset) – The dataset whose attrs are checked.

Returns:

One (attribute, status, value) tuple per mandatory attribute, in canonical order. "match" — present and non-empty; "none" — absent or present-but-empty.

Return type:

list of (str, {“match”, “none”}, str)

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.og1_attrs.conformance_summary(attrs: Mapping[str, object]) → dict[str, int][source]

Return counts for the index’s one-line OG1 conformance verdict.

Parameters:

attrs (collections.abc.Mapping) – A dataset’s global attributes (ds.attrs).

Returns:

mandatory_present / mandatory_total and highly_desirable_missing — enough to render “OG1: N/M mandatory present · K highly-desirable missing”.

Return type:

dict of str to int

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.og1_attrs.group_globals(attrs: Mapping[str, object]) → list[dict[str, object]][source]

Group attrs by OG1 category for the inventory’s merged conformance-and-value tables.

Walks ATTR_GROUPS (not attrs), so the result includes rows for attributes the file lacks — this is what lets one table carry both the value (when present) and the conformance status (present / missing). The display rule follows the registry tier of each row:

  • mandatory — always shown; present is False when absent (the caller marks it amber);

  • highly desirable — always shown; absent rows carry present=False and no value;

  • suggested — shown only when present; an absent suggested attribute is omitted entirely.

File attributes not in the registry are collected into a trailing OTHER_GROUP, in file order, never dropped. Empty groups are omitted.

Parameters:

attrs (collections.abc.Mapping) – A dataset’s global attributes (ds.attrs).

Returns:

[{"title": str, "rows": [{"name", "value", "tier", "present"}, ...]}, ...]. value is the stringified attribute value when present, else None; tier is None for rows in OTHER_GROUP.

Return type:

list of dict

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.og1_attrs.order_globals(attrs: Mapping[str, object]) → list[str][source]

Return attrs’ keys in OG1 canonical order, with non-OG1 keys after, in their given order.

Keys present in GLOBAL_ATTR_ORDER come first, in that order; any remaining key (not an OG1 global attribute) follows in attrs’ own iteration order. No key is added or dropped — only reordered.

Parameters:

attrs (collections.abc.Mapping) – A dataset’s global attributes (ds.attrs).

Returns:

The keys of attrs, canonical OG1 attributes first, then the rest in file order.

Return type:

list of str

Notes

Original Author: Eleanor Frajka-Williams.

glidertest.utilities.bin_profile(ds_profile, variables, binning, agg: str = 'mean')[source]

Bins the data for a single profile using the construct_2dgrid function. The binning determines the depth resolution.

Parameters:
  • ds_profile (xr.Dataset or pd.DataFrame) – The dataset or dataframe containing the data of one profile containing at least ‘DEPTH’, ‘PROFILE_NUMBER’ and the variables to bin.

  • variables (list) – The variables to bin.

  • binning (float) – The depth resolution for binning.

  • agg (str, optional) – The aggregation method (‘mean’ or ‘median’). Default is ‘mean’.

Returns:

binned_profile – A dataframe containing the binned data for the selected profile.

Return type:

pd.DataFrame

Notes

Original author: Till Moritz

glidertest.utilities.calc_DEPTH_Z(ds)[source]

Calculate the depth (Z position) of the glider using the gsw library to convert pressure to depth.

Parameters:

ds (xarray.Dataset) – The input dataset containing ‘PRES’, ‘LATITUDE’, and ‘LONGITUDE’ variables.

Returns:

The dataset with an additional ‘DEPTH_Z’ variable.

Return type:

xarray.Dataset

Notes

Original Author: Eleanor Frajka-Williams

glidertest.utilities.compute_sunset_sunrise(time, lat, lon)[source]

Calculates the local sunrise/sunset of the glider location from GliderTools.

The function uses the Skyfield package to calculate the sunrise and sunset times using the date, latitude and longitude. The times are returned rather than day or night indices, as it is more flexible for the quenching correction.

Parameters:
  • time (numpy.ndarray or pandas.Series) – The date & time array in a numpy.datetime64 format.

  • lat (numpy.ndarray or pandas.Series) – The latitude of the glider position.

  • lon (numpy.ndarray or pandas.Series) – The longitude of the glider position.

Returns:

  • sunrise (numpy.ndarray) – An array of the sunrise times.

  • sunset (numpy.ndarray) – An array of the sunset times.

Notes

Original Author: Function from GliderTools [Source Code](https://github.com/GliderToolsCommunity/GliderTools/blob/master/glidertools/optics.py)

glidertest.utilities.construct_2dgrid(x, y, v, xi=1, yi=1, x_bin_center: bool = True, y_bin_center: bool = True, agg: str = 'median')[source]

Constructs a 2D gridded representation of input data based on specified resolutions. The function takes in x, y, and v data, and generates a grid where each cell contains the aggregated value (e.g., mean, median) of v corresponding to the x and y coordinates. If the input data is already binned and you want the grid coordinates to align with the original bin edges, set x_bin_center and y_bin_center to False and the resolution (i.e. xi and yi) to the bin size.

Parameters:
  • x (array-like) – Input data representing the x-dimension.

  • y (array-like) – Input data representing the y-dimension.

  • v (array-like) – Input data representing the z-dimension (values to be gridded).

  • xi (int or float, optional, default=1) – Resolution for the x-dimension grid spacing.

  • yi (int or float, optional, default=1) – Resolution for the y-dimension grid spacing.

  • x_bin_center (bool, optional, default=True) – If True, the x-coordinate grid (XI) corresponds to the center of each x-bin. If False, it corresponds to the left edge of each bin. This is especially useful if the input x data is already binned with the same resolution as xi, and you want the grid coordinates to align with the original bin edges. (e.g. profile numbers).

  • y_bin_center (bool, optional, default=True) – Same as x_bin_center, but for the y-coordinate grid (YI). Set to False if your y data is already pre-binned with the same resolution as yi.

  • agg (str, optional, default='median') – Aggregation method to be used for gridding. Options include ‘mean’, ‘median’, etc.

Returns:

  • grid (numpy.ndarray) – Gridded representation of the z-values over the x and y space.

  • XI (numpy.ndarray) – Gridded x-coordinates corresponding to the specified resolution.

  • YI (numpy.ndarray) – Gridded y-coordinates corresponding to the specified resolution.

Notes

Original Author: Bastien Queste [Source Code](https://github.com/bastienqueste/gliderad2cp/blob/de0652f70f4768c228f83480fa7d1d71c00f9449/gliderad2cp/process_adcp.py#L140)

Modified by Till Moritz: added the aggregation parameter and the option to chose either bin center or bin edge as the grid coordinates.

glidertest.utilities.get_color_limits(values, log_scale=False)[source]
glidertest.utilities.get_contour_levels(levels=None, log_scale=False, vmin=None, vmax=None)[source]
glidertest.utilities.group_by_profiles(ds, variables=None)[source]

Group glider dataset by the dive profile number.

This function groups the dataset by the PROFILE_NUMBER column, where each group corresponds to a single profile. The resulting groups can be evaluated statistically, for example using methods like pandas.DataFrame.mean or other aggregation functions. To filter a specific profile, use xarray.Dataset.where instead.

Parameters:
  • ds (xarray.Dataset) – A 1-dimensional glider dataset containing profile information.

  • variables (list of str, optional) – A list of variable names to group by, if only a subset of the dataset should be included in the grouping. Grouping by a subset is more memory-efficient and faster.

Returns:

profiles – A pandas GroupBy object, grouped by the PROFILE_NUMBER of the glider dataset. This can be further aggregated using methods like mean or sum.

Return type:

pandas.core.groupby.DataFrameGroupBy

Notes

This function is based on the original GliderTools implementation and was modified by Chiara Monforte to ensure compliance with the OG1 standards. [Source Code](https://github.com/GliderToolsCommunity/GliderTools/blob/master/glidertools/utils.py)

glidertest.utilities.plotting_colormap(variable: str)[source]

Retrieves the colormap associated with a variable from a predefined dictionary.

This function checks if the given variable var exists as a key in the label_dict dictionary. If found, it returns the associated colormap from label_dict. If not, it returns cmocean.cm.delta as a default colormap.

Parameters:

variable (str) – The variable (key) whose colormap is to be retrieved.

Returns:

colormap – The colormap corresponding to the variable var. If the variable is not found in label_dict, the function returns None.

Return type:

matplotlib colormap or None

Notes

Original Author: Till Moritz

glidertest.utilities.plotting_labels(variable: str)[source]

Retrieves the label associated with a variable from a predefined dictionary.

This function checks if the given variable var exists as a key in the label_dict dictionary. If found, it returns the associated label from label_dict. If not, it returns the variable name itself as the label.

Parameters:

variable (str) – The variable (key) whose label is to be retrieved.

Returns:

The label corresponding to the variable var. If the variable is not found in label_dict, the function returns the variable name as the label.

Return type:

str

Notes

Original Author: Chiara Monforte

glidertest.utilities.plotting_units(ds: Dataset, variable: str)[source]

Retrieves the units associated with a variable from a dataset or a predefined dictionary.

This function first checks if the given variable as a key in label_dict. has units in the attributes. If so, it returns the units defined in the dictionary. Otherwise, it checks whether the variable has units from the dataset attributes and returns its value if available. In case none of the two exist, the field is left empty.

Parameters:
  • ds (xarray.Dataset) – The dataset containing the variable var.

  • variable (str) – The variable (key) whose units are to be retrieved.

Returns:

The units associated with the variable. Units defined in label_dict are preferred over those stored in the variable’s dataset attributes. If neither source provides the units, an empty string is returned.

Return type:

str

Notes

Original Author: Chiara Monforte

glidertest.fetchers.load_sample_dataset(dataset_name='sea045_20230604T1253_delayed.nc')[source]

Download sample datasets for use with glidertest

Parameters:

dataset_name (str, optional) – Default is “sea045_20230604T1253_delayed.nc”.

Raises:

ValueError: – If the requests dataset is not known, raises a value error

Returns:

Requested sample dataset

Return type:

xarray.Dataset

glidertest.interactive.daynight_avg(ds)[source]

Creates an interactive day/night average plot with external slider inputs.

Parameters:

ds (xarray.Dataset) – The dataset containing profile information.

The function provides the following interactive widgets:
  • Variable: Dropdown to choose the variable to plot.

  • Select the specific day to plot.

Notes

Original author: Till Moritz

glidertest.interactive.mission_map(ds_list)[source]

Makes an interactive folium map of a glider mission. Needs to run in a jupyter notebook

Parameters:

ds_list (xarray.DataSet or list of xarray.DataSets) – OG1 dataset of a glider mission. can pass a list of missions

Returns:

m – A folium map with a point for each glider dive and a sub-sampled line of glider track

Return type:

folium.Map

Notes

Original author: Callum Rollo

glidertest.interactive.profile(ds)[source]

Creates an interactive profile viewer with external slider inputs.

Parameters:

ds (xarray.Dataset) – The dataset containing profile information.

The function provides the following interactive widgets:
  • Profile Number: Selects the profile number from available profiles.

  • Variable 1, Variable 2, Variable 3: Dropdowns to choose up to three variables to plot.

  • Use Binned Data: Checkbox to toggle between raw and binned data.

  • Binning Resolution: Slider to adjust the binning resolution if binned data is used.

Notes

Original author: Till Moritz

glidertest.interactive.ts_plot(ds)[source]

Creates an interactive temperature-salinity plot with external slider inputs.

Parameters:

ds (xarray.Dataset) – The dataset containing profile information.

The function provides the following interactive widgets:
  • Percentile: Slider to adjust the percentiles for filtering the data.

Notes

Original author: Till Moritz

glidertest.interactive.up_down_bias(ds)[source]

Creates an interactive up/down bias plot with external slider inputs.

Parameters:

ds (xarray.Dataset) – The dataset containing profile information.

The function provides the following interactive widgets:
  • Variable: Dropdown to choose the variable to plot.

  • Vertical Resolution: Slider to adjust the vertical resolution for binning.

Notes

Original author: Till Moritz

Command-line entry point for glidertest: glidertest <command>.

Two subcommands, each a thin wrapper over the library:

report

Write an HTML report for one or more OG1 netCDF files and rebuild the fleet page.

navigator

Rebuild the fleet page over a report root from the per-mission manifests, reading no data.

No report logic lives here; the heavy imports (matplotlib, xarray, the report subsystem) are deferred into the command functions so glidertest --help stays fast and backend-free.

glidertest.cli.build_parser() → ArgumentParser[source]

Build the glidertest argument parser (the report, navigator and init subcommands).

Separated from main() so the documentation can render the parser with sphinx-argparse and the two cannot drift apart.

Returns:

The configured top-level parser.

Return type:

argparse.ArgumentParser

glidertest.cli.main(argv: list[str] | None = None) → None[source]

Parse argv (default sys.argv), dispatch to a subcommand, and exit with its code.

Parameters:

argv (list of str, optional) – Argument vector excluding the program name; defaults to sys.argv[1:].

Legacy

glidertest.summary_sheet builds the older RST/PDF “mission summary” (it is what pulls in the pandoc and rstcloth dependencies). The HTML report — glidertest.reports.report() — supersedes it; it is kept for existing users for now, and its removal is planned.