MatchClaimField
alignment.MatchClaimField(
raw=None,
*,
source_fields=None,
name=None,
metadata=None,
)A SemanticField[MatchClaim] columnar store for pairwise claims.
MatchClaimField is the Field paired with the :class:MatchClaim scalar. It holds a large set of synchronous-instant pairwise alignment claims (millions of rows) in a single derived struct column instead of one frozen :class:MatchClaim per claim. Individual claims are materialised lazily, only when a row is indexed or iterated.
Like every paired Field, its struct schema is derived from the scalar by :func:~timetoalign.core.fields.derive_arrow_struct — so the inner column type is exactly MatchClaimField.pa_schema. Shared provenance is held once at field level as a single :class:MatchMetadata (or None) and injected on read, mirroring how :class:~timetoalign.core.time.CoordinateField carries its unit outside the data: the struct column’s metadata sub-field is left null in bulk, and :meth:__getitem__ injects the field-level metadata into each materialised :class:MatchClaim. This keeps the store compact (one struct column, no per-row metadata) while remaining a genuine SemanticField.
Scope (v1): synchronous instant pairwise claims only. Every row represents a claim where is_synchronous is True, start_anchor is present, and end_anchor is None (an instant). NOMATCH claims (non-synchronous) and interval claims (with an end anchor) are out of scope for this store; :meth:from_claims raises :class:ValueError when handed one.
Attributes
| Name | Type | Description |
|---|---|---|
| table | pa.Table |
The backing single-column :class:pyarrow.Table (read-only property) whose one column is the derived MatchClaim struct. |
| metadata | MatchMetadata | None | Shared :class:MatchMetadata (or None) applied to every materialised claim. |
Examples
>>> agent = Agent(name="dtw", type=AgentType.software, identifier="v1")
>>> meta = MatchMetadata(agent=agent)
>>> field = MatchClaimField.from_columns(
... timeline_a_ids=["A", "A", "B"],
... timeline_b_ids=["B", "C", "C"],
... coordinate_a=[0.0, 0.0, 1.0],
... coordinate_b=[10.0, 20.0, 21.0],
... unit_a=TimeUnit.quarters,
... unit_b=TimeUnit.seconds,
... metadata=meta,
... )
>>> len(field)
3
>>> field[0].timeline_a_id, field[0].timeline_b_id
('A', 'B')Methods
| Name | Description |
|---|---|
| at | Return the claims anchored at (timeline_id, coordinate). |
| connecting | Return the claims that involve timeline_id on either side. |
| connects_groups | Whether any claim spans the two given sets of timeline ids. |
| coordinate_pairs | Read the four defining columns in bulk, materialising no claim. |
| filter | Return a filtered view following the unified filter API. |
| from_claims | Build a field from existing :class:MatchClaim objects. |
| from_columns | Build a field directly from parallel columns (the vectorized path). |
| from_dict | Deserialize a field from a plain dictionary. |
| max_coordinate | The largest coordinate this field carries for timeline_id. |
| to_claims | Materialise every row into a list of :class:MatchClaim objects. |
| to_dict | Serialize to a plain dictionary (inverse of :meth:from_dict). |
at
alignment.MatchClaimField.at(timeline_id, coordinate)Return the claims anchored at (timeline_id, coordinate).
The selection is a vectorized PyArrow boolean mask over the struct column — rows where timeline_a_id == timeline_id and the anchor’s coordinate_a equals coordinate, OR the symmetric timeline_b_id / coordinate_b pair. No claim is materialised and the rest of the field is never touched; the shared metadata carries over.
Coordinate matching is exact float equality — a query coordinate must land on a value the field actually carries. There is no tolerance and no nearest-value fallback, so the result agrees with a per-claim scan of the same claims.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| timeline_id | str |
The timeline the queried coordinate lives on. | required |
| coordinate | float |
The exact coordinate value on that timeline. | required |
Returns
| Name | Type | Description |
|---|---|---|
| 'MatchClaimField' | A new :class:MatchClaimField holding only the matching rows |
|
| 'MatchClaimField' | (possibly empty). |
connecting
alignment.MatchClaimField.connecting(timeline_id)Return the claims that involve timeline_id on either side.
The filter is a vectorized boolean mask over the struct’s id sub-fields; no claim is materialised. The shared metadata carries over.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| timeline_id | str |
The exact timeline id to match against either column. | required |
Returns
| Name | Type | Description |
|---|---|---|
| 'MatchClaimField' | A new :class:MatchClaimField holding only the matching rows. |
connects_groups
alignment.MatchClaimField.connects_groups(group_a_ids, group_b_ids)Whether any claim spans the two given sets of timeline ids.
True when at least one row has one side in group_a_ids and the other side in group_b_ids. The test is a vectorized mask reduced with :func:pyarrow.compute.any; no claim is materialised, so it answers commensurability over a million-row field in one pass.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| group_a_ids | set[str] |
Timeline ids on one side. | required |
| group_b_ids | set[str] |
Timeline ids on the other side. | required |
Returns
| Name | Type | Description |
|---|---|---|
bool |
True if some claim connects the two sets. |
coordinate_pairs
alignment.MatchClaimField.coordinate_pairs()Read the four defining columns in bulk, materialising no claim.
This is the read a tabular consumer wants: the two timeline ids and the two anchor coordinates of every row, as four parallel Python lists pulled straight off the Arrow columns. Materialising the rows as :class:MatchClaim objects instead costs orders of magnitude more for the same information.
Returns
| Name | Type | Description |
|---|---|---|
list[str] |
(timeline_a_ids, timeline_b_ids, coordinates_a, coordinates_b), |
|
list[str] |
all of length len(self). |
filter
alignment.MatchClaimField.filter(
timeline_id=None,
timeline_ids=None,
id_pattern=None,
between=None,
within=None,
synchronous_only=False,
nomatch_only=False,
)Return a filtered view following the unified filter API.
Every criterion is a vectorized boolean mask over the struct column; no claim is materialised and the shared metadata carries over. All non-default criteria are combined with logical AND.
include_domains / include_units are deliberately absent: they need per-timeline metadata (domain, unit) that this store does not hold. A caller that owns that metadata — an :class:~timetoalign.alignment.bundle.AlignmentBundle, say — resolves them into the set of timeline ids that pass and hands that set to within.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| timeline_id | str | None |
Keep rows involving this exact id on either side (equivalent to :meth:connecting). |
None |
| timeline_ids | set[str] | None |
Keep rows involving any id in this set on either side. | None |
| id_pattern | str | None |
Keep rows involving any id matching this regex (re.search against the field’s :attr:timeline_ids). |
None |
| between | tuple[str, str] | None |
Keep rows connecting exactly these two ids (order-independent). | None |
| within | set[str] | None |
Keep rows whose both ids are in this set. This is the primitive behind domain- and unit-restricted queries. | None |
| synchronous_only | bool |
A no-op — every row in this store is a synchronous claim by class invariant. | False |
| nomatch_only | bool |
Returns an empty field, for the same reason. | False |
Returns
| Name | Type | Description |
|---|---|---|
| 'MatchClaimField' | A new :class:MatchClaimField. With no criteria set, a copy of |
|
| 'MatchClaimField' | the whole field is returned. |
Raises
| Name | Type | Description |
|---|---|---|
ValueError |
If synchronous_only and nomatch_only are both set. |
from_claims
alignment.MatchClaimField.from_claims(claims, *, metadata=None)Build a field from existing :class:MatchClaim objects.
Every claim must be a synchronous instant (is_synchronous is True, start_anchor present, end_anchor is None) per the v1 scope.
If metadata is None and all claims share one identical :class:MatchMetadata (by equality), that metadata is adopted as the field-level provenance; otherwise the field’s metadata stays None (no per-row metadata is ever stored).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| claims | list[MatchClaim] |
The claims to store. Coordinates are pulled from each claim’s start_anchor. |
required |
| metadata | MatchMetadata | None | Explicit field-level provenance. When provided it overrides any per-claim metadata inference. | None |
Returns
| Name | Type | Description |
|---|---|---|
| 'MatchClaimField' | A new :class:MatchClaimField. |
Raises
| Name | Type | Description |
|---|---|---|
ValueError |
If any claim is non-synchronous (NOMATCH), lacks a start anchor, or is an interval (carries an end anchor). |
from_columns
alignment.MatchClaimField.from_columns(
timeline_a_ids,
timeline_b_ids,
coordinate_a,
coordinate_b,
*,
unit_a,
unit_b,
metadata=None,
)Build a field directly from parallel columns (the vectorized path).
This is the constructor a bulk producer (e.g. an alignment loader) uses. It assembles the derived MatchClaim struct column straight from the parallel inputs with :meth:pyarrow.StructArray.from_arrays and never materialises a single :class:MatchClaim Python object, so it scales to millions of rows.
Each row is a synchronous instant claim: timeline_a_id / timeline_b_id and the start_anchor sub-struct are filled from the inputs; is_synchronous and is_explicit are True; end_anchor / event ids / names / source_coordinate / metadata / source_claim_id / id are left null (the shared metadata is injected on read, the id is generated on materialise).
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| timeline_a_ids | Sequence[str] | pa.Array | pa.ChunkedArray |
Timeline-A ids, one per claim. | required |
| timeline_b_ids | Sequence[str] | pa.Array | pa.ChunkedArray |
Timeline-B ids, one per claim. | required |
| coordinate_a | Sequence[int | float | Fraction] | pa.Array | pa.ChunkedArray |
Coordinate value on timeline A, one per claim. | required |
| coordinate_b | Sequence[int | float | Fraction] | pa.Array | pa.ChunkedArray |
Coordinate value on timeline B, one per claim. | required |
| unit_a | TimeUnit | str |
Unit applied to every coordinate on timeline A. | required |
| unit_b | TimeUnit | str |
Unit applied to every coordinate on timeline B. | required |
| metadata | MatchMetadata | None | Shared provenance for every claim in the field. | None |
Returns
| Name | Type | Description |
|---|---|---|
| 'MatchClaimField' | A new :class:MatchClaimField. |
Raises
| Name | Type | Description |
|---|---|---|
ValueError |
If the four inputs do not all have the same length. |
from_dict
alignment.MatchClaimField.from_dict(data)Deserialize a field from a plain dictionary.
Inverse of :meth:to_dict.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| data | dict[str, Any] |
A mapping with the four column lists and an optional metadata dict. |
required |
Returns
| Name | Type | Description |
|---|---|---|
| 'MatchClaimField' | A new :class:MatchClaimField. |
max_coordinate
alignment.MatchClaimField.max_coordinate(timeline_id)The largest coordinate this field carries for timeline_id.
Both anchor sides are scanned vectorized with :func:pyarrow.compute.max; no claim is materialised.
Parameters
| Name | Type | Description | Default |
|---|---|---|---|
| timeline_id | str |
The timeline to look up. | required |
Returns
| Name | Type | Description |
|---|---|---|
float | None |
The maximum coordinate value carried for that timeline, or | |
float | None |
None if the timeline does not appear in this field. |
to_claims
alignment.MatchClaimField.to_claims()Materialise every row into a list of :class:MatchClaim objects.
This is O(n) and defeats the columnar purpose for large sets; it is provided for convenience and round-tripping, not for hot paths.
Returns
| Name | Type | Description |
|---|---|---|
list[MatchClaim] |
A list of synchronous instant claims, one per row. |
to_dict
alignment.MatchClaimField.to_dict()Serialize to a plain dictionary (inverse of :meth:from_dict).
The id and coordinate columns are emitted as plain Python lists (read directly from the struct sub-fields); the metadata is emitted via :meth:MatchMetadata.to_dict (or None).
Returns
| Name | Type | Description |
|---|---|---|
dict[str, Any] |
A round-trippable mapping. |