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.