Skip to main content

amphi-ncdata

amphi-ncdata is a Python client library for loading and sampling Amphi NetCDF datasets.

It exposes these main entry points:

  • AmphiNcData: the easiest high-level API for clients using Amphi-style dataset folders.
  • MultiAmphiNcData: an AmphiNcData-style env spanning several bounding boxes, routing each query to the owning box in O(1).
  • NcData: a lower-level API for loading arbitrary NetCDF files or basepaths.

This README is for clients using an already built wheel. Repository maintainers should use README_DEV.md.

All timestamps in the public API are Unix timestamps in seconds.

Install From The Wheel

Ask for the wheel that matches:

  • your operating system
  • your Python version
  • your machine architecture

Install it with:

python3 -m pip install /path/to/amphi_ncdata-0.1.0-<platform>.whl

Quick import check:

python3 -c "import amphi_ncdata; print(amphi_ncdata.__version__)"

If installation succeeds but import fails with a missing shared-library error, ask us for a wheel built for your environment or install the required NetCDF runtime libraries for your platform.

Quick Start

The fastest way to use the library is with AmphiNcData.

Example script:

from amphi_ncdata import AmphiNcData

env = AmphiNcData(
    {
        "currentsBasepaths": ["/data/data_api/FORECAST-CURRENT/"],
        "windBasepaths": ["/data/data_api/FORECAST/wind/"],
        "waveBasepaths": ["/data/data_api/FORECAST/wave/"],
        "climWindBasepaths": ["/data/data_api/HINDCAST-3Y/"],
        "climWaveBasepaths": ["/data/data_api/HINDCAST-3Y-WAVE/"],
    },
    start=1781478000,
    end=1781650800,
    south=35.0,
    west=-73.0,
    north=43.0,
    east=-30.0,
)

lat, lon = 40.0, -50.0
timestamp = 1781524800

currents = env.currents()
wind = env.wind()
waves = env.waves()

currents.set_interpolation_method("linear")
wind.set_interpolation_method("linear")
waves.set_interpolation_method("linear")

u_current, v_current = currents.at(lat, lon, timestamp)
u_wind, v_wind = wind.at(lat, lon, timestamp)
wave_height, wave_period, wave_direction = waves.at(lat, lon, timestamp)

print("Currents:", u_current, v_current)
print("Wind:", u_wind, v_wind)
print("Waves:", wave_height, wave_period, wave_direction)

A ready-to-copy version also lives in examples/client_quickstart.py.

Main Concepts

  • AmphiNcData is the convenience layer for Amphi folder layouts, masks, and tides.
  • NcData is the generic layer when you want to choose the files or variables yourself.
  • load() registers which variables you want available.
  • set_interpolation_method(method, skip_nan=...) sets the dataset interpolation mode once. skip_nan=True lets "linear" interpolate from the corners that hold data instead of returning NaN whenever one of the four is a coastal no-data cell.
  • set_no_data_value(value, when=...) gives the product's no-data mask a value instead of NaN, per variable, either when="before_interpolation" or when="after_interpolation".
  • MultiAmphiNcData(..., inclusive=..., snap_to_grid=..., cell_size=...) tune how boxes claim the routing grid; all three are optional and every default matches earlier behaviour.
  • set_out_of_window_behaviour(behaviour, value, dim=...) sets what a query outside the loaded window returns, per dimension (dim="time" / "space" / "both"): "nearest", "nan", "value", or "fallback" (another NcData). Defaults: time→nearest, space→nan.
  • sample() returns one variable.
  • at() returns all loaded variables for the dataset.
  • at() / sample() are fast for sequential, point-by-point access (e.g. routing); sample_batch() / at_batch() are best when you already have many independent points (roughly a few dozen or more) to sample at once. Pass out= (a buffer from empty_batch()) to sample in place with no per-call allocation.
  • env.wind() / env.waves() auto-fall-back to climatology past the forecast horizon (when climatology basepaths are set); env.climWind() / env.climWave() are the underlying climatology datasets.

Using AmphiNcData

AmphiNcData is the recommended API for most client code.

Using an input.json-style config

from amphi_ncdata import AmphiNcData
import json

with open("input.json", "r", encoding="utf-8") as f:
    cfg = json.load(f)

env = AmphiNcData(
    cfg,
    start=1781478000,
    end=1781650800,
    south=35.0,
    west=-73.0,
    north=43.0,
    east=-30.0,
)

Using a flat config

env = AmphiNcData(
    {
        "currentsBasepaths": ["/data/data_api/FORECAST-CURRENT/"],
        "tidesBasepaths": ["/data/data_api/FORECAST-TIDE/"],
        "windBasepaths": ["/data/data_api/FORECAST/wind/"],
        "waveBasepaths": ["/data/data_api/FORECAST/wave/"],
        "climWindBasepaths": ["/data/data_api/HINDCAST-3Y/"],
        "climWaveBasepaths": ["/data/data_api/HINDCAST-3Y-WAVE/"],
        "bathymetryPath": "/data/data_save/ETOPO/bathy.nc",
        "tidesMaskPath": "/data/data_api/FORECAST-TIDE/masks_tide.nc",
        "nogoPath": "/data/data_user/nogo.nc",
        "coastalZonePath": "/data/data_save/coastal_zone_mask.nc",
    },
    start=1781478000,
    end=1781650800,
    south=35.0,
    west=-73.0,
    north=43.0,
    east=-30.0,
)

High-level helpers

currents = env.currents()
wind = env.wind()
waves = env.waves()
tidal = env.tidal_currents()
bathy = env.bathymetry()
nogo = env.nogo()
coastal = env.coastal_zone()
tides_mask = env.tides_mask()

Return shapes:

  • env.currents().at(...) -> (ucos, vcos)
  • env.tidal_currents().at(...) -> (utotal, vtotal)
  • env.wind().at(...) -> (u10, v10)
  • env.waves().at(...) -> (swh, mwp, mwd)
  • env.bathymetry().at(...) -> bathymetry
  • env.nogo().at(...) -> mask
  • env.coastal_zone().at(...) -> mask
  • env.tides_mask().at(...) -> mask_TIDE

Tidal currents: the fused tidal_currents()

Tides only matter near coasts (the global tide mask is ~9% active), so env.tidal_currents() does not load the whole bounding box. With a tidesMaskPath configured it loads eager 1-degree masked tiles: every 1-degree tile that the mask marks active is pulled into RAM up front, in the raw NetCDF dtype, so the routing hot path never touches NetCDF I/O. Open-ocean and land tiles allocate nothing.

tidal_currents() is fused: at() returns the hourly tidal current where the mask is active (coastal) and the open-ocean current where it is not — so a single call gives the right water velocity everywhere, no manual branch:

from datetime import datetime, timezone
from amphi_ncdata import AmphiNcData

start = int(datetime(2026, 6, 23, tzinfo=timezone.utc).timestamp())
env = AmphiNcData(
    {
        "tidesBasepaths":    ["/data/data_api/FORECAST-TIDE/"],
        # The mask is what turns tides into eager 1-degree masked tiles:
        "tidesMaskPath":     "/data/data_api/FORECAST-TIDE/masks_tide.nc",
        # "tidesTileSizeDegrees": 1.0,   # optional; 1.0 is the default
    },
    start=start, end=start + 24 * 3600,
    south=48.0, west=-6.0, north=52.5, east=4.5,    # English Channel
)

tides = env.tidal_currents()        # eager 1° masked tiles + a daily open-ocean step
u, v = tides.at(lat, lon, timestamp)   # tide near the coast, current offshore — one call

How the open ocean is served. Where the tide product is not tidal (mask 0), its values are constant over the day and equal the surface currents (verified: p99 = 0, mean diff 3.7e-5 m/s over thousands of open-ocean points). So tidal_currents() loads one daily tide step over the full bbox as the open-ocean field — self-contained (no separate currents product needed), same variable names, and roughly half the RAM of loading the multi-step currents product. Coastal cells are overridden by the hourly tide tiles.

You normally never call the gate yourself, but it is exposed for inspection and for fused=False:

tides.mask(lat, lon)                 # compiled gate (~0.2 us): is this point tidal?
tides.mask_batch(lats, lons)         # vectorised

mask() is the nearest high-res mask_TIDE cell (active = non-zero); it is spatial, so timestamp is accepted for symmetry but ignored. A masked-in cell can still be land / fill (NaN) — mask() selects the data source, not its presence.

Knobs: tidesTileSizeDegrees (default 1.0) sets the tile size; TidalCurrents(..., eager=False) keeps tiles lazy with an LRU cache (smaller resident footprint, per-call I/O); TidalCurrents(..., fused=False) makes at() tide-only again (NaN in the open ocean) if you want to gate manually.

What if you omit the tide paths?

configuration env.tidal_currents() behaviour
tidesBasepaths and tidesMaskPath set Eager 1° masked tiles + fused open ocean (the recommended setup). at() is tide-where-coastal, current-where-not; mask() reflects the high-res tide mask.
tidesBasepaths set, tidesMaskPath omitted Falls back to the full-bbox tidal view (lazy, no tiling, no fusion). at() samples tides everywhere in the box, and mask() returns True for any in-box point (no mask to gate on). Memory is the full bbox × all tide steps — fine for a small box, large for a wide one.
tidesBasepaths omitted env.tidal_currents() raises AmphiDiscoveryError ("No valid NetCDF files were found …"). Only call it when tides are configured; currents, wind, and waves are independent and still work — env.currents() stays the currents-only, memory-light path.

Out-of-window behaviour (per dimension, with climatology fallback)

A query can fall outside the loaded window in time (past/before the forecast) or in space (outside the bounding box). Each is handled independently:

wind.set_out_of_window_behaviour(behaviour, value=0.0, dim="both")
  • dim: "time", "space", or "both" (default).
  • behaviour:
    • "nearest" — clamp to the nearest timestep / edge cell.
    • "nan" — return NaN.
    • "value" — return the constant value (a float).
    • "fallback" (alias "data") — sample value instead, which must be another NcData that covers the query (e.g. a climatology). The fallback dataset carries its own out-of-window behaviour.
  • Defaults: time → nearest, space → nan.

Precedence when out of window: a fallback dimension delegates the whole sample to its dataset (time is checked before space); otherwise a nan/value on space applies before time; nearest simply clamps that dimension. This is independent of NaN coming from the data itself (land / fill), which is always NaN. (set_out_of_window_behaviour("nan") / ("value", -999) still set both dimensions, for backward compatibility.)

Climatology fallback (automatic for wind / waves)

env.wind() and env.waves() automatically fall back to climatology past the forecast horizon when climatology basepaths are configured — equivalent to:

wind.set_out_of_window_behaviour("fallback", env.climWind(), dim="time")

So a long voyage just keeps sampling, with no manual gap handling:

wind = env.wind()                      # forecast + climatology time-fallback
u, v = wind.at(40.0, -50.0, ts)        # forecast in-window, climatology past the horizon

The climatology (env.climWind() -> (u10, v10), env.climWave() -> (swh, mwp, mwd)) is still its own dataset and is configured as the safety net: nearest in both time and space and linear interpolation, so it always returns a value. Pass no climatology basepaths, or call wind.set_out_of_window_behaviour("nan", dim="time"), to opt out (e.g. to detect the gap yourself).

This holds for a window lying wholly past the horizon too, not just one that straddles it. With no forecast file for the window at all the dataset is empty rather than absent, and an empty dataset is out of window everywhere — so every query goes to climatology:

# Window 15 days out; wind forecast only reaches ~today+14, so nothing covers it.
env = AmphiNcData(config, start=far_future, end=far_future + 86400, **bbox)
wind = env.wind()
wind.is_empty            # True  -- no file backs it
wind.warnings            # WARN_NO_FILES
wind.at(lat, lon, ts)    # the climatology value, not an exception
wind.time_range          # None -- it holds no timestep; guard before indexing

Missing data is reported, not raised: warnings

A forecast archive routinely has gaps, so ordinary discovery problems do not raise. They set a bitmask on the dataset and the accessor still returns something usable:

code meaning
WARN_NONE (0) nothing was wrong
WARN_NO_FILES (1) no file at all for the window; the dataset is empty, so queries return the out-of-window value or a wired fallback
WARN_PARTIAL_COVERAGE (2) some of the requested days resolved, some did not
WARN_LAST_AVAILABLE (4) nothing covered the window, so the newest file on disk was served — the values are stale
WARN_CLIMATOLOGY_MISSING (8) a climatology basepath was configured but its MM.nc is absent, so there is no safety net

It is a bitmask, not a sequential code, because these co-occur — a window can be both partially covered and served from a stale run:

from amphi_ncdata import WARN_LAST_AVAILABLE, WARN_NO_FILES, warning_names

currents = env.currents()
if currents.warnings & WARN_LAST_AVAILABLE:
    print("stale:", currents.warning_messages)

env.warnings                # OR across every dataset built so far; 0 == clean
warning_names(env.warnings) # ('no_files', 'last_available')
env.warning_messages        # ('wind: no NetCDF files were found for 2026-08-22..2026-08-23', ...)

MultiAmphiNcData aggregates the same way, per box: routed.warnings ORs its members and routed.warning_messages prefixes each line with box <i>.

Turning them back into exceptions: on_warning

AmphiNcData(config, ..., on_warning="raise")                      # every code raises
AmphiNcData(config, ..., on_warning={"no_files": "raise"})         # just this one
AmphiNcData(config, ..., on_warning={"default": "raise",
                                     "partial_coverage": "silent"})

Genuine caller errors are never downgraded and always raise, whatever on_warning says: an unknown variable name, a bounding box that does not overlap the grid, an unconfigured mask or climatology path. The distinction is whether the data is missing (a fact about the archive) or the request is wrong.

load_defaults()

env.load_defaults(
    include_tides=True,
    include_bathymetry=True,
    include_nogo=True,
    include_coastal_zone=True,
)

This preloads:

  • currents
  • wind
  • waves
  • optionally tidal currents and tides mask (tides eager-load their active 1° tiles up front — fast for a route corridor, heavier for a continental box; see the gate section)
  • optionally bathymetry
  • optionally no-go mask
  • optionally coastal zone mask

Overriding default variable names

If your files use different names:

custom_currents = env.currents(u_var="u_current", v_var="v_current")
custom_wind = env.wind(u_var="u_wind", v_var="v_wind")
custom_waves = env.waves(height_var="hs", period_var="tp", direction_var="dir")

Multiple bounding boxes: MultiAmphiNcData

Use MultiAmphiNcData when one env should cover several bounding boxes / time windows at once — e.g. tiling a large region, or layering a smaller box on top of a bigger one. All boxes share the same config; each carries its own start, end, south, west, north, east. Every accessor mirrors AmphiNcData (currents(), wind(), waves(), tidal_currents(), bathymetry(), …) but returns a routed dataset whose at/at_batch/sample/sample_batch dispatch each point to the box that owns it.

from amphi_ncdata import MultiAmphiNcData   # or AmphiNcData.from_bounding_boxes(...)

env = MultiAmphiNcData(
    {"currentsBasepaths": ["/data/data_api/FORECAST-CURRENT/"]},   # shared by all boxes
    boxes=[
        dict(start=1781478000, end=1781650800, south=35.0, west=-73.0, north=43.0, east=-30.0),
        dict(start=1781478000, end=1781650800, south=43.0, west=-30.0, north=60.0, east=10.0),
    ],
    # out_of_box_value=float("nan"),   # what a point in no box returns (default NaN)
)

currents = env.currents()
currents.set_interpolation_method("linear")

u, v = currents.at(40.0, -50.0, 1781524800)         # routed to the owning box in C, O(1)
uv   = currents.at_batch(lats, lons, timestamps)    # routed + sampled in C, one call

buf = currents.empty_batch(len(lats))               # reusable (n, 2) float32 buffer
currents.at_batch(lats, lons, timestamps, out=buf)  # fill in place, returns buf

How dispatch works:

  • A dense (lat, lon, hour) lookup grid (1° × 1° × 1 h) stores, per cell, the index of the winning box. A query computes three integer indices and reads one cell — the heavy bilinear + time interpolation still runs in each box's compiled sampler.
  • Both .at() and .at_batch() run compiled, matching a plain dataset: at/sample route each point in C, and at_batch/sample_batch route and sample every point in C (no Python bucketing). They accept the same out= buffer and empty_batch() helper (see Reusing an output buffer with out= under Using NcData below), so batching is fast from small sizes up.
  • Overlap → first listed box wins. When boxes overlap in both space and time, the earliest box in boxes that covers the point is chosen (so you can layer a high-res box on top of a coarse one by listing it first).
  • A point in no box returns out_of_box_value (default NaN).
  • Cells cut by a box edge are resolved per query against the real box bounds, so routing is exact wherever the edges fall — including a point in a shared edge cell, which goes to the box that actually holds it rather than to whichever claimed the cell. inclusive and snap_to_grid below remove that per-query step for layouts that do not need it.
  • If every box shares the same [start, end], the time axis collapses and the grid stays tiny (~130 KB); otherwise it grows with the total time span (~22 MB for a 7-day window).

inclusive: say which edges each box owns

Box bounds are closed by default, so [0°, 10°] and [10°, 20°] both contain latitude 10.0 — they overlap on their shared edge, and the cell holding it has to be resolved per query.

inclusive lets you declare, per box, which of the six edges are inclusive:

MultiAmphiNcData(config, boxes, inclusive="half_open")   # default for every box

"half_open" keeps south/west inclusive and makes north/east exclusive, so abutting boxes partition space instead of overlapping. Nothing is left to resolve, and the box edges stay exactly where you put them.

What changes, for boxes [0°, 10°] and [10°, 20°] listed in that order:

query latitude closed (default) half_open
9.999 box 0 box 0
10.0 box 0 — both hold it, first listed wins box 1 — the box that starts there
10.001 box 1 box 1
19.999 box 1 box 1
20.0 box 1 — it owns its north edge out of box — nothing above claims it

Only the shared edge moves; everything else routes identically.

Accepted forms — a string of the edges that are inclusive, a {edge: bool} dict patching the default, a set of names, or an alias:

inclusive="south west start"     # the named edges are inclusive; the rest exclusive
inclusive={"north": False}       # patch one edge, keep the rest
inclusive={"south", "west"}      # set form
inclusive="closed"               # all six (the default — unchanged behaviour)
inclusive="half_open"            # south/west inclusive, north/east exclusive
inclusive="half_open_time"       # ...and `end` exclusive too

Any box may override the env-wide default with its own inclusive key. That matters at the outer rim: with north exclusive nothing claims the topmost box's north edge, so a query at exactly that latitude is out of box. Close the last box in each direction to get it back:

boxes = [dict(..., south=0, north=10), dict(..., south=10, north=20, inclusive="closed")]

Time edges

start and end work the same way, and matter when your windows abut rather than sharing one instant. Three consecutive one-hour boxes:

boxes = [dict(start=i * 3600, end=(i + 1) * 3600, south=0, west=0, north=10, east=10)
         for i in range(3)]
timestamp closed (default) end exclusive
0 box 0 box 0
3599 box 0 box 0
3600 box 0 — both windows hold it, first listed wins box 1 — the window that starts there
3601 box 1 box 1
7200 box 1 box 2
10800 box 2 box 2
12000 (past every window) box 2 box 2

Two things to note. Unlike latitude, a timestamp past the last window is not out of box: nothing holds that instant, so routing falls back to a box that holds the position and lets that box's own set_out_of_window_behaviour() decide — which is what keeps a climatology fallback reachable past the forecast horizon. And an exclusive end is exact to the second: [start, end) is [start, end-1], because timestamps are whole seconds.

Ask for it with "half_open_time" (spatial half-open plus an exclusive end), or by naming the edges:

MultiAmphiNcData(config, boxes, inclusive="half_open_time")
MultiAmphiNcData(config, boxes, inclusive={"end": False})   # only the time edge

"half_open" on its own is deliberately spatial only — most box sets pin one instant (start == end), and an exclusive end would make those windows empty, which raises rather than routing to nothing.

snap_to_grid: a cheaper dispatch, for a coarser edge

Routing buckets space into 1° cells, and box edges rarely land on cell edges. By default a cell cut by an edge is resolved per query against the real box bounds — exact, and a point outside every box reliably returns out_of_box_value.

For an abutting tiling, reach for inclusive="half_open" above first: it also leaves nothing to resolve, but keeps exact edges and loads no extra data. snap_to_grid earns its keep when box edges are ragged — not aligned to each other or to the cell grid — where no inclusivity rule can make them partition.

snap_to_grid=True widens every box outward until it swallows whole cells, then gives each cell to the first box listed that owns it. No cell is ever contested, so routing becomes a single array read with nothing to resolve:

multi = MultiAmphiNcData(config, boxes, snap_to_grid=True)
multi.requested_boxes[0]   # what you asked for:  north=10.0
multi.boxes[0]             # what you got:        north=11.0

The widening reaches the data, not just the routing — each box loads the wider area, otherwise it would own cells it cannot serve.

What it costs: each box loads up to one cell of extra data on every widened side, and returns data for up to a cell beyond what you asked for instead of out_of_box_value. The finer the tiling, the larger that overhead is relative to the boxes themselves.

Use it when box edges are ragged and you never treat out-of-box as a signal. Leave it off when out_of_box_value means something to you, or when RAM is the reason you are using multiple boxes at all.

cell_size: the resolution of the dispatch grid

Routing buckets space and time into cells; cell_size sets how big one is, as (lat_deg, lon_deg, seconds). The default is (1.0, 1.0, 3600).

MultiAmphiNcData(config, boxes, cell_size=(1.0, 1.0, 86400))

This is about the geometry of your box layout, not the resolution of your data. In particular the time cell has nothing to do with the product's timestep — tides at 1 h, wind and wave at 3 h then 6 h, currents at 24 h are all handled inside each box's sampler. The grid's time axis exists only to separate boxes that have different windows; if every box shares one [start, end] it collapses away entirely and the seconds you pass are irrelevant.

Two things follow.

Space: pick a cell that divides your tile pitch. A cell straddling a box edge has to be resolved per query, and the band of ground where that happens is one cell wide. Edges at 2.5° on a 1° grid put a full row in that band; a 0.5° grid makes every edge a cell edge. Against that, the grid is (180 / lat_deg) × (360 / lon_deg) × T cells of 2 bytes, so halving the cell quadruples it. Both sizes must divide 180° and 360° evenly, or the constructor raises.

Time: match your window granularity, not your files. One box per day wants seconds=86400 — at 3600 the grid carries 24× the layers to describe the same routing. Windows that abut want the opposite: a cell holding a window boundary is claimed by both neighbours, so coarse cells there create contention rather than removing it. Finer is safer when windows are adjacent, coarser when they are a day apart.

Routing itself is invariant: every cell size returns the same box for the same point. Only memory, build time, and how much resolving happens at the seams change. If you would rather not think about it, inclusive="half_open" removes the seam question at any resolution.

multi.cell_size          # (1.0, 1.0, 3600) -- what is actually in use

env.tidal_currents(), env.wind(), etc. work the same way and keep their per-box behaviour (tide tiling, climatology fallback). MultiAmphiNcData is a context manager and forwards close() to every box's env.

Using NcData

Use NcData when you want more manual control.

Load from basepaths

Use this when the library should discover the right NetCDF files for you.

from amphi_ncdata import NcData

currents = NcData.from_basepaths(
    basepaths=[
        "/data/data_api/FORECAST-CURRENT/",
        "/mnt/store/data_api/HIRES_v3/FORECAST/",
    ],
    start=1781478000,
    end=1781650800,
    south=35.0,
    west=-73.0,
    north=43.0,
    east=-30.0,
    allow_last_available=True,
)

currents.load("ucos")
currents.load("vcos")
currents.set_interpolation_method("linear")

print(currents.at(40.0, -50.0, 1781524800))

Load from explicit filepaths

Use this when you already know the exact files you want.

from amphi_ncdata import NcData

waves = NcData.from_filepaths(
    filepaths=[
        "/tmp/20260614.nc",
        "/tmp/20260615.nc",
    ],
    start=1781391600,
    end=1781478000,
    south=35.0,
    west=-73.0,
    north=43.0,
    east=-30.0,
)

waves.load("swh")
waves.load("mwp")
waves.load("mwd")
waves.set_interpolation_method("linear")

print(waves.at(40.0, -50.0, 1781434800))

Sampling

currents.set_interpolation_method("linear")
value = currents.sample("ucos", 40.0, -50.0, 1781524800)

Batch sampling

For large point sets, batch APIs avoid Python per-sample overhead:

lats = [39.5, 40.0, 40.5]
lons = [-51.0, -50.0, -49.0]
timestamps = [1781521200, 1781524800, 1781528400]

u_values = currents.sample_batch("ucos", lats, lons, timestamps)
uv_values = currents.at_batch(lats, lons, timestamps)

Notes:

  • sample_batch() returns one NumPy array
  • at_batch() returns one NumPy array shaped like (sample_count, variable_count) when multiple variables are loaded
  • use batch APIs when you already hold many independent points; for sequential, point-by-point access (e.g. routing), at() / sample() are the right call

Reusing an output buffer with out=

at_batch() and sample_batch() accept an optional out= buffer: results are written into it in place and the same array is returned — no per-call allocation. Build the correctly-shaped, correctly-typed buffer once with empty_batch() and reuse it across calls (e.g. re-sampling the same points on every step of a loop):

import numpy as np

lats = [39.5, 40.0, 40.5]
lons = [-51.0, -50.0, -49.0]
timestamps = [1781521200, 1781524800, 1781528400]

buf = currents.empty_batch(len(lats))                 # (n, 2) float32 for a 2-variable dataset
currents.at_batch(lats, lons, timestamps, out=buf)    # returns buf, filled in place

sbuf = np.empty(len(lats), dtype=np.float32)          # (n,) float32 for a single variable
currents.sample_batch("ucos", lats, lons, timestamps, out=sbuf)

out must be a C-contiguous float32 array of shape (n, variable_count) for at_batch() — or (n,) when the dataset has a single loaded variable, and always (n,) for sample_batch(). empty_batch(n) returns exactly the shape at_batch() needs. Passing out= implies a NumPy-array return (the as_numpy flag is ignored).

When to batch: the batch APIs run the same compiled sampler as at() / sample(), but in one call. They carry a small fixed per-call cost, so for just a few points a plain at() loop is still faster; batching pays off from roughly a few dozen points upward and scales to millions.

Supported interpolation values for set_interpolation_method():

  • "nearest"
  • "linear"

No-data near the coast: skip_nan and set_no_data_value()

Coastal and land cells carry the product's _FillValue, which decodes to NaN. Bilinear interpolation reads four corners, so one no-data corner is enough to make the whole sample NaN — which is why a point near the coast can return a value under "nearest" and nothing under "linear".

There are two independent controls, and they compose.

1. Interpolate from the corners that do hold data:

currents.set_interpolation_method("linear", skip_nan=True)

The no-data corners drop out and the survivors are reweighted: two valid corners and two no-data corners interpolate from the two valid ones. All four no-data still gives NaN — there is nothing to interpolate from. The same rule extends to the time blend, so a timestep that is wholly no-data no longer poisons the one next to it. Water away from the coast is unaffected: a stencil with no no-data in it interpolates exactly as before.

skip_nan is remembered across calls, so pass it only when changing it. It has no effect under "nearest", which reads a single cell.

2. Give the no-data mask a value:

waves.set_no_data_value(0.0)                                   # every variable
waves.set_no_data_value((0.0, 0.0, float("nan")))              # swh, mwp, mwd
waves.set_no_data_value({"mwd": float("nan")}, when="after_interpolation")

The value is per variable — a scalar applies to all of them, a tuple/list is positional over loaded_variables (waves is height, period, direction; wind is u, v), and a dict sets only the variables it names. Each entry is a float, or NaN to leave that variable as it was.

when decides where the substitution happens, and the two are not equivalent:

when What happens Use it when
"before_interpolation" No-data cells enter the stencil as value, and all four corners interpolate normally. The mask means a real physical value (nil current inside a harbour), so it should bleed into nearby water the way the data would.
"after_interpolation" Interpolate as usual, then replace the result if it came out NaN. Applies whatever skip_nan is set to. You need a number everywhere — it is the backstop for what skip_nan cannot rescue.

after_interpolation never touches valid water, and it does not override set_out_of_window_behaviour(): it replaces no-data, not an out-of-window query, which stays with the out-of-window policy.

Two edges worth knowing. skip_nan reweights by interpolation weight, so a query sitting exactly on a no-data grid node still gives NaN — the valid corners carry zero weight there. And skip_nan never invents data. For a value in those cases, combine the two:

currents.set_interpolation_method("linear", skip_nan=True)
currents.set_no_data_value(0.0, when="after_interpolation")

no_data_values reports what is currently set, as {variable: (value, when)}. Both settings are available on NcData, on every AmphiNcData accessor (including tidal_currents()), and on MultiAmphiNcData routed datasets, where they apply to every box.

Lazy loading and cache

cache = {"size": 128 * 1024 * 1024, "nelems": 20000, "preemption": 0.8}

tidal = NcData.from_basepaths(
    basepaths=["/data/data_api/FORECAST-TIDE/"],
    start=1781478000,
    end=1781650800,
    south=35.0,
    west=-73.0,
    north=43.0,
    east=-30.0,
    allow_last_available=True,
)

tidal.load("utotal", lazy=True, cache=cache)
tidal.load("vtotal", lazy=True, cache=cache)

Loaded variables keep their raw on-disk dtype in RAM (e.g. int16 for currents/tides/waves); scale_factor, add_offset, and _FillValue are applied inside the Cython sampler at lookup time. This halves resident memory for packed products versus decoding to float32 up front, with no loss of precision. (The decode= argument to load() is retained for API compatibility but is now a no-op — storage is always the raw dtype.)

Inspect loaded state

print(currents.resolved_files)
print(currents.loaded_variables)
print(currents.time_range)
print(currents.bounds)
print(currents.contains_timestamp(1781524800))

Context manager

from amphi_ncdata import NcData

with NcData.from_basepaths(
    basepaths=["/data/data_api/FORECAST-CURRENT/"],
    start=1781478000,
    end=1781650800,
    south=35.0,
    west=-73.0,
    north=43.0,
    east=-30.0,
) as data:
    data.load("ucos")
    data.set_interpolation_method("linear")
    print(data.sample("ucos", 40.0, -50.0, 1781524800))

Out-of-window behaviour

A query is "out of window" when its timestamp is outside the loaded time range, or its lat/lon is outside the loaded bounding box. Choose what at() / sample() (and the batch variants) return in that case:

wind.set_out_of_window_behaviour("nearest")   # default: clamp to the nearest
                                               # available timestep / edge cell
wind.set_out_of_window_behaviour("nan")        # return NaN (handy to detect gaps)
wind.set_out_of_window_behaviour("value", 0.0) # return a fixed fill value

This is independent of NaN coming from the data itself (land / fill gaps), which is always returned as NaN regardless of the mode. The setting applies equally to out-of-range time and out-of-box space.

Timestamps And Coordinates

Accepted timestamp format:

  • Unix timestamp integer in seconds

Sampling coordinate format:

  • lat and lon are passed as separate numeric arguments

Errors

The package raises:

  • AmphiDiscoveryError: file discovery, open, or setup problems
  • AmphiVariableError: variable loading or sampling problems
  • AmphiNativeError: lower-level native errors

Missing data is not an error. A window with no files, partial coverage, or only a stale run on disk sets a code on dataset.warnings and still returns a usable dataset — see warnings. So this does not raise; it returns an empty dataset whose queries yield NaN:

from amphi_ncdata import NcData, WARN_NO_FILES

wind = NcData.from_basepaths(
    ["/tmp/does-not-exist"],
    start=0, end=1, south=0, west=0, north=1, east=1,
)
wind.is_empty                       # True
wind.warnings == WARN_NO_FILES      # True

# Pass on_warning="raise" for the old behaviour:
NcData.from_basepaths(["/tmp/does-not-exist"], start=0, end=1,
                      south=0, west=0, north=1, east=1,
                      on_warning="raise")   # -> AmphiDiscoveryError

What does raise, regardless of on_warning:

from amphi_ncdata import AmphiVariableError

try:
    env.wind(u_var="not_a_variable")     # request is wrong, not the archive
except AmphiVariableError as exc:
    print(exc)

One caveat: variable names are validated against the file, so on an empty dataset there is nothing to validate against — a typo'd name is accepted there and only surfaces once the window has files. Check warnings before concluding that a run of NaN means a bad variable name.

Performance

  • at() and sample() are backed by a compiled sampler, so single-point lookups are fast. This is the intended path for routing algorithms (Dijkstra / A* / isochrone / DP) that sample one point at a time, where each step depends on the previous one.
  • Eager-loaded variables (the default) stay in memory, so sampling never touches disk. Use lazy=True only for variables too large to keep resident; lazy sampling reads from disk and is much slower per point.
  • at_batch() / sample_batch() run the same compiled sampler over many points in one call. They carry a small fixed per-call cost, so use them once you have roughly a few dozen points or more (below that, an at() loop wins). Pass out= (from empty_batch()) to avoid per-call allocation when sampling repeatedly.

Practical Notes

  • A wheel is specific to an OS, Python version, and architecture.
  • If you change Python versions, you may need a new wheel.
  • AmphiNcData(...) accepts missing path keys, but a dataset helper such as env.wind() or env.waves() still raises immediately if that dataset cannot be resolved.
  • AmphiNcData is the best starting point unless you specifically need file-level control.
  • This package focuses on point sampling, not bulk NumPy-style array workflows.

Release files for amphi-ncdata 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for amphi-ncdata 0.6.1
File Size Uploaded
amphi_ncdata-0.6.1.tar.gz 367.5 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for amphi-ncdata 0.6.1
File
amphi_ncdata-0.6.1-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
amphi_ncdata-0.6.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
amphi_ncdata-0.6.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.14 CPython 3.14 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
amphi_ncdata-0.6.1-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
amphi_ncdata-0.6.1-cp314-cp314-macosx_10_15_x86_64.whl CPython 3.14 CPython 3.14 macOS 10.15+ x86-64 Details
amphi_ncdata-0.6.1-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
amphi_ncdata-0.6.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
amphi_ncdata-0.6.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 Details
amphi_ncdata-0.6.1-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
amphi_ncdata-0.6.1-cp313-cp313-macosx_10_13_x86_64.whl CPython 3.13 CPython 3.13 macOS 10.13+ x86-64 Details
amphi_ncdata-0.6.1-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
amphi_ncdata-0.6.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
amphi_ncdata-0.6.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
amphi_ncdata-0.6.1-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
amphi_ncdata-0.6.1-cp312-cp312-macosx_10_13_x86_64.whl CPython 3.12 CPython 3.12 macOS 10.13+ x86-64 Details
amphi_ncdata-0.6.1-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
amphi_ncdata-0.6.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
amphi_ncdata-0.6.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
amphi_ncdata-0.6.1-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
amphi_ncdata-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl CPython 3.11 CPython 3.11 macOS 10.9+ x86-64 Details
amphi_ncdata-0.6.1-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details
amphi_ncdata-0.6.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
amphi_ncdata-0.6.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
amphi_ncdata-0.6.1-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details
amphi_ncdata-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl CPython 3.10 CPython 3.10 macOS 10.9+ x86-64 Details

Total release size: 12.4 MB

Release files / amphi_ncdata-0.6.1.tar.gz

Download URL amphi_ncdata-0.6.1.tar.gz
Size 367.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d4c94439dec8b73e7d35d5ea963328ade7b56b570fe697ebcfda8732e39b6e3c
BLAKE2b-256 checksum
How to use checksums
a010e6457b68fce7fd1b7608dbc35c39c8e14f924425d77fedcdd440997c526b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp314-cp314-win_amd64.whl

Download URL amphi_ncdata-0.6.1-cp314-cp314-win_amd64.whl
Size 200.1 kB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
727b2c1783db2a6c9c83e64907fb5780c3235c28e5a19d2346e94f7ebf41cfa8
BLAKE2b-256 checksum
How to use checksums
391a09be3fc1e520b3fe65742f270525bc1497e1246beee57fb07ae207a8568c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 901.6 kB
Tags CPython 3.14 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
fdaeae9c2055228c4faec872402406fb1008c0ad1c6e90f8b6b4794df3563d55
BLAKE2b-256 checksum
How to use checksums
15bfd36486d8062b37640e5fd6ccb1a9726b56bceb459628ae5970b647d9cab7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL amphi_ncdata-0.6.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 884.4 kB
Tags CPython 3.14 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
71b4c58dec9c273d69e94ffb0492a6d9629e3160016a19f23406109ac9c374f9
BLAKE2b-256 checksum
How to use checksums
a12a9bbff439a2a31ff2b8dcaffafbf834fda0d3b600609e308e789531315940
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp314-cp314-macosx_11_0_arm64.whl

Download URL amphi_ncdata-0.6.1-cp314-cp314-macosx_11_0_arm64.whl
Size 205.0 kB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
fbd5c283dac04c7e94c8265de0df8eca6cdb3b5214f52a18087c75228eadbf54
BLAKE2b-256 checksum
How to use checksums
0492523994f03414a7104f2e9b8836c7b7a4d91261fc442620aaa9008dc27a1d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp314-cp314-macosx_10_15_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp314-cp314-macosx_10_15_x86_64.whl
Size 213.0 kB
Tags CPython 3.14 macOS 10.15+ x86-64
SHA-256 checksum
How to use checksums
3a8ac174ce0d5a7d0d26a3d105231e0693c625ae728b774d3e78d76c5f33d329
BLAKE2b-256 checksum
How to use checksums
eda4d8e9581cbba4dfaf07341c3bec17d7b1b047fd24e78445a30359178e0ba3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp313-cp313-win_amd64.whl

Download URL amphi_ncdata-0.6.1-cp313-cp313-win_amd64.whl
Size 195.9 kB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
94a0ae1f8795334b75925a76ee6081492aa4dfe171b6d0bf2b378cb56fbc2a0e
BLAKE2b-256 checksum
How to use checksums
259655ca977db1d1cfeda4ade74d32b80c771a86991d2888de59b2b97343c707
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 910.2 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
cb776e77ead8106c7bcd200b78fa838d2d1824dfe460beb600184636e3572a25
BLAKE2b-256 checksum
How to use checksums
716a4e7b539e4d79cec7a1b663c4382fc67521f1ade21db299a5edbeb5689ff3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL amphi_ncdata-0.6.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 886.4 kB
Tags CPython 3.13 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
d38758e7dac1234b7edf05d8f794897a8c2e304ce444d0c7e362440526041697
BLAKE2b-256 checksum
How to use checksums
1fbe26bfdb6c2ae3ff615f0a5463373ce5f3a539df40c02d174c1b509a32b414
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp313-cp313-macosx_11_0_arm64.whl

Download URL amphi_ncdata-0.6.1-cp313-cp313-macosx_11_0_arm64.whl
Size 204.4 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f66b7ba3433eabdabc593ff16c246aa60bfa85559136f4e74a789ed15a4af147
BLAKE2b-256 checksum
How to use checksums
c9d223e9234c2546002355bb9a7458159b726c4e62a0d72ff99031ff05aa7a6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp313-cp313-macosx_10_13_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp313-cp313-macosx_10_13_x86_64.whl
Size 212.6 kB
Tags CPython 3.13 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
4e2941874a48277d99528c2858dbff967d3895659d3796a51cfc55526a88967b
BLAKE2b-256 checksum
How to use checksums
c53e3fe5a2ee29558983cf9936aa82d0e93ab5d48538a64f351590d3bba020c1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp312-cp312-win_amd64.whl

Download URL amphi_ncdata-0.6.1-cp312-cp312-win_amd64.whl
Size 196.1 kB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
bcc3213f1ec7ef69ecbbb0379474b3fc1b3962e80d136d1504e798b96c77b9b8
BLAKE2b-256 checksum
How to use checksums
6dc5a2f09b34b38d68bd1bcdb18b2a5f44283ac25dbad4525f8bb4a7e7ea1f92
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 920.7 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
a0a664933200bc084d093570cb956f1fdadb1dbcf407d97b0214788ad5255d92
BLAKE2b-256 checksum
How to use checksums
6ee75b86ebb01b07b2051b87abe0a7a75bafb39f4a20aba4fc47ec35dc4f7453
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL amphi_ncdata-0.6.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 901.1 kB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
078e2bb3c5f2f29c090be90e493f87d4a5e94653394abd27aa5c21efa9393bf7
BLAKE2b-256 checksum
How to use checksums
4789b5e627a2a32d19ccf1952f943381ff150975b4823ac07abee503fd7610b1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp312-cp312-macosx_11_0_arm64.whl

Download URL amphi_ncdata-0.6.1-cp312-cp312-macosx_11_0_arm64.whl
Size 205.4 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
20ff06741764d13afe4a4fc8d6f3d7032b1e30d486eb257fff552731cce5be60
BLAKE2b-256 checksum
How to use checksums
89f4b80b9cfe38d64aefbfa6e1a4d4d6735f19443b9cdc9655acf64390639b66
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp312-cp312-macosx_10_13_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp312-cp312-macosx_10_13_x86_64.whl
Size 213.5 kB
Tags CPython 3.12 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
c781172892cc3546957aa28bf1f46909114401d04c2f0b793da41fb3d4fcfd3b
BLAKE2b-256 checksum
How to use checksums
7abc0425547a574616e559ade3217cdfcc143e6e5fef0a5c0b63860baca72fda
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp311-cp311-win_amd64.whl

Download URL amphi_ncdata-0.6.1-cp311-cp311-win_amd64.whl
Size 197.5 kB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
29418dbe3423f31410716a66a972028b0d59ec192e5b790419d2a3de886060dc
BLAKE2b-256 checksum
How to use checksums
4186af22dc3fe65e1f1e7982f36e51151ef8e16925f52c03ac40ca502dea6d52
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 907.7 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
9657a2af8b27fa03d914b33e0c017e24b74695025dfcc19fd67fd6de53143de8
BLAKE2b-256 checksum
How to use checksums
8facf798f4b60582a348318b40981e0a951174201b6a459ee2253fc2fb8315b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL amphi_ncdata-0.6.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 899.5 kB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
8eb252e3fdc5b9c47abe6328027a40442f43911aa4064371ab603c8fc4b50e29
BLAKE2b-256 checksum
How to use checksums
60ee4193df7991e613deb64a89f568a4669208d3d7006e5be167b10477bf2442
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp311-cp311-macosx_11_0_arm64.whl

Download URL amphi_ncdata-0.6.1-cp311-cp311-macosx_11_0_arm64.whl
Size 205.2 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
ffb7770821a1ce9a84748952b2f122ddc53ea437cee53581e7714d7dab2f654f
BLAKE2b-256 checksum
How to use checksums
55950053e16c264bc9c8f8592aa460ef9d1c63d145b09f65e296328055a8abf8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp311-cp311-macosx_10_9_x86_64.whl
Size 213.6 kB
Tags CPython 3.11 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
5f7a9a1f8390b2fe2160ceabcd1eb2a74d6206871e1c2de75e51ccf15fe09437
BLAKE2b-256 checksum
How to use checksums
497f316adadea9c8c297e6d1a6a8dae8c9dfdb65d7852a87fc62674ee25fa001
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp310-cp310-win_amd64.whl

Download URL amphi_ncdata-0.6.1-cp310-cp310-win_amd64.whl
Size 197.7 kB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
1d397e77df74b45c88ab4d28d7080e142f4c2a5db30bf37a9b242b282282cd37
BLAKE2b-256 checksum
How to use checksums
0d6fdfeeaa66e848702de0c37acc006b4f6948675913885b88774a85fdec9529
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 865.2 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
1c383f3328aa0bb2bd7045c41c71fc76922482311eb20f47e09e47ceca1dfadc
BLAKE2b-256 checksum
How to use checksums
6b1060ca2cb78d51d4976dba21ed194da8c7d17bbf3e9dd0b088f634c970300e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL amphi_ncdata-0.6.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 858.7 kB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
28a7d7dc35ef65103a2f06c9a0dd465357f2c8d30fe8e2045755e6eca3216a30
BLAKE2b-256 checksum
How to use checksums
5832d31c1bee44714dfb2afe4b96cbb954013e301a4cbdeb11016c8bcd117e25
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp310-cp310-macosx_11_0_arm64.whl

Download URL amphi_ncdata-0.6.1-cp310-cp310-macosx_11_0_arm64.whl
Size 206.1 kB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9e2d66c0cc194d36319b709929247eaaf6120de7da271f06e64df332279ae5b8
BLAKE2b-256 checksum
How to use checksums
97faca5e8095316c1d176c78ec378c74546a5c334d8fdce3ed8f5938f38d21aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release files / amphi_ncdata-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl

Download URL amphi_ncdata-0.6.1-cp310-cp310-macosx_10_9_x86_64.whl
Size 214.9 kB
Tags CPython 3.10 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
18bb6566a66ed20350888e16cc4ae37d15afe079330ea80b0c6bd094be79f17f
BLAKE2b-256 checksum
How to use checksums
117d273b972a640e359793d54df927f3ae92864ac7c30ea8065ecd8656d5ec47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 12, 2026.

Transparency log

Release history Release notifications | RSS feed

0.6.4

26 release files

0.6.3

26 release files

0.6.2

26 release files

This release

0.6.1 This release

26 release files

0.6.0

26 release files

0.5.0

26 release files

0.3.1

26 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page