Skip to content

mortie.Toc — the temporal coverage object

mortie.toc(...) builds a Toc: a temporal coverage as an object, so that gappy time coverage reads as time.

from mortie import toc

when = toc("2020-01-01", "2021-06-01")
assert store_toc.overlaps(when)
sliver = store_toc & when            # the canonical cover of the overlap

The two-layer rule

mortie's temporal-coverage surface is two layers and stays that way, the same split the spatial object documents:

  • The kernel functions are the array/batch layer. The free toc_* functions on the toc kernel page are words in, words out, unchanged and un-deprecated, and the segmented tocs_reduce stays function-shaped permanently. Array-first consumers keep calling these directly, at zero wrapping cost.
  • The object is ergonomics. Toc is a thin view over the canonical uint64 word set — toc_normalize's sorted maximal merges — never a new representation: every public method is a single delegation to a kernel function (all three delegate to toc_and, the one set operation the issue #177 call-site audit ruled in). The array stays the interchange format — Toc.__toc_words__() hands the canonical words back, and any object exposing that dunder is accepted wherever a Toc is.

The canonical form is a word set

A store observed in campaigns has gappy coverage: one merged envelope papers over the gaps exactly where they are most informative, so the canonical form keeps k disjoint spans (plus free instants, bit-identical). Normalization is lossy toward coverage, one way: a timestamp subsumed by a range's decoded span is absorbed at construction, and a cover can be rebuilt from the sibling word arrays it came from — never the arrays from a cover. Union needs no method (construction normalizes, so Toc(np.append(a.words, b.words)) is the union), and the difference / symmetric-difference directions deliberately do not ship: conservative covers under-cover on subtraction, and no audited call site exists.

Two naming notes. Toc.overlaps / Toc.contains compare two whole covers and answer once; the un-deprecated kernel predicates toc_overlaps / toc_contains of the same names take a [q_start_ns, q_end_ns) query window and answer elementwise, per word — a different question. And the predicates are envelope algebra, not data algebra: the conservative-direction table in the module docstring below says which way each answer can err near a span edge (the quanta are ~2–4 s).

The time-first Toc object over the toc kernel (issue #198).

mortie's temporal-coverage surface is two layers, the same deliberate split :mod:mortie.moc_object documents for space:

  • the kernel -- the free toc_* functions in :mod:mortie._toc, words in and words out, unchanged and un-deprecated. Array-first consumers (zagg's per-cell folds, the segmented :func:~mortie.tocs_reduce) keep calling them on plain ndarrays at zero wrapping cost.
  • the object -- :class:Toc, here. It is ergonomics and nothing else: a thin view over the canonical uint64 word set (:func:~mortie.toc_normalize's sorted maximal merges), never a new representation. Every public method is a single delegation to a kernel function. There is no algebra in this module; a method body that is not one kernel call is a bug, not a feature.

All three object methods delegate to the same kernel, :func:~mortie.toc_and -- the one set operation the issue #177 call-site audit ruled in. The method names are the MOCpy-adjacent vocabulary (issue

198 commitment 6), so they deliberately do not line up with the batch

layer's :func:~mortie.toc_overlaps / :func:~mortie.toc_contains, which stay un-deprecated and ask a different question: those take a [q_start_ns, q_end_ns) query window and answer elementwise, per word, while :meth:Toc.overlaps / :meth:Toc.contains compare two whole covers and answer once. "The object method is the kernel of the same name with self bound" is the wrong reading here; each method docstring names the kernel it actually calls.

The interchange format stays the array. :meth:Toc.__toc_words__ hands back the canonical words -- the temporal sibling of __morton_moc__() -- and any object exposing that dunder is accepted wherever a Toc is: mortie owns the word grammar, downstream stores own their own encodings, and the two meet at a plain uint64 array with neither importing the other's private grammar.

Conservative directions. Every predicate below is envelope algebra, not data algebra. A range word's decoded envelope dilates the real interval it was encoded from (starts floor to the 2^31 ns grid, ends ceil to 2^32 ns), so the covered timeline is always a superset of the real one, on both sides of the comparison. Read the answers accordingly; each method's docstring points back here.

call the question it answers exactly as a question about the real data
a.overlaps(b) do the two covers share any decoded instant? may say True for data that only comes within a quantum (~2-4 s) of each other; a False is decisive. The safe direction for "must I read this store?" -- never a false skip.
a.contains(b) is b's decoded coverage inside a's? may err either way by up to a quantum at span edges (each side's envelope dilates its own data). Exact for the question that matters -- "will a store whose coverage is a answer a query for b?"
a & b, a.intersection(b) the canonical cover of the shared coverage never under-covers the true intersection (A ⊇ X and B ⊇ Y imply A ∩ B ⊇ X ∩ Y); may over-cover near piece edges by up to one quantum per side, inherited from the operands.
either side empty an empty cover is contained in everything and overlaps nothing a.contains(empty) is True (vacuously -- there is no coverage of empty outside a) while a.overlaps(empty) is False. The two predicates disagree here by definition, not by accident: ask contains about coverage and overlaps about work to do.
a == b identical canonical words not equality of the underlying timeline: an instant and the degenerate span at the same time encode different words and compare unequal.

Toc

A temporal coverage as an object -- gappy time coverage that reads as time.

A thin view over the canonical uint64 toc word set and nothing more: the words are the coverage, this class is the ergonomics, and every public method is a single delegation to a kernel function (see the module docstring for the two-layer rule and the conservative-direction table the methods share).

The canonical form is a word set, not a single envelope (issue #198): a store observed in campaigns has gappy coverage, and one merged envelope papers over the gaps exactly where they are most informative -- k disjoint spans keep them. The words are normalized eagerly (:func:~mortie.toc_normalize) and stored read-only, which makes == and :func:hash well defined; the instance itself is immutable.

Normalization is lossy toward coverage, one way (the #177 Q2 ruling): a timestamp subsumed by a range's decoded span adds no coverage and is absorbed at construction -- which subsumed instants existed, and how many times, is dropped. Exact instants live in the sibling word arrays a cover is built from; a cover can be rebuilt from the arrays, never the arrays from a cover. A timestamp no range subsumes survives bit-identical as an exact degenerate member, and a surviving decoded gap is never bridged (Q1).

Union needs no method: construction normalizes, so Toc(np.append(a.words, b.words)) is the union. The #177 call-site audit ruled exactly one set operation in (:func:~mortie.toc_and, the :meth:intersection / & delegate); the difference and symmetric-difference directions deliberately do not ship -- conservative covers under-cover on subtraction, and no audited call site exists.

Parameters:

Name Type Description Default
source str, datetime64, array_like, or Toc

What the coverage is. A UTC instant -- an ISO 8601 string or numpy.datetime64 -- or an array of them, encoded exactly via :func:~mortie.time2toc; with end given, the start side of one or more closed real intervals [source, end], enveloped conservatively via :func:~mortie.span2toc (source and end broadcast). A 1-D integer array (or a single int) is taken as toc words as given; any object exposing __toc_words__(), another :class:Toc included, contributes its canonical words. Integers are always words: internal nanoseconds go through :func:~mortie.time2toc / :func:~mortie.span2toc explicitly, so a bare number can never be misread as a time on the wrong epoch. Any size-0 source that is not datetimes or strings -- [], (), np.array([]), a typed empty -- is the empty cover.

required
end str, datetime64, or array_like

End side of the time-pair form, same forms as source. Only a time source takes it: with a words or protocol source it is refused rather than ignored.

None

Raises:

Type Description
ValueError

If a time endpoint is numeric rather than datetime64 / ISO string, a span is inverted or outside the representable epoch range (see :func:~mortie.span2toc / :func:~mortie.from_datetime64), words are negative, non-integer-typed or not 1-D, or end is given for a source that is already words.

See Also

mortie.toc_normalize : the eager canonicalization applied to every instance. mortie.toc_and : the intersection kernel the set methods delegate to.

Examples:

>>> import mortie
>>> when = mortie.Toc("2020-01-01", "2021-06-01")
>>> mortie.Toc("2020-06-15").overlaps(when)
True
>>> when.contains(mortie.Toc("2020-03-01", "2020-04-01"))
True
Source code in mortie/toc_object.py
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
class Toc:
    """A temporal coverage as an object -- gappy time coverage that reads as time.

    A thin view over the canonical ``uint64`` toc word set and nothing more:
    the words *are* the coverage, this class is the ergonomics, and every
    public method is a single delegation to a kernel function (see the module
    docstring for the two-layer rule and the conservative-direction table the
    methods share).

    The canonical form is a word **set**, not a single envelope (issue #198):
    a store observed in campaigns has *gappy* coverage, and one merged
    envelope papers over the gaps exactly where they are most informative --
    k disjoint spans keep them.  The words are normalized eagerly
    (:func:`~mortie.toc_normalize`) and stored read-only, which makes ``==``
    and :func:`hash` well defined; the instance itself is immutable.

    Normalization is **lossy toward coverage, one way** (the #177 Q2 ruling):
    a timestamp subsumed by a range's decoded span adds no coverage and is
    absorbed at construction -- which subsumed instants existed, and how many
    times, is dropped.  Exact instants live in the sibling word arrays a
    cover is built from; a cover can be rebuilt from the arrays, never the
    arrays from a cover.  A timestamp no range subsumes survives
    bit-identical as an exact degenerate member, and a surviving decoded gap
    is never bridged (Q1).

    Union needs no method: construction normalizes, so
    ``Toc(np.append(a.words, b.words))`` is the union.  The #177 call-site
    audit ruled exactly one set operation in (:func:`~mortie.toc_and`, the
    :meth:`intersection` / ``&`` delegate); the difference and
    symmetric-difference directions deliberately do not ship -- conservative
    covers under-cover on subtraction, and no audited call site exists.

    Parameters
    ----------
    source : str, datetime64, array_like, or Toc
        What the coverage is.  A UTC instant -- an ISO 8601 string or
        ``numpy.datetime64`` -- or an array of them, encoded exactly via
        :func:`~mortie.time2toc`; with ``end`` given, the start side of one
        or more closed real intervals ``[source, end]``, enveloped
        conservatively via :func:`~mortie.span2toc` (``source`` and ``end``
        broadcast).  A 1-D integer array (or a single int) is taken as toc
        **words** as given; any object exposing ``__toc_words__()``, another
        :class:`Toc` included, contributes its canonical words.  Integers are
        always words: internal nanoseconds go through
        :func:`~mortie.time2toc` / :func:`~mortie.span2toc` explicitly, so a
        bare number can never be misread as a time on the wrong epoch.  Any
        size-0 source that is not datetimes or strings -- ``[]``, ``()``,
        ``np.array([])``, a typed empty -- is the empty cover.
    end : str, datetime64, or array_like, optional
        End side of the time-pair form, same forms as ``source``.  Only a
        time source takes it: with a words or protocol source it is refused
        rather than ignored.

    Raises
    ------
    ValueError
        If a time endpoint is numeric rather than datetime64 / ISO string, a
        span is inverted or outside the representable epoch range (see
        :func:`~mortie.span2toc` / :func:`~mortie.from_datetime64`), words
        are negative, non-integer-typed or not 1-D, or ``end`` is given for a
        source that is already words.

    See Also
    --------
    mortie.toc_normalize : the eager canonicalization applied to every
        instance.
    mortie.toc_and : the intersection kernel the set methods delegate to.

    Examples
    --------
    >>> import mortie
    >>> when = mortie.Toc("2020-01-01", "2021-06-01")
    >>> mortie.Toc("2020-06-15").overlaps(when)
    True
    >>> when.contains(mortie.Toc("2020-03-01", "2020-04-01"))
    True
    """

    __slots__ = ("words",)

    def __init__(self, source, end=None):
        words = toc_normalize(_source_words(source, end))
        words.setflags(write=False)
        object.__setattr__(self, "words", words)

    def __setattr__(self, name, value):
        """Refuse attribute assignment -- a Toc is immutable."""
        raise AttributeError(
            "Toc is immutable (its hash is its words); build a new one instead"
        )

    def __delattr__(self, name):
        """Refuse attribute deletion -- a Toc is immutable."""
        raise AttributeError("Toc is immutable; build a new one instead")

    def __reduce__(self):
        """Rebuild through the constructor -- pickle and copy cannot set slots.

        A ``__slots__`` class is restored by assigning its slot state, which
        the immutability guard above refuses; reconstructing from the words
        instead keeps ``Toc`` picklable (workers marshal their arguments) and
        deep-copyable at the cost of one ``toc_normalize`` on already-canonical
        words.

        Returns
        -------
        tuple
            The ``(callable, args)`` pair the pickle protocol rebuilds from.
        """
        return (Toc, (self.words,))

    def overlaps(self, other):
        """Whether this cover and ``other`` share any coverage.

        Envelope algebra, not data algebra -- see the module docstring's
        conservative-direction table: ``True`` can mean "within a quantum of
        each other", ``False`` is decisive.

        Parameters
        ----------
        other : Toc or array_like
            The cover to test against.

        Returns
        -------
        bool
            ``True`` if the two covers share any decoded instant.

        See Also
        --------
        mortie.toc_and : the kernel this delegates to.
        mortie.toc_overlaps : the batch layer's *window* predicate of the
            same name, a different question -- which individual words
            intersect a ``[q_start_ns, q_end_ns)`` window, elementwise.
        """
        return toc_and(self.words, _words(other)).size > 0

    def contains(self, other):
        """Whether ``other``'s coverage lies entirely inside this cover.

        Envelope algebra, not data algebra -- see the module docstring's
        conservative-direction table.  This is the "will a store whose
        coverage is ``self`` answer a query for ``other``?" test: the
        intersection with ``other`` must give ``other`` back whole, and both
        sides of that comparison are canonical -- the kernel's output by
        construction, the operand because :func:`_words` canonicalizes every
        operand it is handed -- so word equality is coverage equality.  The
        single-delegation shape costs a second :func:`_words` call (a foreign
        ``__toc_words__()`` is therefore invoked twice per test); binding it
        to a local would be a second statement, which the delegation pin
        refuses.

        Parameters
        ----------
        other : Toc or array_like
            The cover to test for containment.

        Returns
        -------
        bool
            ``True`` if ``other`` adds no coverage outside this cover.

        See Also
        --------
        mortie.toc_and : the kernel this delegates to.
        mortie.toc_contains : the batch layer's *window* predicate of the
            same name, and the mirror direction -- which individual words
            fall inside a ``[q_start_ns, q_end_ns)`` window, elementwise,
            rather than whether one cover sits inside another.
        """
        return np.array_equal(toc_and(self.words, _words(other)), _words(other))

    def intersection(self, other):
        """Intersect with ``other``: the canonical cover of the shared coverage (``&``).

        Never under-covers the true intersection and may over-cover near
        piece edges by up to one quantum per side, inherited from the
        operands' envelopes -- see the module docstring's table.

        Parameters
        ----------
        other : Toc or array_like
            The cover to intersect with.

        Returns
        -------
        Toc
            The intersection cover.
        """
        return Toc(toc_and(self.words, _words(other)))

    __and__ = intersection

    def __toc_words__(self):
        """Canonical toc words -- the interchange protocol (issue #198).

        Returns
        -------
        numpy.ndarray
            The read-only ``uint64`` word array backing this cover.
        """
        return self.words

    def __eq__(self, other):
        """Compare canonical words -- word identity, not timeline equality."""
        if not isinstance(other, Toc):
            return NotImplemented
        return np.array_equal(self.words, other.words)

    def __hash__(self):
        """Hash the canonical words; sound because a Toc is immutable."""
        return hash(self.words.tobytes())

    def __len__(self):
        """Count the words (disjoint spans and free instants) in the cover."""
        return int(self.words.size)

    def __iter__(self):
        """Iterate the cover's toc words."""
        return iter(self.words)

    def __repr__(self):
        """Show the span count, the UTC extent, and the covered duration.

        Both printed bounds round **outward** to the second -- the start
        floors, the end ceils -- so the extent shown is never narrower than
        what the cover covers.  A decoded end sits on the 2^32 ns grid
        (~4.295 s) and so is essentially never a whole second; flooring it
        would print a time strictly inside the envelope, the one direction
        the module docstring's conservative-direction table rules out.
        """
        if self.words.size == 0:
            return "Toc(0 spans)"
        ranges = toc_is_range(self.words)
        n_ranges, n_instants = int(ranges.sum()), int((~ranges).sum())
        kinds = []
        if n_ranges:
            kinds.append(f"{n_ranges} range" + ("s" if n_ranges > 1 else ""))
        if n_instants:
            kinds.append(
                f"{n_instants} instant" + ("s" if n_instants > 1 else ""))
        starts, ends = toc2time(self.words)
        first = np.datetime64(to_datetime64(int(starts.min())), "s")
        end = to_datetime64(int(ends.max()))
        last = np.datetime64(end, "s")
        if last != end:
            last += np.timedelta64(1, "s")
        covered = _covered_display(int((ends - starts).sum()))
        return (f"Toc({' + '.join(kinds)}, {first} to {last}, "
                f"{covered} covered)")

__delattr__(name)

Refuse attribute deletion -- a Toc is immutable.

Source code in mortie/toc_object.py
347
348
349
def __delattr__(self, name):
    """Refuse attribute deletion -- a Toc is immutable."""
    raise AttributeError("Toc is immutable; build a new one instead")

__eq__(other)

Compare canonical words -- word identity, not timeline equality.

Source code in mortie/toc_object.py
459
460
461
462
463
def __eq__(self, other):
    """Compare canonical words -- word identity, not timeline equality."""
    if not isinstance(other, Toc):
        return NotImplemented
    return np.array_equal(self.words, other.words)

__hash__()

Hash the canonical words; sound because a Toc is immutable.

Source code in mortie/toc_object.py
465
466
467
def __hash__(self):
    """Hash the canonical words; sound because a Toc is immutable."""
    return hash(self.words.tobytes())

__iter__()

Iterate the cover's toc words.

Source code in mortie/toc_object.py
473
474
475
def __iter__(self):
    """Iterate the cover's toc words."""
    return iter(self.words)

__len__()

Count the words (disjoint spans and free instants) in the cover.

Source code in mortie/toc_object.py
469
470
471
def __len__(self):
    """Count the words (disjoint spans and free instants) in the cover."""
    return int(self.words.size)

__reduce__()

Rebuild through the constructor -- pickle and copy cannot set slots.

A __slots__ class is restored by assigning its slot state, which the immutability guard above refuses; reconstructing from the words instead keeps Toc picklable (workers marshal their arguments) and deep-copyable at the cost of one toc_normalize on already-canonical words.

Returns:

Type Description
tuple

The (callable, args) pair the pickle protocol rebuilds from.

Source code in mortie/toc_object.py
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
def __reduce__(self):
    """Rebuild through the constructor -- pickle and copy cannot set slots.

    A ``__slots__`` class is restored by assigning its slot state, which
    the immutability guard above refuses; reconstructing from the words
    instead keeps ``Toc`` picklable (workers marshal their arguments) and
    deep-copyable at the cost of one ``toc_normalize`` on already-canonical
    words.

    Returns
    -------
    tuple
        The ``(callable, args)`` pair the pickle protocol rebuilds from.
    """
    return (Toc, (self.words,))

__repr__()

Show the span count, the UTC extent, and the covered duration.

Both printed bounds round outward to the second -- the start floors, the end ceils -- so the extent shown is never narrower than what the cover covers. A decoded end sits on the 2^32 ns grid (~4.295 s) and so is essentially never a whole second; flooring it would print a time strictly inside the envelope, the one direction the module docstring's conservative-direction table rules out.

Source code in mortie/toc_object.py
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
def __repr__(self):
    """Show the span count, the UTC extent, and the covered duration.

    Both printed bounds round **outward** to the second -- the start
    floors, the end ceils -- so the extent shown is never narrower than
    what the cover covers.  A decoded end sits on the 2^32 ns grid
    (~4.295 s) and so is essentially never a whole second; flooring it
    would print a time strictly inside the envelope, the one direction
    the module docstring's conservative-direction table rules out.
    """
    if self.words.size == 0:
        return "Toc(0 spans)"
    ranges = toc_is_range(self.words)
    n_ranges, n_instants = int(ranges.sum()), int((~ranges).sum())
    kinds = []
    if n_ranges:
        kinds.append(f"{n_ranges} range" + ("s" if n_ranges > 1 else ""))
    if n_instants:
        kinds.append(
            f"{n_instants} instant" + ("s" if n_instants > 1 else ""))
    starts, ends = toc2time(self.words)
    first = np.datetime64(to_datetime64(int(starts.min())), "s")
    end = to_datetime64(int(ends.max()))
    last = np.datetime64(end, "s")
    if last != end:
        last += np.timedelta64(1, "s")
    covered = _covered_display(int((ends - starts).sum()))
    return (f"Toc({' + '.join(kinds)}, {first} to {last}, "
            f"{covered} covered)")

__setattr__(name, value)

Refuse attribute assignment -- a Toc is immutable.

Source code in mortie/toc_object.py
341
342
343
344
345
def __setattr__(self, name, value):
    """Refuse attribute assignment -- a Toc is immutable."""
    raise AttributeError(
        "Toc is immutable (its hash is its words); build a new one instead"
    )

__toc_words__()

Canonical toc words -- the interchange protocol (issue #198).

Returns:

Type Description
ndarray

The read-only uint64 word array backing this cover.

Source code in mortie/toc_object.py
449
450
451
452
453
454
455
456
457
def __toc_words__(self):
    """Canonical toc words -- the interchange protocol (issue #198).

    Returns
    -------
    numpy.ndarray
        The read-only ``uint64`` word array backing this cover.
    """
    return self.words

contains(other)

Whether other's coverage lies entirely inside this cover.

Envelope algebra, not data algebra -- see the module docstring's conservative-direction table. This is the "will a store whose coverage is self answer a query for other?" test: the intersection with other must give other back whole, and both sides of that comparison are canonical -- the kernel's output by construction, the operand because :func:_words canonicalizes every operand it is handed -- so word equality is coverage equality. The single-delegation shape costs a second :func:_words call (a foreign __toc_words__() is therefore invoked twice per test); binding it to a local would be a second statement, which the delegation pin refuses.

Parameters:

Name Type Description Default
other Toc or array_like

The cover to test for containment.

required

Returns:

Type Description
bool

True if other adds no coverage outside this cover.

See Also

mortie.toc_and : the kernel this delegates to. mortie.toc_contains : the batch layer's window predicate of the same name, and the mirror direction -- which individual words fall inside a [q_start_ns, q_end_ns) window, elementwise, rather than whether one cover sits inside another.

Source code in mortie/toc_object.py
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
def contains(self, other):
    """Whether ``other``'s coverage lies entirely inside this cover.

    Envelope algebra, not data algebra -- see the module docstring's
    conservative-direction table.  This is the "will a store whose
    coverage is ``self`` answer a query for ``other``?" test: the
    intersection with ``other`` must give ``other`` back whole, and both
    sides of that comparison are canonical -- the kernel's output by
    construction, the operand because :func:`_words` canonicalizes every
    operand it is handed -- so word equality is coverage equality.  The
    single-delegation shape costs a second :func:`_words` call (a foreign
    ``__toc_words__()`` is therefore invoked twice per test); binding it
    to a local would be a second statement, which the delegation pin
    refuses.

    Parameters
    ----------
    other : Toc or array_like
        The cover to test for containment.

    Returns
    -------
    bool
        ``True`` if ``other`` adds no coverage outside this cover.

    See Also
    --------
    mortie.toc_and : the kernel this delegates to.
    mortie.toc_contains : the batch layer's *window* predicate of the
        same name, and the mirror direction -- which individual words
        fall inside a ``[q_start_ns, q_end_ns)`` window, elementwise,
        rather than whether one cover sits inside another.
    """
    return np.array_equal(toc_and(self.words, _words(other)), _words(other))

intersection(other)

Intersect with other: the canonical cover of the shared coverage (&).

Never under-covers the true intersection and may over-cover near piece edges by up to one quantum per side, inherited from the operands' envelopes -- see the module docstring's table.

Parameters:

Name Type Description Default
other Toc or array_like

The cover to intersect with.

required

Returns:

Type Description
Toc

The intersection cover.

Source code in mortie/toc_object.py
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
def intersection(self, other):
    """Intersect with ``other``: the canonical cover of the shared coverage (``&``).

    Never under-covers the true intersection and may over-cover near
    piece edges by up to one quantum per side, inherited from the
    operands' envelopes -- see the module docstring's table.

    Parameters
    ----------
    other : Toc or array_like
        The cover to intersect with.

    Returns
    -------
    Toc
        The intersection cover.
    """
    return Toc(toc_and(self.words, _words(other)))

overlaps(other)

Whether this cover and other share any coverage.

Envelope algebra, not data algebra -- see the module docstring's conservative-direction table: True can mean "within a quantum of each other", False is decisive.

Parameters:

Name Type Description Default
other Toc or array_like

The cover to test against.

required

Returns:

Type Description
bool

True if the two covers share any decoded instant.

See Also

mortie.toc_and : the kernel this delegates to. mortie.toc_overlaps : the batch layer's window predicate of the same name, a different question -- which individual words intersect a [q_start_ns, q_end_ns) window, elementwise.

Source code in mortie/toc_object.py
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
def overlaps(self, other):
    """Whether this cover and ``other`` share any coverage.

    Envelope algebra, not data algebra -- see the module docstring's
    conservative-direction table: ``True`` can mean "within a quantum of
    each other", ``False`` is decisive.

    Parameters
    ----------
    other : Toc or array_like
        The cover to test against.

    Returns
    -------
    bool
        ``True`` if the two covers share any decoded instant.

    See Also
    --------
    mortie.toc_and : the kernel this delegates to.
    mortie.toc_overlaps : the batch layer's *window* predicate of the
        same name, a different question -- which individual words
        intersect a ``[q_start_ns, q_end_ns)`` window, elementwise.
    """
    return toc_and(self.words, _words(other)).size > 0