fletchr-measurand
Arrow-native bit-fragment extraction and engineering-unit decoding for
binary protocol data. Parses parameter and measurand spec strings into
evaluable objects; runs them against pa.Tables whose data columns are
fletchr.uintn
extension arrays.
Why?
Bit-packed protocol data routinely needs two things:
- Bit-fragment extraction — "this value is word 3 concatenated with word 4 as a 16-bit value." Done by hand, it's masking and shifting; done at scale, it's bugs.
- Engineering-unit decoding — "raw × 0.1 + (-273.15)" for a scaled measurement.
fletchr-measurand makes both declarative. Parameter("[1+2]") extracts
word 1 concatenated with word 2; Measurand(parameter=..., encoding="2c", euc=EUC(...)) adds decoding (two's complement, float, etc.) and scaling.
Features
- Parameter DSL —
[1](single word),[1+2](multi-word, MSB first),[1-3](range),[1+3+5](non-contiguous concatenation); plus generator / iteration patterns for repeated bit-fragments at successive column offsets. - Level 1 encodings via byteforge — unsigned, sign-magnitude, one's-complement, two's-complement, offset-binary, IEEE 754 (32/64), MIL-STD-1750A (32/48), packed BCD, Gray code, IBM/DEC/TI floats.
- Level 2 EUC — linear scaling (
scale_factor,data_bias,scaled_bias) and arbitrary callable transforms. - Arrow-native build chain —
Parameter.buildandMeasurand.buildconsumepa.Tabledirectly and returnpa.ExtensionArray/MeasurandResult. Validity bitmaps propagate through both decode levels. - Field-metadata convention — the
fletchr.encoding/fletchr.scale_factor/fletchr.data_bias/fletchr.scaled_biaskeys defined in SPEC-decode.md give a language-neutral wire format for decode rules attached to Arrow column metadata.
Install
uv add fletchr-measurand # or: pip install fletchr-measurand
Requires Python 3.9+. Pulls in fletchr-uintn, pyarrow >= 16,
numpy >= 2.0, byteforge, lark, and antlr4-python3-runtime.
Quickstart
import pyarrow as pa
from fletchr_uintn import uintn_array
from fletchr_measurand import EUC, Measurand, parameter_parser
# A FrameArray-shaped pa.Table: one column per word position (c1..cN,
# 1-based), each a fletchr.uintn column. Real users get this from
# fletchr-core's FrameArray; constructed manually here for illustration.
table = pa.table({
"c1": uintn_array([0x12, 0x34, 0x56], bits=8),
"c2": uintn_array([0xFF, 0x80, 0x00], bits=8),
"c3": uintn_array([0x10, 0x20, 0x30], bits=8),
})
# Parameter spec is 1-based: [2] selects word 2 (column c2). Decode it as
# signed two's-complement, then linear-scale to Celsius from a centikelvin
# raw representation.
m = Measurand(
parameter=parameter_parser.parse("[2]"),
encoding="2c",
euc=EUC(scale_factor=0.1, scaled_bias=-273.15),
)
result = m.build(table)
result.dns.to_pylist() # [255, 128, 0] — raw 8-bit DNs
result.decoded.to_pylist() # [-1, -128, 0] — Level 1: two's-complement
result.values.to_pylist() # [-273.25, -285.95, -273.15] — Level 2: scale + bias
Multi-word values use + to concatenate, MSB first:
# Words 2 and 3 as a single 16-bit unsigned value (c2 high, c3 low).
m16 = Measurand(parameter=parameter_parser.parse("[2+3]"))
m16.build(table).values.to_pylist() # [65296, 32800, 48]
Range direction matters for words but not for bits: a
descending word range reverses word order ([3-1] reads c3, c2, c1),
while a descending bit range is identical to its ascending form
([1:8-5] ≡ [1:5-8] — bit positions name which bits to extract,
1-based with bit 1 the LSB, not the order to lay them out). To reverse
bit order, use the R flag ([1R], [1:5-8R]).
See SPEC-decode.md for the full encoding registry and the field-metadata convention.
Public API
from fletchr_measurand import (
# Parameter / Measurand DSL
Parameter, ParameterSpec, parameter_parser,
Measurand, MeasurandSpec, measurand_parser,
resolve_parameter, resolve_measurand,
# Result + Level 2 transform
MeasurandResult,
EUC, SamplingStrategy,
# Calculator parser (for the SPEC's expression-mode hook)
calculator_parser,
)
Status
The runtime data model (Parameter, Measurand, MeasurandResult,
EUC) is stable. The wire-format convention in SPEC-decode.md is
draft v0.6 — the encoding registry is locked, but one open question
remains (the expression-mode allow-list) before incrementing to v1.0.
Field-metadata read/write helpers that round-trip the SPEC keys onto
pa.Field.metadata are tracked as future work.
Links
- Source: https://github.com/fletchr-labs/fletchr
- Issues: https://github.com/fletchr-labs/fletchr/issues
- Decode metadata spec: SPEC-decode.md
License
MIT.
Metadata
Release files for fletchr-measurand 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| fletchr_measurand-0.3.1.tar.gz | 93.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fletchr_measurand-0.3.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 168.9 kB
Release files / fletchr_measurand-0.3.1.tar.gz
| Download URL | fletchr_measurand-0.3.1.tar.gz |
|---|---|
| Size | 93.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5e1601352aa4e3eda624cbbbfaac101963b9852b05b9b92f9fcf58117ff99c02
|
|
BLAKE2b-256 checksum How to use checksums |
3c88b24fff45acdee2548f8cacce0e52bf08185cb3cef66a7a5d258b3c41c18b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / fletchr_measurand-0.3.1-py3-none-any.whl
| Download URL | fletchr_measurand-0.3.1-py3-none-any.whl |
|---|---|
| Size | 75.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
cd382cb4b572347ce0b6d9878173db416821020c535636832d6f93d9e8223895
|
|
BLAKE2b-256 checksum How to use checksums |
e80413c4dd0d6a24fe399dbe7dea73667db6f97c556b40d6b88b92aa13c410a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.13 {"installer":{"name":"uv","version":"0.12.13","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|