Interval Operations

The Interval class provides several operations to manipulate and combine interval objects.

First, let’s create some simple intervals:

from temporaldata import Interval
import numpy as np

# Create two intervals: [1, 8] and [12, 18]
interval1 = Interval(start=np.array([1., 12.]),end=np.array([8., 18.]))

# Create three intervals: [2, 5], [7, 10], and [14, 17]
interval2 = Interval(start=np.array([2., 7., 14.]), end=np.array([5., 10., 17.]))

Typically for most operations that involve multiple Interval objects, each Interval object must be disjoint and sorted.

You can check these conditions using:

interval.is_disjoint()  # Returns True if intervals don't overlap
interval.is_sorted()    # Returns True if intervals are sorted by start time

Intersection

The intersection operation (&) returns a new Interval containing only the overlapping time periods between two Interval objects.

Visualization of interval intersection operation
# Compute intersection
intersection = interval1 & interval2

# Result will contain [2, 5], [7, 8] and [14, 17] as these are the overlapping periods
print(intersection.start)  # [2., 7., 14.]
print(intersection.end)    # [5., 8., 17.]

Union

The union operation (|) returns a new Interval containing the union of all intervals in both objects.

Visualization of interval union operation
# Compute union
union = interval1 | interval2

# Result will contain [1, 10] and [12, 18]
print(union.start)  # [ 1., 12.]
print(union.end)    # [10., 18.]

Difference

The difference operation (.difference()) returns a new Interval containing time periods that are in the first interval but not in the second interval.

Visualization of interval difference operation
# Compute difference
difference = interval1.difference(interval2)

# Results in intervals: [1, 2], [5, 7], [12, 14], and [17, 18]
print(difference.start)  # [1., 5., 12., 17.]
print(difference.end)    # [2., 7., 14., 18.]

Dilation

The dilation operation (.dilate()) expands each interval by a specified amount on both sides. This is useful for creating buffer periods around intervals or merging nearby intervals.

Visualization of interval dilation operation
# Create three intervals: [1, 5], [10, 13.5], and [14, 18]
interval = Interval(start=np.array([1.0, 10.0, 14.0]), end=np.array([5.0, 13.5, 18.]))

# Dilate by 0.5 on each side
dilated = interval.dilate(0.5)

# Results in intervals: [0.5, 5.5], [9.5, 13.75], and [13.75, 18.5]
print(dilated.start)  # [0.5 , 9.5 , 13.75]
print(dilated.end)    # [5.5 ,13.75, 18.5 ]

The dilation operation is particularly useful when you need to:

  • Create buffer periods around events

  • Account for uncertainty in interval boundaries

  • Merge intervals that are close together

Coalescing

The coalesce operation (.coalesce()) merges overlapping or touching intervals into single continuous intervals. This is useful for simplifying interval sets and removing gaps below a certain threshold.

Visualization of interval coalesce operation
# Create four intervals [1, 6], [6.1, 11], [11.3, 14.5], and [14.5, 17.8]
interval = Interval(
    start=np.array([1., 6.1, 11.3, 14.5]), end=np.array([6., 11., 14.5, 17.8])
)


# Coalesce intervals that are within 0.2 of each other
coalesced = interval.coalesce(0.2)

# [6-6.1] and [14.5-14.5] merged, [11-11.3] unchanged
print(coalesced.start)  # [ 1., 11.3]
print(coalesced.end)    # [11., 17.8]

The coalesce operation is useful for:

  • Cleaning up noisy interval data

  • Merging intervals that are effectively continuous

  • Simplifying interval representations

You can combine coalesce with dilate to merge intervals within a certain distance:

# Create two intervals [1, 2.5], and [3, 4]
interval = Interval(start=np.array([1., 3.]), end=np.array([2.5, 4.]))

# Merge intervals within distance 0.5
merged = interval.dilate(0.5).coalesce()

print(merged.start)  # [0.5]
print(merged.end)    # [4.5]

There are multiple edge cases that can occur when performing interval operations. For more details, see Interval Operations - Edge Cases.