Metadata-Version: 2.4
Name: annoray
Version: 0.0.1rc0
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Rust
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Typing :: Typed
Requires-Dist: numpy>=1.26
Requires-Dist: matplotlib>=3.8
Requires-Dist: astropy>=6 ; extra == 'astropy'
Requires-Dist: cftime ; extra == 'cftime'
Requires-Dist: pytest ; extra == 'test'
Requires-Dist: xarray>=2025.1 ; extra == 'test'
Requires-Dist: pandas ; extra == 'test'
Requires-Dist: cftime ; extra == 'test'
Requires-Dist: netcdf4 ; extra == 'test'
Requires-Dist: h5netcdf ; extra == 'test'
Requires-Dist: h5py ; extra == 'test'
Requires-Dist: astropy>=6 ; extra == 'test'
Requires-Dist: zarr>=3 ; extra == 'test'
Requires-Dist: scipy ; extra == 'test'
Requires-Dist: bottleneck ; extra == 'test'
Requires-Dist: cf-xarray ; extra == 'test'
Requires-Dist: pint ; extra == 'test'
Requires-Dist: dask ; extra == 'test'
Requires-Dist: xarray>=2025.1 ; extra == 'xarray'
Provides-Extra: astropy
Provides-Extra: cftime
Provides-Extra: test
Provides-Extra: xarray
License-File: LICENSE-MIT
License-File: LICENSE-APACHE
Summary: Annotated arrays: labelled, units-aware N-dimensional arrays with netCDF and HDF5 I/O, in Rust
Keywords: xarray,netcdf,hdf5,units,labelled arrays,climate,cf-conventions
Home-Page: https://github.com/sunipkm/annoray
Author-email: "Sunip K. Mukherjee" <sunipkmukherjee@gmail.com>
License-Expression: MIT OR Apache-2.0
Requires-Python: >=3.11
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Changelog, https://github.com/sunipkm/annoray/releases
Project-URL: Homepage, https://github.com/sunipkm/annoray
Project-URL: Issues, https://github.com/sunipkm/annoray/issues
Project-URL: Repository, https://github.com/sunipkm/annoray

# annoray

**Annotated arrays**: the [xarray](https://xarray.dev) data model with first-class physical
units, implemented in Rust (PyO3). I/O uses pure-Rust netCDF-3, netCDF-4, HDF5 and Zarr
(v2/v3, `open_zarr`/`to_zarr`) backends; the runtime dependencies are NumPy and matplotlib.
Wheels use the stable ABI: one per platform for CPython 3.11 and later.

- **Labelled indexing and alignment:** `isel`, `sel` (exact, nearest, pad, backfill;
  pointwise with `DataArray` indexers), `query`, name-based broadcasting, `groupby`,
  `resample`, `convert_calendar`, `rolling`, `rolling_exp`, `coarsen`, `weighted`, `interp`,
  `interpolate_na`, `stack`/`unstack`, `concat`, `merge`, `DataTree`.
- **Computation:** quantiles, `corr`/`cov`, `differentiate`/`integrate`/`polyfit`, numpy
  ufuncs and `apply_ufunc`, the `.str` accessor, all unit-aware.
- **Immutable values, checked updates:** `da[...] = v` is refused; `da.put(v, time=3)` and
  `da.put_sel(v, time="2001-07-01")` return an updated copy, converting `v` into the array's
  unit and refusing values that do not fit its element type. Containers are assignable:
  `ds["v"] = ...`, `ds.coords[...] = ...`, and `attrs`/`encoding` are live dicts.
- **Units:** binary operations check dimensional consistency and propagate units; `.to(...)`
  converts exactly; CF `units` attributes decode into units.
- **Out-of-core evaluation:** lazy memory-mapped open; lazy elementwise composition and
  streaming reductions within a configurable memory budget (`set_stream_bytes`), including
  disk-to-disk pipelines.
- **Dimension annotations:** `Quantity[Velocity]` / `DataArray[Velocity]` type hints,
  enforced at call time by `@checked`; derived dimensions are declared as `Dim` subclasses.
- **Zero-copy NumPy interop:** `.values` exposes the Rust buffer as a read-only array; text
  is NumPy fixed-width `<U{n}`.
- **Performance:** parallel kernels and chunk decoding; faster than xarray (with bottleneck,
  flox, numbagg and dask) in most operations on large files, with one copy of the data on
  load and streaming reductions in a few hundred MB
  ([benchmarks](https://github.com/sunipkm/annoray/blob/main/docs/performance.md)).
- **astropy interop** (`annoray[astropy]`): `to_astropy()` on units, quantities and arrays;
  `from_astropy(...)`; astropy units accepted wherever units are. Units correspond through
  their SI-plus-radian decomposition (angle is a dimension in both); names are kept only
  where both systems define them identically (UDUNITS' `yr` is the tropical year, astropy's
  the Julian year); °C/°F map to `deg_C`/`deg_F`.
- **matplotlib plotting:** `da.plot()` dispatching on rank, `line`, `step`,
  `hist`, `scatter`, `pcolormesh`, `imshow` (incl. RGB), `contour`, `contourf`, `surface`;
  `ds.plot.scatter`/`quiver`/`streamplot`; `row`/`col` faceting via `FacetGrid` with a shared
  colour scale. Semantics follow `xarray.plot` (CF-derived labels, robust/divergent colormap
  heuristics, discrete levels, interval inference); labels carry the array's unit.

> Pre-1.0: the API is unstable.

```sh
pip install annoray            # extras: "annoray[xarray]", "annoray[astropy]"
```

```python
import numpy as np
import annoray as ar

da = ar.DataArray(
    np.arange(6.0).reshape(2, 3),
    dims=("x", "y"),
    coords={"x": [10.0, 20.0], "y": [1.0, 2.0, 3.0]},
    units="m",
)
seconds = ar.DataArray(2.0, units="s")
print((da / seconds).units)  # m s-1
print(da.sel(y=2.4, method="nearest").mean("x").to("cm").values)
try:
    da + seconds
except ar.UnitError as e:  # dimensionally inconsistent
    print(e)

ds = ar.open_dataset("air_temperature.nc")  # lazy, memory-mapped
point = ds["air"].sel(lat=40.0, lon=260.0, method="nearest")
print(point.max("time").to("degC"))
```

xarray is optional. When present, annoray registers an xarray backend
(`engine="annoray"`) and provides `to_xarray()` / `from_xarray()` conversion (units map to the
`units` attribute) and `ar.to_netcdf(obj, path)` for writing xarray objects with annoray's
writers.

Most xarray code runs unchanged with `import annoray as ar`. The deliberate differences
(unit-checked comparisons and fills, no unchecked casts, immutable values, single-coordinate
indexes, eager computation instead of dask) are listed in
[differences from xarray](https://github.com/sunipkm/annoray/blob/main/docs/xarray-differences.md).

Further examples: [`examples/`](https://github.com/sunipkm/annoray/tree/main/annoray-python/examples)
(each paired with a Rust twin of identical output).

## License

Dual-licensed under [Apache-2.0](LICENSE-APACHE) or [MIT](LICENSE-MIT), at the licensee's
option.

