Source code for speasy.core.span_utils

from typing import List, Tuple, Any, Sequence, Union, Optional


[docs] def span_ctor(span_type, start, stop): if start <= stop: if span_type is list or span_type is tuple: return span_type((start, stop)) else: return span_type(start, stop) else: return None
[docs] def is_span(maybe_span: Any) -> bool: return hasattr(maybe_span, '__getitem__') and len(maybe_span) == 2 and maybe_span[0] <= maybe_span[1]
[docs] def is_empty(span: Sequence) -> bool: return span[0] == span[1]
[docs] def intersection(span: Sequence, other: Sequence) -> Optional[Sequence]: if not is_span(span) or not is_span(other): raise TypeError("You must provide a Span like object") if other[0] > span[1] or span[0] > other[1]: return None else: return span_ctor(type(span), max(span[0], other[0]), min(span[1], other[1]))
[docs] def intersects(span: Sequence, other: Sequence) -> bool: return intersection(span, other) is not None
[docs] def contains(span: Sequence, other: Sequence) -> bool: if not is_span(span) or not is_span(other): raise TypeError("You must provide a Span like object") return span[0] <= other[0] <= span[1] and span[1] >= other[1] >= span[0]
[docs] def equals(span: Sequence, other: Sequence) -> bool: if not is_span(span) or not is_span(other): raise TypeError("You must provide a Span like object") return span[0] == other[0] and span[1] == other[1]
[docs] def merge(spans: Union[List[Sequence], Tuple[Sequence]]) -> List[Sequence]: assert all([is_span(span) for span in spans]) merged_list = [] spans.sort(key=lambda item: item[0]) while len(spans): current_span = spans.pop(0) while len(spans): if current_span[1] >= spans[0][0]: current_span[1] = max(current_span[1], spans[0][1]) spans.pop(0) else: break merged_list.append(current_span) return merged_list
[docs] def difference(span: Sequence, other_s: Sequence) -> List[Sequence]: if not is_span(span) or not is_span(other_s): raise TypeError("You must provide a Span like object") diff = [ span_ctor(type(span), span[0], min(other_s[0], span[1])), span_ctor(type(span), max(other_s[1], span[0]), span[1]) ] diff = [part for part in diff if part is not None and not is_empty(part)] return diff
[docs] def zoom(span: Sequence, factor: float): if not is_span(span): raise TypeError("You must provide a Span like object") if type(factor) is not float and type(factor) is not int: raise TypeError("factor must be float") width = (span[1] - span[0]) / 2 center = span[0] + width width *= factor return span_ctor(type(span), center - width, center + width)
[docs] def shift(span: Sequence, distance): if not is_span(span): raise TypeError("You must provide a Span like object") return span_ctor(type(span), span[0] + distance, span[1] + distance)
[docs] def split(span: Sequence, fragment_duration) -> List[Sequence]: from math import ceil if not is_span(span): raise TypeError("You must provide a Span like object") total_duration = span[1] - span[0] if total_duration <= fragment_duration: return [span] fragments = [ span_ctor(type(span), span[0] + fragment_duration * i, min(span[0] + fragment_duration * (i + 1), span[1])) for i in range(ceil(total_duration / fragment_duration))] return fragments