CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-intervaltree

A mutable, self-balancing interval tree data structure that enables efficient querying of intervals by point, range overlap, or range envelopment

Pending
Overview
Eval results
Files

bulk-operations.mddocs/

Bulk Operations

Advanced operations for batch processing, interval manipulation, and tree restructuring. These operations enable efficient modification of multiple intervals simultaneously and provide powerful tools for interval-based data processing.

Capabilities

Bulk Removal Operations

Remove multiple intervals based on overlap criteria.

def remove_overlap(self, begin, end=None):
    """
    Remove all intervals overlapping with point or range.
    
    Parameters:
    - begin: Point, range start, or Interval object
    - end: Range end (optional if begin is Interval or point query)
    
    Time Complexity: O((r+m)*log n) where r is removed count, m is result size
    """

def remove_envelop(self, begin, end):
    """
    Remove all intervals completely contained within range.
    
    Parameters:
    - begin: Range start
    - end: Range end
    
    Time Complexity: O((r+m)*log n) where r is removed count, m is result size
    """

Interval Modification Operations

Modify intervals by chopping, slicing, and splitting.

def chop(self, begin, end, datafunc=None):
    """
    Remove portion [begin, end) from all intervals, splitting as needed.
    
    Parameters:
    - begin: Start of region to remove
    - end: End of region to remove  
    - datafunc: Optional function to modify data of split intervals
                Signature: datafunc(interval, is_left_part) -> new_data
    
    Intervals overlapping [begin, end) are modified:
    - Completely contained intervals are removed
    - Partially overlapping intervals are trimmed or split
    """

def slice(self, point, datafunc=None):
    """
    Split all intervals crossing point into two intervals.
    
    Parameters:
    - point: Point at which to split intervals
    - datafunc: Optional function to modify data of split intervals
                Signature: datafunc(interval, is_left_part) -> new_data
    
    Each interval containing point becomes two intervals:
    - Left part: [original_begin, point)
    - Right part: [point, original_end)
    """

Overlap Processing Operations

Detect and resolve overlapping intervals.

def split_overlaps(self):
    """
    Split all overlapping intervals at their boundary points.
    
    After this operation, no two intervals will overlap - they will
    either be disjoint or share exact boundaries.
    
    Time Complexity: O(n²*log n) worst case, O(n*log n) best case
    """

def merge_overlaps(self, data_reducer=None, data_initializer=None, strict=True):
    """
    Merge all overlapping intervals into single intervals.
    
    Parameters:
    - data_reducer: Function to combine data from merged intervals
                   Signature: data_reducer(current_data, new_data) -> combined_data
    - data_initializer: Function to initialize data for merged intervals
                       Signature: data_initializer(intervals_list) -> initial_data
    - strict: If True, merge only overlapping intervals
             If False, also merge adjacent intervals
    
    Time Complexity: O(n*log n)
    """

def merge_equals(self, data_reducer=None, data_initializer=None):
    """
    Merge intervals with identical ranges (same begin and end).
    
    Parameters:
    - data_reducer: Function to combine data from merged intervals
    - data_initializer: Function to initialize data for merged intervals
    
    Time Complexity: O(n*log n)
    """

Analysis Operations

Find complex interval relationships.

def find_nested(self):
    """
    Find nested interval relationships.
    
    Returns:
    dict: Mapping of parent intervals to sets of nested child intervals
          {parent_interval: {child1, child2, ...}, ...}
    
    Time Complexity: O(n²)
    """

Usage Examples

Bulk Removal

from intervaltree import Interval, IntervalTree

# Create tree with overlapping intervals
tree = IntervalTree([
    Interval(0, 10, "a"),
    Interval(5, 15, "b"),
    Interval(12, 18, "c"),
    Interval(20, 30, "d"),
    Interval(25, 35, "e")
])

print(f"Initial tree: {len(tree)} intervals")

# Remove all intervals that overlap with range [8, 22)
tree.remove_overlap(8, 22)
print(f"After remove_overlap(8, 22): {len(tree)} intervals")
# Removes intervals a, b, c, d (all overlap with [8, 22))
# Remaining: interval e (25, 35)

# Reset tree
tree = IntervalTree([
    Interval(0, 10, "a"),
    Interval(5, 15, "b"), 
    Interval(12, 18, "c"),
    Interval(20, 30, "d")
])

# Remove only intervals completely contained within [6, 25)
tree.remove_envelop(6, 25)
print(f"After remove_envelop(6, 25): {len(tree)} intervals")
# Removes intervals c, d (completely within [6, 25))
# Remaining: intervals a, b (partially overlap but not completely contained)

Chopping and Slicing

from intervaltree import Interval, IntervalTree

# Create tree for chopping example
tree = IntervalTree([
    Interval(0, 20, "long_interval"),
    Interval(5, 15, "middle_interval"),
    Interval(25, 35, "separate_interval")
])

# Chop out the region [8, 12) from all intervals
tree.chop(8, 12)
print(f"After chop(8, 12): {len(tree)} intervals")
# Original interval (0, 20) becomes two: (0, 8) and (12, 20)
# Interval (5, 15) becomes two: (5, 8) and (12, 15)  
# Interval (25, 35) unchanged (no overlap with [8, 12))

# Reset for slicing example
tree = IntervalTree([
    Interval(0, 20, "span_point"),
    Interval(15, 25, "also_spans"),
    Interval(30, 40, "no_span")
])

# Split all intervals that cross point 18
tree.slice(18)
print(f"After slice(18): {len(tree)} intervals")
# Interval (0, 20) becomes: (0, 18) and (18, 20)
# Interval (15, 25) becomes: (15, 18) and (18, 25)
# Interval (30, 40) unchanged (doesn't contain point 18)

Data Modification During Operations

from intervaltree import Interval, IntervalTree

# Example with data modification functions
def modify_chopped_data(interval, is_left_part):
    """Modify data when interval is split by chopping"""
    original_data = interval.data
    if is_left_part:
        return f"{original_data}_left"
    else:
        return f"{original_data}_right"

def modify_sliced_data(interval, is_left_part):
    """Modify data when interval is split by slicing"""
    original_data = interval.data
    part = "before" if is_left_part else "after"
    return f"{original_data}_{part}_split"

# Create tree
tree = IntervalTree([
    Interval(0, 20, "original"),
    Interval(10, 30, "another")
])

# Chop with data modification
tree.chop(8, 12, datafunc=modify_chopped_data)
# Results in intervals with modified data like "original_left", "original_right"

# Reset and slice with data modification  
tree = IntervalTree([Interval(0, 20, "data")])
tree.slice(10, datafunc=modify_sliced_data)
# Results in "data_before_split" and "data_after_split"

Merging Operations

from intervaltree import Interval, IntervalTree

# Create tree with overlapping intervals
tree = IntervalTree([
    Interval(0, 10, "a"),
    Interval(5, 15, "b"),
    Interval(12, 20, "c"),
    Interval(25, 30, "d"),
    Interval(28, 35, "e")
])

def combine_data(current, new):
    """Combine data from merged intervals"""
    return f"{current}+{new}"

def initialize_data(intervals):
    """Initialize data for merged intervals"""
    data_parts = [i.data for i in intervals]
    return "+".join(sorted(data_parts))

print(f"Before merge: {len(tree)} intervals")

# Merge overlapping intervals
tree.merge_overlaps(data_reducer=combine_data, data_initializer=initialize_data)
print(f"After merge_overlaps: {len(tree)} intervals")
# Overlapping intervals (0,10), (5,15), (12,20) become one interval (0,20)
# Overlapping intervals (25,30), (28,35) become one interval (25,35)

# Example with equal intervals
tree = IntervalTree([
    Interval(0, 10, "first"),
    Interval(0, 10, "second"),  # Same range
    Interval(0, 10, "third"),   # Same range
    Interval(15, 25, "different")
])

print(f"Before merge_equals: {len(tree)} intervals")
tree.merge_equals(data_initializer=initialize_data)
print(f"After merge_equals: {len(tree)} intervals")
# Three intervals with range (0,10) become one with combined data

Split Overlaps

from intervaltree import Interval, IntervalTree

# Create tree with complex overlaps
tree = IntervalTree([
    Interval(0, 15, "a"),
    Interval(5, 20, "b"), 
    Interval(10, 25, "c"),
    Interval(30, 40, "d")
])

print(f"Before split_overlaps: {len(tree)} intervals")
for interval in sorted(tree):
    print(f"  {interval}")

# Split all overlaps at boundary points
tree.split_overlaps()

print(f"After split_overlaps: {len(tree)} intervals")
for interval in sorted(tree):
    print(f"  {interval}")

# Result: intervals are split at points 5, 10, 15, 20 where boundaries cross
# No two intervals overlap anymore - they're either disjoint or adjacent

Finding Nested Intervals

from intervaltree import Interval, IntervalTree

# Create tree with nested structure
tree = IntervalTree([
    Interval(0, 100, "outer"),
    Interval(10, 30, "inner1"), 
    Interval(40, 60, "inner2"),
    Interval(15, 25, "nested_in_inner1"),
    Interval(70, 90, "another_inner"),
    Interval(200, 300, "separate")
])

# Find nesting relationships
nested_map = tree.find_nested()

print("Nesting relationships:")
for parent, children in nested_map.items():
    print(f"Parent {parent}:")
    for child in children:
        print(f"  -> {child}")

# Output shows:
# - "outer" contains "inner1", "inner2", "nested_in_inner1", "another_inner"  
# - "inner1" contains "nested_in_inner1"
# - "separate" has no nested intervals

Complex Bulk Processing

from intervaltree import Interval, IntervalTree

# Example: Processing time series data with gaps
data_tree = IntervalTree([
    Interval(0, 100, "sensor_data_1"),
    Interval(50, 150, "sensor_data_2"),
    Interval(120, 200, "sensor_data_3"),
    Interval(300, 400, "sensor_data_4")
])

# Step 1: Merge overlapping data segments
def combine_sensor_data(current, new):
    return f"merged({current},{new})"

print("Original data segments:", len(data_tree))
data_tree.merge_overlaps(data_reducer=combine_sensor_data)
print("After merging overlaps:", len(data_tree))

# Step 2: Remove data during maintenance window [175, 225)
maintenance_start, maintenance_end = 175, 225
print(f"Removing data during maintenance [{maintenance_start}, {maintenance_end})")
data_tree.remove_overlap(maintenance_start, maintenance_end)
print("After maintenance removal:", len(data_tree))

# Step 3: Split remaining data at analysis boundary
analysis_point = 350
print(f"Splitting data at analysis point {analysis_point}")
data_tree.slice(analysis_point)
print("Final data segments:", len(data_tree))

for interval in sorted(data_tree):
    print(f"  Data segment: {interval}")

Install with Tessl CLI

npx tessl i tessl/pypi-intervaltree

docs

bulk-operations.md

index.md

intervals.md

python-integration.md

queries.md

set-operations.md

tree-operations.md

tile.json