3030
3131# cast-value.py
3232
33- A python implementation of the ` cast_value ` codec for [ Zarr] ( https://zarr.dev/ ) ,
33+ A Python implementation of the ` cast_value ` codec for [ Zarr] ( https://zarr.dev/ ) ,
3434with [ zarr-python] ( https://zarr.readthedocs.io/en/stable/ ) integration.
3535
36- ## what
36+ ## What
3737
3838The ` cast_value ` codec defines how to _ safely_ convert arrays between integer
3939and float data types. In Zarr terminology, this codec is an "array -> array"
@@ -44,55 +44,133 @@ You can find the
4444in the
4545[ zarr-extensions repository] ( https://github.com/zarr-developers/zarr-extensions ) .
4646
47- ## why
47+ ## Why
4848
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.
49+ This codec is commonly used for lossy data compression: when decoded data should
50+ be high-precision floats, but the absolute range of the values fits within the
51+ range of a smaller integer data type, then encoding the floats as ints before
52+ writing data can vastly shrink the stored values.
5353
5454For example, if your data is a sequence of ` float64 ` values like
5555` [100.1, 120.3, 125.5] ` , storing those values as ` uint8 ` , e.g.
5656` [100, 120, 125] ` , offers 8-fold reduction in storage size, provided the
5757precision lost due to rounding is acceptable.
5858
59- ## how
59+ ## Installation
60+
61+ <!-- pytest.mark.skip-->
62+
63+ ``` bash
64+ pip install cast-value
65+ ```
66+
67+ For the optional Rust backend (faster for large arrays):
68+
69+ <!-- pytest.mark.skip-->
70+
71+ ``` bash
72+ pip install ' cast-value[rs]'
73+ ```
74+
75+ ## Usage
76+
77+ The codec is automatically registered with zarr-python via the ` zarr.codecs `
78+ entrypoint. When ` cast-value[rs] ` is installed, the Rust backend is used;
79+ otherwise it falls back to the pure-NumPy backend.
6080
6181``` python
62- # import the codec that uses the rust backend
63- from cast_value import CastValueRustV1
82+ import numpy as np
83+ import zarr
84+ import zarr.storage
6485
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.
86+ from cast_value import CastValueNumpyV1
6887
69- codec = CastValueRustV1 (
88+ codec = CastValueNumpyV1 (
7089 data_type = " uint8" ,
7190 rounding = " nearest-even" ,
7291 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- },
7792)
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)
8193
82- # Read it back — comes back as float64, but with uint8 precision
94+ # Write float64 data -- values are rounded and clamped to [0, 255]
95+ data = np.array([1.5 , 100.7 , 255.9 , - 3.0 ], dtype = np.float64)
96+ arr = zarr.create_array(store = {}, data = data, filters = codec)
97+
98+ # Read it back -- comes back as float64, but with uint8 precision
8399result = arr[:]
84100
85101print (f " Array dtype: { arr.dtype} " )
86102print (f " Values written: { data} " )
87103print (f " Values read: { result} " )
104+ ```
105+
106+ <!-- pytest-codeblocks:expected-output-->
88107
89- """
108+ ```
90109Array dtype: float64
91- Values written: [ nan inf -inf 3.3 4. ]
92- Values read: [ nan inf -inf 3. 4.]
93- """
110+ Values written: [ 1.5 100.7 255.9 -3. ]
111+ Values read: [ 2. 101. 255. 0.]
112+ ```
113+
114+ ## Development
115+
116+ This project uses [ uv] ( https://docs.astral.sh/uv/ ) for dependency management.
117+
118+ ### Setup
119+
120+ <!-- pytest.mark.skip-->
121+
122+ ``` bash
123+ # Clone the repo
124+ git clone https://github.com/zarr-developers/cast-value.py.git
125+ cd cast-value.py
126+
127+ # Install dev dependencies (includes test + benchmark deps)
128+ uv sync --group dev
129+ ```
130+
131+ ### Running tests
132+
133+ <!-- pytest.mark.skip-->
134+
135+ ``` bash
136+ # Run the full test suite
137+ uv run pytest tests
138+
139+ # Run with coverage
140+ uv run pytest tests --cov=cast_value --cov-report=term-missing
141+ ```
142+
143+ ### Running all checks
144+
145+ <!-- pytest.mark.skip-->
146+
147+ ``` bash
148+ # Run the full CI suite locally (tests, linting, type checking)
149+ uvx nox
150+
151+ # Or run just linting and type checking
152+ uvx prek
153+ ```
154+
155+ ### Building docs
156+
157+ <!-- pytest.mark.skip-->
158+
159+ ``` bash
160+ uv sync --group docs
161+ uv run zensical build
162+ # Output is in site/
163+ ```
164+
165+ ### Running examples
166+
167+ <!-- pytest.mark.skip-->
168+
169+ ``` bash
170+ uv run python examples/zarr_integration/zarr_cast_value.py
171+ uv run python examples/benchmarks/bench_numpy_vs_rust.py
94172```
95173
96- # who
174+ ## Who
97175
98176Davis Bennett (@d-v-b )
0 commit comments