Skip to content

Commit 8ef0279

Browse files
authored
Merge pull request #8 from d-v-b/chore/docs
docs!: add zensical-based docs for the project
2 parents bd23d2a + 561f7e3 commit 8ef0279

28 files changed

Lines changed: 359 additions & 172 deletions

.readthedocs.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ build:
1212
- asdf install uv latest
1313
- asdf global uv latest
1414
- uv sync --group docs
15-
- uv run mkdocs build --site-dir $READTHEDOCS_OUTPUT/html
15+
- uv run zensical build --site-dir $READTHEDOCS_OUTPUT/html

README.md

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,69 @@
3030

3131
# cast-value.py
3232

33-
Python implementation of the `cast_value` codec for Zarr.
33+
A python implementation of the `cast_value` codec for [Zarr](https://zarr.dev/),
34+
with [zarr-python](https://zarr.readthedocs.io/en/stable/) integration.
3435

35-
## `cast_value` codec
36+
## what
3637

37-
The `cast_value` codec defines an operation for safely converting an array from
38-
one numeric data type to another.
38+
The `cast_value` codec defines how to _safely_ convert arrays between integer
39+
and float data types. In Zarr terminology, this codec is an "array -> array"
40+
codec, which means its input and output are both arrays.
41+
42+
You can find the
43+
[specification for this codec](https://github.com/zarr-developers/zarr-extensions/tree/main/codecs/cast_value)
44+
in the
45+
[zarr-extensions repository](https://github.com/zarr-developers/zarr-extensions).
46+
47+
## why
48+
49+
This codec is commonly used to for lossy data compression: when decoded data
50+
should be high-precision floats, but the absolute range of the values fits
51+
within the range of a smaller integer data type, then encoding the floats as
52+
ints before writing data can vastly shrink the stored values.
53+
54+
For example, if your data is a sequence of `float64` values like
55+
`[100.1, 120.3, 125.5]`, storing those values as `uint8`, e.g.
56+
`[100, 120, 125]`, offers 8-fold reduction in storage size, provided the
57+
precision lost due to rounding is acceptable.
58+
59+
## how
60+
61+
```python
62+
# import the codec that uses the rust backend
63+
from cast_value import CastValueRustV1
64+
65+
# Create an in-memory zarr array with float64 dtype, stored as uint8.
66+
# The cast_value codec handles the conversion: float64 -> uint8 on write,
67+
# uint8 -> float64 on read.
68+
69+
codec = CastValueRustV1(
70+
data_type="uint8",
71+
rounding="nearest-even",
72+
out_of_range="clamp",
73+
scalar_map={
74+
"encode": [(np.nan, 0), (np.inf, 1), (-np.inf, 2)],
75+
"decode": [(0, np.nan), (1, np.inf), (2, -np.inf)],
76+
},
77+
)
78+
# Create array and write float64 data — values are rounded and clamped to [0, 255]
79+
data = np.array([np.nan, np.inf, -np.inf, 3.3, 4])
80+
arr = zarr.create_array(data=data, store=zarr.storage.MemoryStore(), filters=codec)
81+
82+
# Read it back — comes back as float64, but with uint8 precision
83+
result = arr[:]
84+
85+
print(f"Array dtype: {arr.dtype}")
86+
print(f"Values written: {data}")
87+
print(f"Values read: {result}")
88+
89+
"""
90+
Array dtype: float64
91+
Values written: [ nan inf -inf 3.3 4. ]
92+
Values read: [ nan inf -inf 3. 4.]
93+
"""
94+
```
95+
96+
# who
97+
98+
Davis Bennett (@d-v-b)

docs/api.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,21 @@
1-
# ::: cast_value.example
1+
# Python API
2+
3+
## Zarr Codec
4+
5+
::: cast_value.CastValueRustV1
6+
7+
::: cast_value.CastValueNumpyV1
8+
9+
::: cast_value.cast_array
10+
11+
::: cast_value.ScalarMapJSON
12+
13+
::: cast_value.ScalarMapEntry
14+
15+
::: cast_value.ScalarMapEntries
16+
17+
::: cast_value.RoundingMode
18+
19+
::: cast_value.OutOfRangeMode
20+
21+
::: cast_value.NumericScalar

docs/index.md

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,61 @@
11
# cast-value
22

3-
Here you can document whatever you'd like on your main page. Common choices
4-
include installation instructions, a minimal usage example, BibTex citations,
5-
and contribution guidelines.
3+
Python implementation of the
4+
[`cast_value` codec](https://github.com/zarr-developers/zarr-extensions/tree/main/codecs/cast_value)
5+
for [Zarr V3](https://zarr-specs.readthedocs.io/en/latest/v3/core/index.html).
66

7-
See [this link](https://squidfunk.github.io/mkdocs-material/reference/) for all
8-
the easy references and components you can use with mkdocs-material, or feel
9-
free to go through through
10-
[from the top](https://squidfunk.github.io/mkdocs-material/).
7+
The `cast_value` codec converts array elements between numeric data types during
8+
encoding and decoding, with configurable rounding, out-of-range handling, and
9+
explicit scalar mappings.
1110

1211
## Installation
1312

14-
You can install this package via running:
13+
```bash
14+
pip install cast-value
15+
```
16+
17+
For the optional Rust-accelerated backend:
1518

1619
```bash
17-
pip install cast_value
20+
pip install cast-value[rs]
21+
```
22+
23+
## Quick start
24+
25+
```python
26+
import numpy as np
27+
import zarr
28+
from cast_value import CastValueNumpyV1
29+
30+
zarr.registry.register_codec("cast_value", CastValueNumpyV1)
31+
32+
codec = CastValueNumpyV1(
33+
data_type="uint8",
34+
rounding="nearest-even",
35+
out_of_range="clamp",
36+
)
37+
38+
arr = zarr.create(
39+
shape=(100,),
40+
dtype="float64",
41+
chunks=(10,),
42+
store=zarr.storage.MemoryStore(),
43+
codecs=[codec, zarr.codecs.BytesCodec()],
44+
fill_value=0.0,
45+
)
46+
47+
arr[:] = np.linspace(0, 300, 100)
48+
print(arr[:10]) # [0. 3. 6. 9. 12. 15. 18. 21. 24. 27.]
1849
```
50+
51+
## Backends
52+
53+
Two backends are available:
54+
55+
- **`CastValueNumpyV1`** — Pure Python + NumPy. Always available.
56+
- **`CastValueRustV1`** — Rust via
57+
[cast-value-rs](https://pypi.org/project/cast-value-rs/). Faster for
58+
non-default rounding modes and SIMD-accelerated float-to-integer casts with
59+
clamping, with more efficient memory usage.
60+
61+
Both implement the same codec interface and produce identical results.

examples/benchmarks/bench_numpy_vs_rust.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
import numpy as np
2222
from cast_value_rs import cast_array as rs_cast_array
2323

24-
from cast_value.core import cast_array as numpy_cast_array
24+
from cast_value.impl._numpy import cast_array as numpy_cast_array
2525

2626
SIZE = 1_000_000
2727
WARMUP = 3

examples/zarr_integration/zarr_cast_value.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,20 @@
1717

1818
import numpy as np
1919
import zarr
20+
import zarr.registry
21+
import zarr.storage
2022

21-
from cast_value.zarr_compat.v1 import CastValueRust
23+
from cast_value.zarr_compat.v1 import CastValueRustV1
2224

2325
# Register the codec so zarr can discover it by name
24-
zarr.registry.register_codec("cast_value", CastValueRust)
26+
zarr.registry.register_codec("cast_value", CastValueRustV1)
2527

2628

2729
def main() -> None:
2830
# Create an in-memory zarr array with float64 dtype, stored as uint8.
2931
# The cast_value codec handles the conversion: float64 -> uint8 on write,
3032
# uint8 -> float64 on read.
31-
codec = CastValueRust(
33+
codec = CastValueRustV1(
3234
data_type="uint8",
3335
rounding="nearest-even",
3436
out_of_range="clamp",

mkdocs.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ site_name: cast-value
22
site_url: https://cast-value.readthedocs.io/
33
site_author: "Davis Bennett"
44

5-
repo_name: "zarr-developers/cast_value"
6-
repo_url: "https://github.com/zarr-developers/cast-value"
5+
repo_name: "zarr-developers/cast-value.py"
6+
repo_url: "https://github.com/zarr-developers/cast-value.py"
77

88
theme:
99
name: material
@@ -16,8 +16,6 @@ theme:
1616
- navigation.tracking
1717
- toc.follow
1818
palette:
19-
# See options to customise your color scheme here:
20-
# https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/
2119
- media: "(prefers-color-scheme: light)"
2220
scheme: default
2321
toggle:
@@ -34,17 +32,19 @@ plugins:
3432
mkdocstrings:
3533
handlers:
3634
python:
37-
paths: [.]
35+
paths: [src]
3836
inventories:
3937
- https://docs.python.org/3/objects.inv
40-
- https://docs.pydantic.dev/latest/objects.inv
4138
options:
39+
docstring_style: numpy
4240
members_order: source
4341
separate_signature: true
4442
filters: ["!^_"]
4543
show_root_heading: true
4644
show_if_no_docstring: true
4745
show_signature_annotations: true
46+
signature_crossrefs: true
47+
scoped_crossrefs: true
4848
search: {}
4949

5050
nav:

noxfile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,9 @@ def docs(session: nox.Session) -> None:
6464
session.install("-e.", *doc_deps)
6565

6666
if session.interactive:
67-
session.run("mkdocs", "serve", "--clean", *session.posargs)
67+
session.run("zensical", "serve", *session.posargs)
6868
else:
69-
session.run("mkdocs", "build", "--clean", *session.posargs)
69+
session.run("zensical", "build", *session.posargs)
7070

7171

7272
@nox.session(default=False)

pyproject.toml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,8 @@ dev = [
6262
{ include-group = "bench" },
6363
]
6464
docs = [
65-
"markdown>=3.9",
66-
"mdx-include>=1.4.2",
67-
"mkdocs-material>=9.1.19",
68-
"mkdocs>=1.1.2",
65+
"zensical",
6966
"mkdocstrings-python>=1.18.2",
70-
"pyyaml>=6.0.1",
7167
]
7268

7369

@@ -106,6 +102,7 @@ report.exclude_also = [
106102

107103
[tool.ruff]
108104
show-fixes = true
105+
exclude = ["src/cast_value/_version.py"]
109106

110107
[tool.ruff.lint]
111108
extend-select = [

src/cast_value/__init__.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,26 @@
66
from __future__ import annotations
77

88
from ._version import version as __version__
9+
from .impl._numpy import cast_array
10+
from .types import (
11+
NumericScalar,
12+
OutOfRangeMode,
13+
RoundingMode,
14+
ScalarMapEntries,
15+
ScalarMapEntry,
16+
ScalarMapJSON,
17+
)
18+
from .zarr_compat.v1 import CastValueNumpyV1, CastValueRustV1
919

10-
__all__ = ["__version__"]
20+
__all__ = [
21+
"CastValueNumpyV1",
22+
"CastValueRustV1",
23+
"NumericScalar",
24+
"OutOfRangeMode",
25+
"RoundingMode",
26+
"ScalarMapEntries",
27+
"ScalarMapEntry",
28+
"ScalarMapJSON",
29+
"__version__",
30+
"cast_array",
31+
]

0 commit comments

Comments
 (0)