> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encord.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Objects.events

#### EventKind

What a stored entry in an event-based label row asserts from its frame onward.

An event-based row (a continuous scene, see :attr:`~encord.objects.LabelRowV2.is_event_based`) stores sparse
events at nanosecond offsets rather than labels on a frame grid:

* `"upsert"`: the object exists with this geometry until its next event. An untagged entry reads as an upsert.
* `"delete"`: the object does not exist until a later upsert. Carries placeholder geometry nobody reads.

## LabelUpsertEvent Objects

```python theme={"dark"}
@dataclass(frozen=True)
class LabelUpsertEvent(_LabelEventBase)
```

The object exists with this geometry from `frame` until its next event.

## LabelDeleteEvent Objects

```python theme={"dark"}
@dataclass(frozen=True)
class LabelDeleteEvent(_LabelEventBase)
```

The object does not exist from `frame` until a later upsert.

A delete carries no geometry, there are no `coordinates` to read.

#### LabelEvent

One stored event: narrow on `kind`, or with `isinstance`, to reach an upsert's `coordinates`.

#### resolve\_event\_at

```python theme={"dark"}
def resolve_event_at(events: Sequence[LabelEvent],
                     frame: int) -> Optional[LabelEvent]
```

The event holding over `frame`, or None where the object does not exist.

**Arguments**:

* `events` - The object's events sorted by frame ascending.
* `frame` - The frame to resolve.

**Returns**:

The last upsert at or before `frame`, unless the last event at or before `frame` is a delete.

#### check\_events\_terminated

```python theme={"dark"}
def check_events_terminated(events: Sequence[LabelEvent],
                            *,
                            object_hash: Optional[str] = None) -> None
```

Raise unless every stretch the events open is closed by a delete.

A trailing upsert is a dangling stretch: the object is present from it with no end. The editor never writes
one — an object running to the end of the timeline is closed on the frame after it — so it is not a layout
the SDK stores or loads. Half-built objects are allowed to dangle in memory while a caller assembles them;
this is checked at the two points where the row meets stored labels, parsing them and writing them back out.

**Arguments**:

* `events` - The object's stored events, sorted by frame ascending.
* `object_hash` - The object the events belong to, named in the error.

**Raises**:

* `LabelRowError` - If the events end on an upsert.

#### event\_ranges

```python theme={"dark"}
def event_ranges(events: Sequence[LabelEvent]) -> Ranges
```

The closed ranges an object is present over.

Each upsert following absence opens a range; the next delete closes it on the frame before itself. Every
range is closed: an object that runs to the end of the timeline is terminated by a delete on the frame
after it.

**Arguments**:

* `events` - The object's events sorted by frame ascending.

**Raises**:

* `LabelRowError` - If the events end on an upsert, leaving a range with no closing delete.

#### events\_intersect

```python theme={"dark"}
def events_intersect(events: Sequence[LabelEvent], start: int,
                     end: int) -> bool
```

Whether the object is present anywhere in `[start, end]` (both inclusive).

**Arguments**:

* `events` - The object's events sorted by frame ascending.
* `start` - First frame of the window.
* `end` - Last frame of the window.

**Raises**:

* `LabelRowError` - If the events end on an upsert, leaving a range with no closing delete.

#### prune\_dangling\_deletes

```python theme={"dark"}
def prune_dangling_deletes(events: Sequence[LabelEvent]) -> List[int]
```

Frames of delete events that terminate nothing.

A delete is dangling when it is the first event or directly follows another delete.

**Arguments**:

* `events` - The object's events sorted by frame ascending.
