Skip to content

mortie.Moc — the coverage object

mortie.moc(...) builds a Moc: a multi-order coverage as an object, so that coverage geometry reads as geometry.

from mortie import moc

cali = moc(cali_geojson)     # multi-order coverage; no order argument
q    = moc(aoi_geojson)
assert cali.contains(q)
q9 = q.to_order(9)           # fixed-order cast when a consumer's grid wants one

The two-layer rule

mortie's coverage surface is two layers and stays that way:

  • The kernel functions are the array/batch layer. The free moc_* functions on mortie MOC kernel are words in, words out, unchanged and un-deprecated, and the plural forms in mortie.batch (mocs_and, mocs_intersect, mocs_to_orders, polygons_to_morton_mocs) stay function-shaped permanently — an offset-packed many-cover operation has no natural self. Array-first consumers keep calling these directly, at zero wrapping cost.
  • The object is ergonomics. Moc is a thin view over the canonical uint64 word array, never a new representation: every method is a single delegation to a kernel function. The array stays the interchange format — Moc.__morton_moc__() hands the canonical words back, and any object exposing that dunder is accepted wherever a Moc is.

MOCpy crosswalk

HEALPix-MOC users already know these names, so the object mirrors them where they apply. The word encoding is mortie's own frozen grammar (specification §1/§4) either way — only the vocabulary is shared.

MOCpy mortie object mortie kernel
MOC.from_polygon(lon, lat, max_depth=…) Moc.from_polygon(lats, lons), or moc(geojson) morton_coverage_moc(lats, lons, order=…)
a.union(b), a \| b a.union(b), a \| b moc_or(a, b)
a.intersection(b), a & b a.intersection(b), a & b moc_and(a, b)
a.difference(b), a - b a.difference(b), a - b moc_minus(a, b)
a.symmetric_difference(b) a.symmetric_difference(b), a ^ b moc_xor(a, b)
b.difference(a).empty() a.contains(b), b.within(a) moc_minus(b, a).size == 0
a.contains_lonlat(lon, lat) — (kernel only) moc_intersects(a, geo2mort(lat, lon, order))
a.intersects(b) moc_intersects(a, b)
a.degrade_to_order(n).flatten() a.to_order(n) moc_to_order(a, n)
a.complement() — (kernel only) moc_not(a, domain)
a.max_order repr(a) orders_of(a).max()

Three places the vocabulary matches but the meaning does not:

  • from_polygon takes its coordinates the other way round. MOCpy is MOC.from_polygon(lon, lat, …); mortie is Moc.from_polygon(lats, lons, …). Same name, swapped order — transpose it and you get a cover somewhere else entirely.
  • MOCpy has no MOC-in-MOC contains. MOC.contains(lon, lat, …) is a point-in-MOC mask (and is deprecated in favour of contains_lonlat / contains_skycoords); the MOCpy spelling of mortie's a.contains(b) is b.difference(a).empty().
  • a.to_order(n) is not degrade_to_order and not flatten. degrade_to_order(n) returns a coarsened MOC and flatten() takes no order, so the MOCpy equivalent is the pair degrade_to_order(n).flatten(). That covers the coarsening direction only: to_order(n) also densifies when n is finer than the cover, which MOCpy has no single call for.

Two mortie-specific notes. a.to_order(n) returns the flat array, not a Moc: a single-order cell list is not a MOC, and re-normalizing it would collapse it straight back to the compact form. And the predicates are cover algebra, not polygon algebra — the conservative-direction table below says which way each answer can err near a boundary.

The geometry-first Moc object over the MOC kernel (issue #196).

mortie's coverage surface is two layers, and the split is deliberate:

  • the kernel — the free moc_* functions in :mod:mortie._moc, words in and words out, unchanged and un-deprecated. Array-first consumers (moczarr's mask internals, zagg's grids, the batch shardmap machinery) keep calling them on plain ndarrays at zero wrapping cost, and the plural batch forms (:func:~mortie.batch.mocs_and, :func:~mortie.batch.mocs_intersect, :func:~mortie.batch.mocs_to_orders, :func:~mortie.batch.polygons_to_morton_mocs) stay function-shaped permanently — an offset-packed many-cover operation has no natural self.
  • the object — :class:Moc, here. It is ergonomics and nothing else: a thin view over the canonical uint64 word array, never a new representation. Every 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.

The interchange format stays the array. :meth:Moc.__morton_moc__ hands back the canonical words, and any object exposing that dunder is accepted wherever a Moc is — mortie owns geometry and words, 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 cover algebra, not polygon algebra. A cover dilates the polygon it was built from — a boundary cell is included when it only partly overlaps — so the covered area is always a superset of the polygon, on both sides of the comparison. Read the answers accordingly; each predicate's docstring points back here.

call the question it answers exactly as a polygon question
a.intersects(b) do the two covers share any area? may say True for polygons that only come within a cell of each other; a False is decisive. The safe direction for "must I read this shard?" — never a false skip.
a.contains(b) is every cell of b inside a? may say True when b's polygon pokes outside a's by less than a cell. Exact for the question that matters — "will a store whose coverage is a answer a query for b?"
a.within(b) is every cell of a inside b? the mirror of contains; same caveat.
either side empty an empty cover is contained in everything and intersects nothing a.contains(empty) is True (vacuously — there is no cell of empty outside a) while a.intersects(empty) is False. The two predicates disagree here by definition, not by accident: ask contains about coverage and intersects about work to do.
a == b identical canonical words not geometric equality: two covers of the same polygon built at different tolerance / max_cells compare unequal.

Moc

A multi-order coverage as an object — coverage geometry that reads as geometry.

A thin view over the canonical uint64 word array and nothing more: the words are the MOC, this class is the ergonomics, and every method is a single delegation to the kernel function of the same meaning (see the module docstring for the two-layer rule and the conservative-direction table the predicates share).

Coverage is multi-order by default — coarse cells inside, fine cells along the boundary, down to :func:~mortie.morton_coverage_moc's default finest order — so there is no order argument. Use :meth:to_order to cast to a flat single-order cell list when a consumer's grid wants one, and read :func:repr to see what resolution you actually got. Construction is deterministic: the same input through the same mortie version yields the same words, byte for byte.

The words are normalized eagerly (:func:~mortie.compress_moc) and stored read-only, which makes == and :func:hash well defined; the instance itself is immutable.

Parameters:

Name Type Description Default
source dict or array_like or Moc

What to cover. A GeoJSON mapping (Feature / FeatureCollection / Polygon / MultiPolygon, parsed without shapely and tolerant of a missing "type"); one (N, 2+) ring of [lon, lat] positions or a list of such rings (holes and disjoint parts are resolved by one even-odd descent); a 1-D uint64 array of morton words; or any object exposing __morton_moc__(), which includes another :class:Moc. Rings within one geometry take that even-odd descent — nested rings carve holes — while separate geometries of a FeatureCollection are unioned, since overlapping and nested features are legal there and must add area rather than cancel it. Words are taken as given: any integer array is cast to uint64, so a negative or downcast value wraps rather than being rejected here and fails later inside the kernel.

required
tolerance float

Stop refining a boundary cell once its angular radius (in degrees) drops to this value; see :func:~mortie.morton_coverage_moc.

None
max_cells int

Best-first cell budget for the boundary; see :func:~mortie.morton_coverage_moc. Mutually exclusive with tolerance. Applied per geometry, so a FeatureCollection budgets each feature's boundary rather than the union's.

None
latitude str

Latitude convention of the input vertices (default "authalic"); see :func:~mortie.morton_coverage.

'authalic'

Raises:

Type Description
ValueError

If source is not one of the forms above, the coverer rejects the rings (see :func:~mortie.morton_coverage_moc), or a coverage knob (tolerance / max_cells / latitude) is given for a source that is already words — those steer the coverer, which such a source never reaches, so they are refused rather than ignored.

See Also

mortie.morton_coverage_moc : the coverage kernel this wraps. mortie.compress_moc : the eager normalization applied to every instance.

Examples:

>>> import mortie
>>> aoi = {"type": "Polygon", "coordinates": [[
...     [-76.56, 38.87], [-76.50, 38.87], [-76.50, 38.91],
...     [-76.56, 38.91], [-76.56, 38.87]]]}
>>> region = mortie.moc(aoi)
>>> region.contains(region)
True
>>> region.to_order(9).dtype
dtype('uint64')
Source code in mortie/moc_object.py
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
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
class Moc:
    """A multi-order coverage as an object — coverage geometry that reads as geometry.

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

    Coverage is **multi-order by default** — coarse cells inside, fine cells
    along the boundary, down to :func:`~mortie.morton_coverage_moc`'s default
    finest order — so there is no ``order`` argument.  Use :meth:`to_order` to
    cast to a flat single-order cell list when a consumer's grid wants one, and
    read :func:`repr` to see what resolution you actually got.  Construction is
    **deterministic**: the same input through the same mortie version yields
    the same words, byte for byte.

    The words are normalized eagerly (:func:`~mortie.compress_moc`) and stored
    read-only, which makes ``==`` and :func:`hash` well defined; the instance
    itself is immutable.

    Parameters
    ----------
    source : dict or array_like or Moc
        What to cover.  A GeoJSON mapping (``Feature`` / ``FeatureCollection``
        / ``Polygon`` / ``MultiPolygon``, parsed without shapely and tolerant
        of a missing ``"type"``); one ``(N, 2+)`` ring of ``[lon, lat]``
        positions or a list of such rings (holes and disjoint parts are
        resolved by one even-odd descent); a 1-D ``uint64`` array of morton
        words; or any object exposing ``__morton_moc__()``, which includes
        another :class:`Moc`.  Rings *within* one geometry take that even-odd
        descent — nested rings carve holes — while separate geometries of a
        ``FeatureCollection`` are **unioned**, since overlapping and nested
        features are legal there and must add area rather than cancel it.
        Words are taken as given: any integer array is cast to ``uint64``, so a
        negative or downcast value wraps rather than being rejected here and
        fails later inside the kernel.
    tolerance : float, optional
        Stop refining a boundary cell once its angular radius (in degrees)
        drops to this value; see :func:`~mortie.morton_coverage_moc`.
    max_cells : int, optional
        Best-first cell budget for the boundary; see
        :func:`~mortie.morton_coverage_moc`.  Mutually exclusive with
        ``tolerance``.  Applied per geometry, so a ``FeatureCollection``
        budgets each feature's boundary rather than the union's.
    latitude : str, optional
        Latitude convention of the input vertices (default ``"authalic"``);
        see :func:`~mortie.morton_coverage`.

    Raises
    ------
    ValueError
        If ``source`` is not one of the forms above, the coverer rejects the
        rings (see :func:`~mortie.morton_coverage_moc`), or a coverage knob
        (``tolerance`` / ``max_cells`` / ``latitude``) is given for a source
        that is already words — those steer the coverer, which such a source
        never reaches, so they are refused rather than ignored.

    See Also
    --------
    mortie.morton_coverage_moc : the coverage kernel this wraps.
    mortie.compress_moc : the eager normalization applied to every instance.

    Examples
    --------
    >>> import mortie
    >>> aoi = {"type": "Polygon", "coordinates": [[
    ...     [-76.56, 38.87], [-76.50, 38.87], [-76.50, 38.91],
    ...     [-76.56, 38.91], [-76.56, 38.87]]]}
    >>> region = mortie.moc(aoi)
    >>> region.contains(region)
    True
    >>> region.to_order(9).dtype
    dtype('uint64')
    """

    __slots__ = ("words",)

    def __init__(self, source, tolerance=None, max_cells=None, *, latitude="authalic"):
        words = compress_moc(_source_words(source, tolerance, max_cells, latitude))
        words.setflags(write=False)
        object.__setattr__(self, "words", words)

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

    def __delattr__(self, name):
        """Refuse attribute deletion -- a Moc is immutable."""
        raise AttributeError("Moc 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 ``Moc`` picklable (workers marshal their arguments) and
        deep-copyable at the cost of one ``compress_moc`` on already-compact
        words.

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

    @classmethod
    def from_polygon(cls, lats, lons, tolerance=None, max_cells=None, *,
                     latitude="authalic"):
        """Cover a polygon given as vertex latitudes and longitudes.

        The MOCpy-vocabulary spelling of the coverage constructor, for callers
        who already have ``(lats, lons)`` rather than GeoJSON.  Multipart /
        holes take the list-of-rings form, exactly as
        :func:`~mortie.morton_coverage_moc` documents.

        Parameters
        ----------
        lats, lons : array_like
            Vertex latitudes / longitudes in degrees (one ring), or a list of
            such arrays for the multipart form.
        tolerance : float, optional
            Angular stop criterion in degrees.
        max_cells : int, optional
            Best-first cell budget for the boundary.
        latitude : str, optional
            Latitude convention of the input vertices (default
            ``"authalic"``).

        Returns
        -------
        Moc
            The polygon's multi-order cover.
        """
        return cls(
            morton_coverage_moc(
                lats, lons, tolerance=tolerance, max_cells=max_cells,
                latitude=latitude,
            )
        )

    def intersects(self, other):
        """Whether this cover and ``other`` share any area, at any order.

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

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

        Returns
        -------
        bool
            ``True`` if the two covers overlap anywhere.
        """
        return moc_intersects(self.words, _words(other))

    def contains(self, other):
        """Whether every cell of ``other`` lies inside this cover.

        Cover algebra, not polygon 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.

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

        Returns
        -------
        bool
            ``True`` if ``other`` adds no area outside this cover.
        """
        return moc_minus(_words(other), self.words).size == 0

    def within(self, other):
        """Whether every cell of this cover lies inside ``other``.

        The mirror of :meth:`contains`; the same conservative direction
        applies (module docstring).

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

        Returns
        -------
        bool
            ``True`` if this cover adds no area outside ``other``.
        """
        return moc_minus(self.words, _words(other)).size == 0

    def union(self, other):
        """Cells in this cover or in ``other`` (MOCpy ``union``, ``|``).

        Parameters
        ----------
        other : Moc or array_like
            The cover to union with.

        Returns
        -------
        Moc
            The union cover.
        """
        return Moc(moc_or(self.words, _words(other)))

    def intersection(self, other):
        """Cells in both this cover and ``other`` (MOCpy ``intersection``, ``&``).

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

        Returns
        -------
        Moc
            The intersection cover.
        """
        return Moc(moc_and(self.words, _words(other)))

    def difference(self, other):
        r"""Cells in this cover but not ``other`` (MOCpy ``difference``, ``-``).

        Parameters
        ----------
        other : Moc or array_like
            The cover to subtract.

        Returns
        -------
        Moc
            The difference cover ``self \ other``.
        """
        return Moc(moc_minus(self.words, _words(other)))

    def symmetric_difference(self, other):
        """Cells in exactly one of the two covers (MOCpy ``symmetric_difference``, ``^``).

        Parameters
        ----------
        other : Moc or array_like
            The cover to compare against.

        Returns
        -------
        Moc
            The symmetric-difference cover.
        """
        return Moc(moc_xor(self.words, _words(other)))

    __or__ = union
    __and__ = intersection
    __sub__ = difference
    __xor__ = symmetric_difference

    def to_order(self, order, max_cells=_FLAT_COVER_WARN_THRESHOLD):
        """Cast to a flat list of cells at one fixed ``order``.

        The consumer-grid direction: a multi-order cover in, every cell at
        ``order`` out, as the canonical ``uint64`` **array** — a flat
        single-order cell list is not a MOC, and re-normalizing it would
        collapse it straight back to the compact form.

        Parameters
        ----------
        order : int
            Target HEALPix order (0-29).
        max_cells : int or None, optional
            Pre-emptive budget on the densified cell count; see
            :func:`~mortie.moc_to_order`.  ``None`` opts out.

        Returns
        -------
        numpy.ndarray
            Sorted 1-D array of flat morton cells at ``order`` (``uint64``).
        """
        return moc_to_order(self.words, order, max_cells)

    def __morton_moc__(self):
        """Canonical morton words — the interchange protocol (issue #196).

        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 geometric equality."""
        if not isinstance(other, Moc):
            return NotImplemented
        return np.array_equal(self.words, other.words)

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

    def __len__(self):
        """Count the cells in the cover."""
        return int(self.words.size)

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

    def __repr__(self):
        """Show the cell count and the orders actually present."""
        if self.words.size == 0:
            return "Moc(0 cells)"
        orders = orders_of(self.words)
        low, high = int(orders.min()), int(orders.max())
        span = f"order {low}" if low == high else f"orders {low}-{high}"
        finest = res2display(high)[-1]
        return (
            f"Moc({self.words.size} cells, {span}, "
            f"finest {finest.value:g} {finest.unit})"
        )

__delattr__(name)

Refuse attribute deletion -- a Moc is immutable.

Source code in mortie/moc_object.py
446
447
448
def __delattr__(self, name):
    """Refuse attribute deletion -- a Moc is immutable."""
    raise AttributeError("Moc is immutable; build a new one instead")

__eq__(other)

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

Source code in mortie/moc_object.py
655
656
657
658
659
def __eq__(self, other):
    """Compare canonical words -- word identity, not geometric equality."""
    if not isinstance(other, Moc):
        return NotImplemented
    return np.array_equal(self.words, other.words)

__hash__()

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

Source code in mortie/moc_object.py
661
662
663
def __hash__(self):
    """Hash the canonical words; sound because a Moc is immutable."""
    return hash(self.words.tobytes())

__iter__()

Iterate the cover's morton words.

Source code in mortie/moc_object.py
669
670
671
def __iter__(self):
    """Iterate the cover's morton words."""
    return iter(self.words)

__len__()

Count the cells in the cover.

Source code in mortie/moc_object.py
665
666
667
def __len__(self):
    """Count the cells in the cover."""
    return int(self.words.size)

__morton_moc__()

Canonical morton words — the interchange protocol (issue #196).

Returns:

Type Description
ndarray

The read-only uint64 word array backing this cover.

Source code in mortie/moc_object.py
645
646
647
648
649
650
651
652
653
def __morton_moc__(self):
    """Canonical morton words — the interchange protocol (issue #196).

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

__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 Moc picklable (workers marshal their arguments) and deep-copyable at the cost of one compress_moc on already-compact words.

Returns:

Type Description
tuple

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

Source code in mortie/moc_object.py
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
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 ``Moc`` picklable (workers marshal their arguments) and
    deep-copyable at the cost of one ``compress_moc`` on already-compact
    words.

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

__repr__()

Show the cell count and the orders actually present.

Source code in mortie/moc_object.py
673
674
675
676
677
678
679
680
681
682
683
684
def __repr__(self):
    """Show the cell count and the orders actually present."""
    if self.words.size == 0:
        return "Moc(0 cells)"
    orders = orders_of(self.words)
    low, high = int(orders.min()), int(orders.max())
    span = f"order {low}" if low == high else f"orders {low}-{high}"
    finest = res2display(high)[-1]
    return (
        f"Moc({self.words.size} cells, {span}, "
        f"finest {finest.value:g} {finest.unit})"
    )

__setattr__(name, value)

Refuse attribute assignment -- a Moc is immutable.

Source code in mortie/moc_object.py
440
441
442
443
444
def __setattr__(self, name, value):
    """Refuse attribute assignment -- a Moc is immutable."""
    raise AttributeError(
        "Moc is immutable (its hash is its words); build a new one instead"
    )

contains(other)

Whether every cell of other lies inside this cover.

Cover algebra, not polygon 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.

Parameters:

Name Type Description Default
other Moc or array_like

The cover to test for containment.

required

Returns:

Type Description
bool

True if other adds no area outside this cover.

Source code in mortie/moc_object.py
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
def contains(self, other):
    """Whether every cell of ``other`` lies inside this cover.

    Cover algebra, not polygon 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.

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

    Returns
    -------
    bool
        ``True`` if ``other`` adds no area outside this cover.
    """
    return moc_minus(_words(other), self.words).size == 0

difference(other)

Cells in this cover but not other (MOCpy difference, -).

Parameters:

Name Type Description Default
other Moc or array_like

The cover to subtract.

required

Returns:

Type Description
Moc

The difference cover self \ other.

Source code in mortie/moc_object.py
587
588
589
590
591
592
593
594
595
596
597
598
599
600
def difference(self, other):
    r"""Cells in this cover but not ``other`` (MOCpy ``difference``, ``-``).

    Parameters
    ----------
    other : Moc or array_like
        The cover to subtract.

    Returns
    -------
    Moc
        The difference cover ``self \ other``.
    """
    return Moc(moc_minus(self.words, _words(other)))

from_polygon(lats, lons, tolerance=None, max_cells=None, *, latitude='authalic') classmethod

Cover a polygon given as vertex latitudes and longitudes.

The MOCpy-vocabulary spelling of the coverage constructor, for callers who already have (lats, lons) rather than GeoJSON. Multipart / holes take the list-of-rings form, exactly as :func:~mortie.morton_coverage_moc documents.

Parameters:

Name Type Description Default
lats array_like

Vertex latitudes / longitudes in degrees (one ring), or a list of such arrays for the multipart form.

required
lons array_like

Vertex latitudes / longitudes in degrees (one ring), or a list of such arrays for the multipart form.

required
tolerance float

Angular stop criterion in degrees.

None
max_cells int

Best-first cell budget for the boundary.

None
latitude str

Latitude convention of the input vertices (default "authalic").

'authalic'

Returns:

Type Description
Moc

The polygon's multi-order cover.

Source code in mortie/moc_object.py
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
@classmethod
def from_polygon(cls, lats, lons, tolerance=None, max_cells=None, *,
                 latitude="authalic"):
    """Cover a polygon given as vertex latitudes and longitudes.

    The MOCpy-vocabulary spelling of the coverage constructor, for callers
    who already have ``(lats, lons)`` rather than GeoJSON.  Multipart /
    holes take the list-of-rings form, exactly as
    :func:`~mortie.morton_coverage_moc` documents.

    Parameters
    ----------
    lats, lons : array_like
        Vertex latitudes / longitudes in degrees (one ring), or a list of
        such arrays for the multipart form.
    tolerance : float, optional
        Angular stop criterion in degrees.
    max_cells : int, optional
        Best-first cell budget for the boundary.
    latitude : str, optional
        Latitude convention of the input vertices (default
        ``"authalic"``).

    Returns
    -------
    Moc
        The polygon's multi-order cover.
    """
    return cls(
        morton_coverage_moc(
            lats, lons, tolerance=tolerance, max_cells=max_cells,
            latitude=latitude,
        )
    )

intersection(other)

Cells in both this cover and other (MOCpy intersection, &).

Parameters:

Name Type Description Default
other Moc or array_like

The cover to intersect with.

required

Returns:

Type Description
Moc

The intersection cover.

Source code in mortie/moc_object.py
572
573
574
575
576
577
578
579
580
581
582
583
584
585
def intersection(self, other):
    """Cells in both this cover and ``other`` (MOCpy ``intersection``, ``&``).

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

    Returns
    -------
    Moc
        The intersection cover.
    """
    return Moc(moc_and(self.words, _words(other)))

intersects(other)

Whether this cover and other share any area, at any order.

Cover algebra, not polygon algebra — see the module docstring's conservative-direction table: True can mean "within a cell of each other", False is decisive.

Parameters:

Name Type Description Default
other Moc or array_like

The cover to test against.

required

Returns:

Type Description
bool

True if the two covers overlap anywhere.

Source code in mortie/moc_object.py
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
def intersects(self, other):
    """Whether this cover and ``other`` share any area, at any order.

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

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

    Returns
    -------
    bool
        ``True`` if the two covers overlap anywhere.
    """
    return moc_intersects(self.words, _words(other))

symmetric_difference(other)

Cells in exactly one of the two covers (MOCpy symmetric_difference, ^).

Parameters:

Name Type Description Default
other Moc or array_like

The cover to compare against.

required

Returns:

Type Description
Moc

The symmetric-difference cover.

Source code in mortie/moc_object.py
602
603
604
605
606
607
608
609
610
611
612
613
614
615
def symmetric_difference(self, other):
    """Cells in exactly one of the two covers (MOCpy ``symmetric_difference``, ``^``).

    Parameters
    ----------
    other : Moc or array_like
        The cover to compare against.

    Returns
    -------
    Moc
        The symmetric-difference cover.
    """
    return Moc(moc_xor(self.words, _words(other)))

to_order(order, max_cells=_FLAT_COVER_WARN_THRESHOLD)

Cast to a flat list of cells at one fixed order.

The consumer-grid direction: a multi-order cover in, every cell at order out, as the canonical uint64 array — a flat single-order cell list is not a MOC, and re-normalizing it would collapse it straight back to the compact form.

Parameters:

Name Type Description Default
order int

Target HEALPix order (0-29).

required
max_cells int or None

Pre-emptive budget on the densified cell count; see :func:~mortie.moc_to_order. None opts out.

_FLAT_COVER_WARN_THRESHOLD

Returns:

Type Description
ndarray

Sorted 1-D array of flat morton cells at order (uint64).

Source code in mortie/moc_object.py
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
def to_order(self, order, max_cells=_FLAT_COVER_WARN_THRESHOLD):
    """Cast to a flat list of cells at one fixed ``order``.

    The consumer-grid direction: a multi-order cover in, every cell at
    ``order`` out, as the canonical ``uint64`` **array** — a flat
    single-order cell list is not a MOC, and re-normalizing it would
    collapse it straight back to the compact form.

    Parameters
    ----------
    order : int
        Target HEALPix order (0-29).
    max_cells : int or None, optional
        Pre-emptive budget on the densified cell count; see
        :func:`~mortie.moc_to_order`.  ``None`` opts out.

    Returns
    -------
    numpy.ndarray
        Sorted 1-D array of flat morton cells at ``order`` (``uint64``).
    """
    return moc_to_order(self.words, order, max_cells)

union(other)

Cells in this cover or in other (MOCpy union, |).

Parameters:

Name Type Description Default
other Moc or array_like

The cover to union with.

required

Returns:

Type Description
Moc

The union cover.

Source code in mortie/moc_object.py
557
558
559
560
561
562
563
564
565
566
567
568
569
570
def union(self, other):
    """Cells in this cover or in ``other`` (MOCpy ``union``, ``|``).

    Parameters
    ----------
    other : Moc or array_like
        The cover to union with.

    Returns
    -------
    Moc
        The union cover.
    """
    return Moc(moc_or(self.words, _words(other)))

within(other)

Whether every cell of this cover lies inside other.

The mirror of :meth:contains; the same conservative direction applies (module docstring).

Parameters:

Name Type Description Default
other Moc or array_like

The cover to test containment against.

required

Returns:

Type Description
bool

True if this cover adds no area outside other.

Source code in mortie/moc_object.py
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
def within(self, other):
    """Whether every cell of this cover lies inside ``other``.

    The mirror of :meth:`contains`; the same conservative direction
    applies (module docstring).

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

    Returns
    -------
    bool
        ``True`` if this cover adds no area outside ``other``.
    """
    return moc_minus(self.words, _words(other)).size == 0