Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Contextual Integration of NCAR/NOAA Environmental Data with the NOAA Water Column Sonar Archive

Contextual Integration of NCAR/NOAA Environmental Data with the NOAA Water Column Sonar Archive

This notebook walks through an end-to-end workflow to relate shipboard sonar backscatter (Sv) to local environmental conditions. We (1) open EK60 data from a public NOAA S3 Zarr, (2) gather co-located environmental variables from OISST and IOOS ERDDAP, (3) compute hourly mean Sv, (4) assemble a depth×time error map for reference, and (5) synchronize timestamps to produce an interactive line-plus-heatmap visualization. All selections (time/depth/frequency) and conversions are kept explicit for reproducibility.

  1. Imports Load core libraries for data access (xarray, s3fs), analysis (numpy, pandas), plotting (plotly), and I/O.

  2. Initializing the datasets Access HB1906 EK60 Zarr data from public S3; subset by time/depth, select 38 kHz, and mask bins below bottom.

  3. Access buoy data Define Georges Bank buoy coordinates, sample daily OISST SST at the nearest grid cell (±1 day), and download the model error map (.npy).

  4. Calculate the temperature anomaly, sun elevation in degree and azimuth

  5. Downloading external error map for the specific location Downloading the error map comes from a fixed file

  6. Helper Function: Mean Sv (dB) Convert Sv from dB→linear, compute mean, convert back to dB.

  7. Group Cruise Data into Hourly Chunks Add an hourly label and split the EK60 dataset into per-hour xarray.Dataset chunks.

  8. Compute Hourly Mean Sv & Attach to env_df Aggregate Sv per hour and append results as a new column in the environmental dataframe.

  9. Build Depth×Time Error-Map DataFrame & Align Timestamps Construct a depth-by-time matrix from the error map, guard for size mismatches, and align env_df endpoints to the heatmap timestamps.

  10. Data Visualization: Synchronized Lines + Heatmap Plot environmental time series above a depth×time heatmap with shared x-axis; save interactive HTML output.


Prerequisites

This section was inspired by this template of the wonderful The Turing Way Jupyter Book.

This notebook opens public NOAA EK60 Zarr data from S3, subsets by time/depth, reads daily OISST SST near a buoy, fetches ERDDAP environmental variables, computes hourly mean Sv (dB), aligns with a depth×time error map, and renders synchronized line/heatmap plots.

Label the importance of each concept explicitly as helpful/necessary.

ConceptsImportanceNotes
Xarray + Zarr basicsNecessaryOpening Zarr stores, selecting by coords/dims, .compute() semantics
s3fs & public S3 accessNecessaryAnonymous reads from AWS S3 (anon=True)
Pandas time seriesNecessaryDatetimeIndex, sorting, filtering, timezone-naive vs. aware
NumPy fundamentalsNecessaryArray slicing, stats, type conversion
Acoustic backscatter (Sv) & dB averagingNecessaryConvert dB→linear, mean, then linear→dB, Understanding results
ERDDAP tabledap & info endpointsHelpfulReading CSV responses; unit metadata lookup
Plotly fundamentalsHelpfulSubplots, heatmaps, interactive HTML export
Understanding of NetCDF/CFHelpfulVariable metadata and geospatial conventions
Dask awarenessHelpfulLazy arrays; when/why to call .compute()
Geographic coordinatesHelpful0–360 vs. −180–180 longitude handling
HTTP/IO with requestsHelpfulDownloading .npy assets for local use
  • Time to learn: ~75 minutes

  • System requirements:

    • Python 3.9+ with Jupyter Notebook/Lab

    • Required packages: xarray, s3fs, numpy, pandas, plotly, requests, netCDF4 (optional but helpful: dask)

Note: Run the cell below only in a local environment to install the required packages. If you’re using Binder, skip this step.

Running: /usr/bin/conda install -y -p /home/runner/micromamba/envs/osdf-cookbook -c conda-forge jupyterlab mystmd jupyterlab-myst aiohttp bash_kernel intake intake-esm=2025.2.3 pelicanplatform panel bokeh xmltodict cartopy colorcet cf-units boto3 basemap pelicanfs=1.2.1 matplotlib metpy pandas xarray geopandas pystac-client rasterio dask dask-jobqueue openpyxl hvplot plotly zarr=2.18.1 s3fs seaborn tqdm h5netcdf igwn-auth-utils=1.4.0
CI detected...
By accessing https://repo.anaconda.com/pkgs/main via CI for this repository you 
acknowledge and agree to the Terms of Service:
ANACONDA TERMS OF SERVICE
Effective Date: July 15, 2025

See https://anaconda.com/legal/terms/terms-of-service
By accessing https://repo.anaconda.com/pkgs/r via CI for this repository you 
acknowledge and agree to the Terms of Service:
ANACONDA TERMS OF SERVICE
Effective Date: July 15, 2025

See https://anaconda.com/legal/terms/terms-of-service
2 channel Terms of Service accepted
Retrieving notices: ...working... done
Channels:
 - conda-forge
 - defaults
Platform: linux-64
Collecting package metadata (repodata.json): ...working... 
done
Solving environment: ...working... 
done
WARNING conda.conda_pypi.main:notify_externally_managed_future(156): 
  Did you know? You can install many PyPI packages with conda
  using the conda-pypi beta. Get started:
    https://docs.conda.io/projects/conda/en/stable/new-features.html


# All requested packages already installed.


Channel "defaults" has the following notices:
  [info] -- Thu Aug  6 00:00:00 2026
  main-x (Anaconda's new authenticated channel) is now generally available, with thousands of additional packages from our secure supply chain. Get started at: https://anaconda.com/docs/getting-started/main-x?utm_source=channel_notices

Running: /home/runner/micromamba/envs/osdf-cookbook/bin/python -m pip install import-ipynb OpenVisus openvisuspy pvlib rioxarray stackstac
Requirement already satisfied: import-ipynb in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (0.2.1)
Requirement already satisfied: OpenVisus in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (2.2.149)
Requirement already satisfied: openvisuspy in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (1.0.71)
Requirement already satisfied: pvlib in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (0.16.1)
Requirement already satisfied: rioxarray in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (0.23.0)
Requirement already satisfied: stackstac in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (0.5.1)
Requirement already satisfied: IPython in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from import-ipynb) (9.17.1)
Requirement already satisfied: nbformat in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from import-ipynb) (5.11.1)
Requirement already satisfied: numpy>=1.23.2 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pvlib) (2.3.5)
Requirement already satisfied: pandas>=1.5.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pvlib) (2.2.3)
Requirement already satisfied: pytz in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pvlib) (2024.1)
Requirement already satisfied: requests in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pvlib) (2.34.2)
Requirement already satisfied: scipy>=1.9.2 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pvlib) (1.18.1)
Requirement already satisfied: h5py in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pvlib) (3.16.0)
Requirement already satisfied: tzdata in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pvlib) (2026.4)
Requirement already satisfied: packaging in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rioxarray) (25.0)
Requirement already satisfied: rasterio>=1.4.3 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rioxarray) (1.5.1)
Requirement already satisfied: xarray>=2026.2 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rioxarray) (2026.7.0)
Requirement already satisfied: pyproj>=3.3 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rioxarray) (3.7.2)
Requirement already satisfied: dask>=2022.1.1 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from dask[array]>=2022.1.1->stackstac) (2026.8.0)
Requirement already satisfied: python-dateutil>=2.8.2 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pandas>=1.5.0->pvlib) (2.9.0.post0)
Requirement already satisfied: certifi in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pyproj>=3.3->rioxarray) (2026.7.22)
Requirement already satisfied: affine in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rasterio>=1.4.3->rioxarray) (3.0.1)
Requirement already satisfied: attrs in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rasterio>=1.4.3->rioxarray) (26.1.0)
Requirement already satisfied: click!=8.2.*,>=4.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rasterio>=1.4.3->rioxarray) (8.5.0)
Requirement already satisfied: pyparsing>=3.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from rasterio>=1.4.3->rioxarray) (3.3.3)
Requirement already satisfied: cloudpickle>=3.0.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from dask>=2022.1.1->dask[array]>=2022.1.1->stackstac) (3.1.2)
Requirement already satisfied: fsspec>=2021.09.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from dask>=2022.1.1->dask[array]>=2022.1.1->stackstac) (2026.9.0)
Requirement already satisfied: partd>=1.4.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from dask>=2022.1.1->dask[array]>=2022.1.1->stackstac) (1.4.2)
Requirement already satisfied: pyyaml>=5.4.1 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from dask>=2022.1.1->dask[array]>=2022.1.1->stackstac) (6.0.3)
Requirement already satisfied: toolz>=0.12.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from dask>=2022.1.1->dask[array]>=2022.1.1->stackstac) (1.1.0)
Requirement already satisfied: locket in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from partd>=1.4.0->dask>=2022.1.1->dask[array]>=2022.1.1->stackstac) (1.0.0)
Requirement already satisfied: six>=1.5 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from python-dateutil>=2.8.2->pandas>=1.5.0->pvlib) (1.17.0)
Requirement already satisfied: ipython-pygments-lexers>=1.0.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (1.1.1)
Requirement already satisfied: jedi>=0.18.2 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (0.20.0)
Requirement already satisfied: matplotlib-inline>=0.1.6 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (0.2.2)
Requirement already satisfied: pexpect>4.6 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (4.9.0)
Requirement already satisfied: prompt_toolkit<3.1.0,>=3.0.41 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (3.0.53)
Requirement already satisfied: psutil>=7 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (7.2.2)
Requirement already satisfied: pygments>=2.14.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (2.21.0)
Requirement already satisfied: stack_data>=0.6.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (0.6.3)
Requirement already satisfied: traitlets>=5.13.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from IPython->import-ipynb) (5.16.1)
Requirement already satisfied: wcwidth>=0.1.4 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from prompt_toolkit<3.1.0,>=3.0.41->IPython->import-ipynb) (0.9.1)
Requirement already satisfied: parso<0.9.0,>=0.8.6 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from jedi>=0.18.2->IPython->import-ipynb) (0.8.7)
Requirement already satisfied: ptyprocess>=0.5 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from pexpect>4.6->IPython->import-ipynb) (0.7.0)
Requirement already satisfied: executing>=1.2.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from stack_data>=0.6.0->IPython->import-ipynb) (2.2.1)
Requirement already satisfied: asttokens>=2.1.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from stack_data>=0.6.0->IPython->import-ipynb) (3.0.2)
Requirement already satisfied: pure_eval in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from stack_data>=0.6.0->IPython->import-ipynb) (0.2.4)
Requirement already satisfied: fastjsonschema>=2.15 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from nbformat->import-ipynb) (2.22.2)
Requirement already satisfied: jsonschema>=2.6 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from nbformat->import-ipynb) (4.26.0)
Requirement already satisfied: jupyter-core!=5.0.*,>=4.12 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from nbformat->import-ipynb) (5.9.1)
Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from jsonschema>=2.6->nbformat->import-ipynb) (2025.9.1)
Requirement already satisfied: referencing>=0.28.4 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from jsonschema>=2.6->nbformat->import-ipynb) (0.37.0)
Requirement already satisfied: rpds-py>=0.25.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from jsonschema>=2.6->nbformat->import-ipynb) (2026.6.3)
Requirement already satisfied: platformdirs>=2.5 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from jupyter-core!=5.0.*,>=4.12->nbformat->import-ipynb) (4.12.1)
Requirement already satisfied: typing-extensions>=4.4.0 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from referencing>=0.28.4->jsonschema>=2.6->nbformat->import-ipynb) (4.16.0)
Requirement already satisfied: charset_normalizer<4,>=2 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from requests->pvlib) (3.5.1)
Requirement already satisfied: idna<4,>=2.5 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from requests->pvlib) (3.20)
Requirement already satisfied: urllib3<3,>=1.26 in /home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages (from requests->pvlib) (2.8.0)

1) Imports

Core libraries used throughout the notebook.

Key roles:

xarray/s3fs for reading NOAA Zarr data from S3
numpy/pandas for arrays & tables
plotly for interactive plotting
requests/io/os for file I/O and downloads
datetime for time calculations

2) Initializing the datasets

Builds the S3 path to the HB1906 EK60 Zarr dataset and opens it anonymously. Subsets by time window and depth range, selects the 38 kHz channel, and masks samples below the estimated bottom. .compute() materializes the selection; hm_timestamps will be reused for time alignment later. All datasets are accessed using the OSDF infrastructure

3) Accessing buoy data

Defines a buoy location on Georges Bank (longitude converted to 0–360).

  1. Optional: Loads three daily OISST files and samples SST at the nearest grid point (day before, day of, day after).

  2. ERDDAP buoy environmental data.

Sets ERDDAP dataset parameters and enforces a max_days cap by adjusting end_date_time if needed. Reads station metadata to extract lon/lat and wind-speed units; prepares a conversion to knots. Pulls a table of time, wind_speed, SST, significant wave height, converts wind speed to knots, indexes by time. Filters to the requested window and keeps the first nine rows (intentional truncation for later alignment).

end_date_time updated to 2019-11-10 14:00:00

4) Calculate the temperature anomaly, sun elevation in degree and azimuth

Extracts World Ocean Atlas 2023 temperature data for a specific location and month and calculates temperature anomaly (optional), sun elevation in degree and azimuth (optional).

/home/runner/micromamba/envs/osdf-cookbook/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html
  from .autonotebook import tqdm as notebook_tqdm
Loading...

5) Downloading external error map for the specific location.

Currently the error map comes from a fixed file; our plan is to switch to a dynamic AWS download that accepts location parameters.


6) Helper: mean Sv in dB

Computes the mean of Sv correctly by converting dB → linear, averaging, then linear → dB. Accepts array-like input (NumPy/xarray/dask); returns a scalar in dB.

7) Group cruise data into hourly chunks

Adds an hourly label and groups the cruise data by hour. Produces a list of per-hour xarray.Dataset chunks for downstream aggregation.

8) Compute hourly mean Sv and attach to env_df

Iterates over hourly chunks, computes mean Sv per hour using calculate_sv_mean. Converts dask→NumPy→Python float and appends to a list. Assigns the resulting hourly series to env_df[“sv_hourly”]. Assumes the number/order of hours matches rows retained in env_df.

9) Build (depth × time) error-map DataFrame and align timestamps

Extracts one channel from sonar_clusters and pairs it with cruise depths and timestamps to form a DataFrame. Uses min(...) to guard against size mismatches in depth/time dimensions. Aligns only the first and last timestamps in env_df to the heatmap’s time range (keeps interior indices unchanged, sets UTC).

10) Data Visualization: Synchronized Lines + Heatmap

Plots synchronized data: top = time series from line_df; bottom = depth×time heatmap from heatmap_df. Expects line_df to have a DatetimeIndex (timezone-naive or converted). Depth axis is reversed (surface at top). Saves an interactive HTML file to the parent directory (correlations.html) and shows the figure if show=True.

Because rendering the plot is computationally intensive and involves downloading approximately 1 GB of data, we present a static image of the result instead.

<IPython.core.display.Image object>