EventData(table, unit, number_type=NumberType.float)
PyArrow-based storage for timeline events.
EventData wraps a PyArrow table containing events. Events are rows in the table, not Python wrapper objects. The primary API is bulk operations:
from_dicts(): Create from list of row dictionaries
from_arrays(): Create from field-oriented arrays
from_dataframe(): Create from pandas DataFrame
The schema is fixed at class definition time but can be extended by subclasses to add domain-specific fields (e.g., pitch, velocity for notes).
NOTE: This class was renamed from EventStore to EventData in the 2026-01 API refactoring. EventStore now refers to the container class (formerly EventBundle) that holds one or more EventData tables.
Return a column’s values as plain, decoded Python objects.
A rational-shaped column – any struct column carrying a value sub-field, such as the canonical {value, numerator, denominator} coordinate struct used by start, end, duration, and any extra field sharing that shape – decodes to an exact Fraction via struct_to_rational. When a row’s struct carries no exact ratio (missing or non-integral numerator/denominator), the float value member is used instead, wrapped in a Fraction. Every other column type is returned via to_pylist() unchanged, including None for a null cell – default only substitutes for a null rational-shaped struct or a column absent from this table entirely.
Parameters
Name
Type
Description
Default
name
str
Field name in the underlying table.
required
default
Any
Value substituted for every row when name is not a column of this table, and for individual null rational struct cells.
None
Returns
Name
Type
Description
list[Any]
A list of per-row values, one for each event.
concat
EventData.concat(*others)
Concatenate with other EventData, returning a new EventData.
Parameters
Name
Type
Description
Default
*others
'EventData'
Other EventData to concatenate (extra fields are allowed and will be merged using schema promotion).
()
Returns
Name
Type
Description
'EventData'
A new EventData containing all events.
Raises
Name
Type
Description
ValueError
If any units don’t match.
coordinate_range
EventData.coordinate_range()
Get the min and max coordinates across all events.
Returns
Name
Type
Description
tuple[float | Fraction, float | Fraction] | None
Tuple of (min, max) coordinates, or None if store is empty.
tuple[float | Fraction, float | Fraction] | None
Returns Fraction values when number_type is fraction.
count_by
EventData.count_by(field)
Count events grouped by a field’s values.
Parameters
Name
Type
Description
Default
field
str
The field to group by.
required
Returns
Name
Type
Description
dict[str, int]
Dict mapping field values to counts.
create_timeline
EventData.create_timeline(uid=None, filters=None)
Create a Timeline from this EventData.
This is a convenience method that creates a timeline with the data’s events directly. The timeline class and number_type are inferred from the data’s unit (e.g., ticks -> DiscreteLogicalTimeline with int).
Parameters
Name
Type
Description
Default
uid
str | None
Unique ID for the timeline. Auto-generated if None.
None
filters
dict[str, Any] | None
Filter kwargs to apply before timeline creation. Example: {“event_type”: “Note”} to exclude rests.
Filter events by criteria, returning a new EventData.
All criteria are AND-ed together.
Parameters
Name
Type
Description
Default
temporal_type
Literal['instant', 'interval'] | None
Filter by “instant” or “interval”.
None
event_type
str | None
Filter by event type name.
None
min_coord
CoordinateSpec | None
Minimum coordinate (inclusive), optionally with a unit.
None
max_coord
CoordinateSpec | None
Maximum coordinate (exclusive), optionally with a unit.
None
**kwargs
Any
Exact match filters for other fields (e.g. event_category=“note”).
{}
Coordinate bounds are compared against the stored float coordinate representation. Fraction bounds are converted to float for this comparison; integer and float bounds retain their respective types. The minimum remains inclusive and the maximum remains exclusive.
Returns
Name
Type
Description
'EventData'
A new EventData with filtered events.
from_arrays
EventData.from_arrays( fields, unit, number_type=NumberType.float,*, validate=True, extra_fields=None, interval_policy=IntervalPolicy.warn,)
Create EventData from field-oriented arrays (VECTORIZED).
This is the PRIMARY construction method for loaders. All operations are vectorized - NO row iteration occurs.
Missing end or duration values are computed automatically from the other (end = start + duration or duration = end - start). Behaviour when both are present but inconsistent is controlled by interval_policy.
Parameters
Name
Type
Description
Default
fields
dict[str, np.ndarray | pa.Array | list[Any]]
Dict mapping field names to arrays. Supports: - np.ndarray: NumPy arrays - pa.Array: PyArrow arrays (including StructArray for coords) - list: Python lists (converted to numpy) For coordinate fields (start, end, duration): - If pa.StructArray: used directly - If numeric/string array: parsed via CoordinateParser
required
unit
TimeUnit
The time unit for coordinates.
required
number_type
NumberType
The number type for coordinates.
NumberType.float
validate
bool
Whether to validate arrays before table construction.
True
extra_fields
list[pa.Field] | None
Optional list of PyArrow fields for extra data. These fields include metadata (e.g., unit for CoordinateFields). If not provided, fields are inferred from the data arrays.
None
interval_policy
IntervalPolicy
How to handle end/duration inconsistencies. See IntervalPolicy for options.
IntervalPolicy.warn
Returns
Name
Type
Description
Self
A new EventData containing the events.
Raises
Name
Type
Description
ValueError
If validation fails (missing fields, length mismatch, etc.)
Examples
>>># Vectorized construction from arrays>>> data = EventData.from_arrays({... "id": np.array(["e1", "e2"]),... "temporal_type": np.array(["instant", "instant"]),... "event_type": np.array(["Beat", "Beat"]),... "start": CoordinateParser.parse([0, 480], NumberType.int, unit),... }, unit=TimeUnit.ticks)
>>># Direct from loader output (StructArrays already parsed)>>> data = EventData.from_arrays(loader_fields, unit=TimeUnit.quarters)
from_dataframe
EventData.from_dataframe(df, unit, number_type=NumberType.float)
Create EventData from a pandas DataFrame.
Parameters
Name
Type
Description
Default
df
pd.DataFrame
DataFrame with event data. Field names should match the schema.
required
unit
TimeUnit
The time unit for coordinates.
required
number_type
NumberType
The number type for coordinates.
NumberType.float
Returns
Name
Type
Description
Self
A new EventData containing the events.
from_dicts
EventData.from_dicts( rows, unit, number_type=NumberType.float,*, interval_policy=IntervalPolicy.warn,)
Create EventData from a list of row dictionaries.
Coordinate values (instant, start, end, duration) are automatically converted to the internal struct format. Convenience defaults are applied so that callers can omit boilerplate fields:
id: Auto-generated as {event_type}:{counter} if missing, e.g. note:000001, rest:000001, beat:000001. When events are placed on a timeline, the timeline’s ID is prepended, yielding e.g. clt:1:note:000001.
temporal_type: Inferred from the keys present in the dict – "interval" when bothstart and end (or duration) are given, "instant" otherwise.
Missing end or duration values are computed automatically from the other (end = start + duration or duration = end - start). Behaviour when both are present but inconsistent is controlled by interval_policy.
Parameters
Name
Type
Description
Default
rows
list[dict[str, Any]]
List of event dictionaries. At minimum each dict needs a coordinate (instantorstart/end) and an event_type. All other fields have sensible defaults.
required
unit
TimeUnit
The time unit for coordinates.
required
number_type
NumberType
The number type for coordinates.
NumberType.float
interval_policy
IntervalPolicy
How to handle end/duration inconsistencies. See IntervalPolicy for options.
Get the canonical PyArrow schema for this EventData class.
This is a class-level method that returns the schema for a given unit, independent of any specific instance. Useful for constructing empty tables or validating incoming data.
Parameters
Name
Type
Description
Default
unit
TimeUnit
The time unit for coordinate fields.
required
number_type
NumberType | None
The number type for coordinate fields.
None
Returns
Name
Type
Description
pa.Schema
The complete schema including base and extra fields.
head
EventData.head(n=5)
Return the first n events as a pandas DataFrame.
A pandas-style preview of the stored rows. Coordinate columns render as their native numbers — the same conversion :meth:to_dataframe applies — so events.head() shows the leading events directly, without reaching for the raw PyArrow table.
Parameters
Name
Type
Description
Default
n
int
Number of leading events to include. Values larger than the event count return every event; n <= 0 returns an empty frame.
5
Returns
Name
Type
Description
pd.DataFrame
A pandas DataFrame of the first n events.
Examples
>>> events.head() # first five events>>> events.head(3) # first three events
prefix_ids
EventData.prefix_ids(prefix)
Return a new EventData with all event IDs prefixed.
Prepends prefix: to every event ID. Used when events are placed onto a timeline so that IDs become globally unique and informative, e.g. clt1:note:000001.
If the IDs already start with the prefix, they are left unchanged.
Parameters
Name
Type
Description
Default
prefix
str
The prefix to prepend (without trailing colon).
required
Returns
Name
Type
Description
'EventData'
A new EventData with prefixed IDs.
select
EventData.select(fields)
Select specific fields from the table.
Parameters
Name
Type
Description
Default
fields
list[str]
List of field names to select.
required
Returns
Name
Type
Description
pa.Table
A PyArrow table with only the selected fields.
summary
EventData.summary()
Get a comprehensive summary of the store.
Returns
Name
Type
Description
dict[str, Any]
Dict with count, temporal type counts, event type counts,