Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions amocatlas/data_sources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from .zheng2024 import read_zheng2024
from .wh41n import read_41n
from .noac47n import read_47n
from .nac import read_nac

__all__ = [
"read_rapid",
Expand All @@ -43,4 +44,5 @@
"read_zheng2024",
"read_41n",
"read_47n",
"read_nac",
]
188 changes: 188 additions & 0 deletions amocatlas/data_sources/nac.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
"""North Atlantic Current (NAC) data reader for AMOCatlas.

This module provides functions to read and process the North Atlantic current time series from satellite and float observations.
The NAC is a key component of the Atlantic Meridional Overturning Circulation, transporting warm, saline water from the tropics to the high northern latitudes.

The dataset includes NAC transport estimates from satellite and float observations and an NAC estimation from satellite altimetry alone.

Key functions:
- read_nac(): Main data loading interface for North Atlantic Current data

Data source: Satellite and float observations
Location: Between tip of Greenland and northern Spain
"""

from pathlib import Path
from typing import Union

import xarray as xr

# Import the modules used
from amocatlas import logger, utilities
from amocatlas.logger import log_error, log_info, log_warning
from amocatlas.utilities import apply_defaults
from amocatlas.reader_utils import ReaderUtils

log = logger.log # Use the global logger

# Datasource identifier for automatic standardization
DATASOURCE_ID = "nac"

# Default list of NAC data files
NAC_DEFAULT_FILES = ["_2_1.nc"]
NAC_TRANSPORT_FILES = ["_2_1.nc"]
NAC_DEFAULT_SOURCE = "https://library.ucsd.edu/dc/object/bb6635909m"

NAC_METADATA = {
"project": "North Atlantic Current Time Series from Satellite and Float Observations (1993-2025)",
"weblink": "https://library.ucsd.edu/dc/object/bb6635909m",
"comment": "Dataset accessed and processed via http://github.com/AMOCcommunity/amocatlas",
}

NAC_FILE_METADATA = {
"_2_1.nc": {
"data_product": "6-monthly estimates of NAC transport from satellite altimetry and float observations",
},
}


@apply_defaults(NAC_DEFAULT_SOURCE, NAC_DEFAULT_FILES)
def read_nac(
source: Union[str, Path, None],
file_list: Union[str, list[str]],
transport_only: bool = True,
data_dir: Union[str, Path, None] = None,
redownload: bool = False,
track_added_attrs: bool = False,
) -> list[xr.Dataset]:
"""Load the NAC (North Atlantic Current) transport datasets from a URL or local file path into xarray Datasets.

Parameters
----------
source : str, optional
Local path to the data directory (remote source is handled per-file).

file_list : str or list of str, optional
Filename or list of filenames to process.
Defaults to NAC_DEFAULT_FILES.

transport_only : bool, optional
If True, restrict to transport files only.

data_dir : str, Path or None, optional
Optional local data directory.

redownload : bool, optional
If True, force redownload of the data.
track_added_attrs : bool, optional
If True, track which attributes were added during metadata enrichment.

Returns
-------
list of xr.Dataset
List of loaded xarray datasets with basic inline and file-specific metadata.
And if track_added_attrs is True, also returns a list of dictionaries with the attributes that were added to each dataset during metadata enrichment.

Raises
------
ValueError
If no source is provided for a file and no default URL mapping is found.

FileNotFoundError
If the file cannot be downloaded or does not exist locally.

"""
log.info("Starting to read NAC dataset")

# Load YAML metadata with fallback
global_metadata, yaml_file_metadata = ReaderUtils.load_array_metadata_with_fallback(
DATASOURCE_ID, NAC_METADATA
)

# Ensure file_list has a default
if file_list is None:
file_list = NAC_DEFAULT_FILES
if transport_only:
file_list = NAC_TRANSPORT_FILES
if isinstance(file_list, str):
file_list = [file_list]
# Determine the local storage path
local_data_dir = Path(data_dir) if data_dir else utilities.get_default_data_dir()
local_data_dir.mkdir(parents=True, exist_ok=True)

# Print information about files being loaded
ReaderUtils.print_loading_info(file_list, DATASOURCE_ID, NAC_FILE_METADATA)

datasets = []

added_attrs_per_dataset = [] if track_added_attrs else None
for file in file_list:
if not (file.lower().endswith(".nc")):
log_warning("Skipping unsupported file type : %s", file)
continue

download_url = (
f"{source.rstrip('/')}/{file}" if utilities.is_valid_url(source) else None
)

file_path = utilities.resolve_file_path(
file_name=file,
source=source,
download_url=download_url,
local_data_dir=local_data_dir,
redownload=redownload,
)

# Open dataset

if file.lower().endswith(".nc"):
# Use ReaderUtils for consistent dataset loading

ds = ReaderUtils.safe_load_dataset(file_path)
# Attach metadata
# Attach metadata with optional tracking

if track_added_attrs:

ds, attr_changes = ReaderUtils.attach_metadata_with_tracking(
ds,
file,
file_path,
global_metadata,
yaml_file_metadata,
NAC_FILE_METADATA,
DATASOURCE_ID,
track_added_attrs=True,
)

added_attrs_per_dataset.append(attr_changes)

else:

ds = ReaderUtils.attach_metadata_with_tracking(
ds,
file,
file_path,
global_metadata,
yaml_file_metadata,
NAC_FILE_METADATA,
DATASOURCE_ID,
track_added_attrs=False,
)
else:
raise ValueError(
f"Unsupported file type for {file}. Only .nc files are supported."
)

datasets.append(ds)

if not datasets:
log_error("No valid NAC files in %s", file_list)
raise FileNotFoundError(f"No valid data files found in {file_list}")

log_info("Successfully loaded %d NAC dataset(s)", len(datasets))

if track_added_attrs:
return datasets, added_attrs_per_dataset
else:
return datasets
Comment thread
isaschmitz marked this conversation as resolved.
39 changes: 39 additions & 0 deletions amocatlas/metadata/nac.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
metadata:
program: "NAC"
description: "North Atlantic Current Time Series from Satellite and Float Observations (1993-2025)"
project: "Lankhorst, Matthias (2025). North Atlantic Current Time Series from Satellite and Float Observations (1993-2025). "
weblink: https://library.ucsd.edu/dc/object/bb6635909m
comment: Dataset accessed and processed via http://github.com/AMOCcommunity/amocatlas
acknowledgment: >
Earlier versions of this dataset were created with support from the European Commission through awards EVK2-CT-2000-00087 and EVR1-CT-2001-40014 (projects 'GYROSCOPE' and 'ANIMATE'). Updated versions were partially supported through award NA15OAR4320071 from U.S. NOAA OOMD.
citation: >
Lankhorst, Matthias (2025). North Atlantic Current Time Series from Satellite and Float Observations (1993-2025). In North Atlantic Current Time Series from Satellite and Float Observations. UC San Diego Library Digital Collections. https://doi.org/10.6075/J0D79CCG
license:
featureType: timeSeries
time_coverage_start: '1993-01-01'
time_coverage_end: '2025-07-02'

files:
_2_1.nc:
source_url: https://library.ucsd.edu/dc/object/bb6635909m/
data_product: "6-monthly mean NAC transport time series (1993-2025) estimated from satellite and float observations"
variable_mapping:
"NAC": TRANS_NAC
"NAC_UNCERTAINTY": TRANS_NAC_UNCERTAINTY
"NAC_PROXY": TRANS_NAC_PROXY
original_variable_metadata:
NAC:
long_name: "NAC Transport"
description: "North Atlantic Current transport time series from satellite and float observations"
units: Sverdrup
standard_name: ocean_volume_transport_across_line
NAC_UNCERTAINTY:
long_name: "Uncertainty of values in NAC variable"
description: "Uncertainty of North Atlantic Current transport time series"
units: Sverdrup
standard_name: ocean_volume_transport_across_line_uncertainty
NAC_PROXY:
long_name: "NAC Transport Proxy"
description: "Proxy for North Atlantic Current transport time series from satellite altimetry"
units: Sverdrup
standard_name: ocean_volume_transport_across_line
8 changes: 4 additions & 4 deletions amocatlas/plotters.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,14 +585,14 @@ def plot_amoc_timeseries(

# Raw plot
if plot_raw:
# Use black if no monthly resampling, grey otherwise
raw_color = "black" if not resample_monthly else "grey"
# Use grey if monthly resampling is enabled, otherwise the specified color
raw_color = "grey" if resample_monthly else color
ax.plot(
da[time_key],
da,
color=raw_color,
alpha=0.7 if not resample_monthly else 0.5,
linewidth=0.5,
alpha=0.85 if not resample_monthly else 0.5,
linewidth=1 if not resample_monthly else 0.5,
label=f"{label} (raw)",
)

Expand Down
7 changes: 7 additions & 0 deletions amocatlas/read.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
read_47n,
read_fbc,
read_arcticgateway,
read_nac,
)

# Import file constants for list_files() functionality
Expand All @@ -66,6 +67,7 @@
from .data_sources.noac47n import NOAC47N_DEFAULT_FILES
from .data_sources.fbc import FBC_DEFAULT_FILES
from .data_sources.arcticgateway import ARCTIC_DEFAULT_FILES
from .data_sources.nac import NAC_DEFAULT_FILES

# Import standardization functions
from . import standardise
Expand All @@ -85,6 +87,7 @@
"fbc",
"calafat2025",
"zheng2024",
"nac",
}


Expand Down Expand Up @@ -428,6 +431,9 @@ def list_files() -> List[str]:
zheng2024 = _create_array_function(
read_zheng2024, "Zheng et al. 2024", available_files=ZHENG2024_DEFAULT_FILES
)
nac = _create_array_function(
read_nac, "North Atlantic Current", available_files=NAC_DEFAULT_FILES
)


# Define __all__ to control what's exported
Expand All @@ -445,4 +451,5 @@ def list_files() -> List[str]:
"fbc",
"calafat2025",
"zheng2024",
"nac"
]
3 changes: 3 additions & 0 deletions amocatlas/readers.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
read_47n,
read_fbc,
read_arcticgateway,
read_nac,
)

log = logger.log
Expand Down Expand Up @@ -83,6 +84,7 @@ def _get_reader(array_name: str) -> Callable[..., List[xr.Dataset]]:
"47n": read_47n,
"fbc": read_fbc,
"arcticgateway": read_arcticgateway,
"nac": read_nac,
}
try:
return readers[array_name.lower()]
Expand Down Expand Up @@ -175,6 +177,7 @@ def load_dataset(
- '47n' : 47N array
- 'fbc' : Faroe Bank Channel overflow array
- 'arcticgateway' : ARCTIC Gateway array
- 'nac' : North Atlantic Current array
source : str, optional
URL or local path to the data source.
If None, the reader-specific default source will be used.
Expand Down
12 changes: 12 additions & 0 deletions amocatlas/standardise.py
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,18 @@ def standardise_arcticgateway(ds: xr.Dataset, file_name: str) -> xr.Dataset:
return standardise_array(ds, file_name)


def standardise_nac(ds: xr.Dataset, file_name: str) -> xr.Dataset:
"""Standardise NAC array dataset to consistent format."""
warnings.warn(
"standardise_nac() is deprecated and will be removed in a future version. "
"Use standardise_data() instead.",
DeprecationWarning,
stacklevel=2,
)

return standardise_array(ds, file_name)


def standardise_data(ds: xr.Dataset, file_name: str) -> xr.Dataset:
"""Standardise a dataset using YAML-based metadata.
Comment thread
isaschmitz marked this conversation as resolved.

Expand Down
4 changes: 4 additions & 0 deletions amocatlas/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import pandas as pd
import requests
import xarray as xr
import numpy as np

from amocatlas import logger
from amocatlas.logger import log_debug
Expand Down Expand Up @@ -879,6 +880,9 @@ def mask_invalid_values(ds: xr.Dataset) -> xr.Dataset:
# Use xarray operations to preserve lazy evaluation
invalid_mask = xr.zeros_like(var, dtype=bool)

if np.issubdtype(var.dtype, np.datetime64):
continue

if valid_min is not None:
invalid_mask = invalid_mask | (var < valid_min)

Expand Down
Binary file added data/_2_1.nc
Binary file not shown.
Loading
Loading