Skip to content

moczarr.ranges

Interval substrate for the MOC-backed lazy index — numpy-only, no I/O.

The lazy index (phase 5, espg/moczarr#1) holds open_hive's row domain as a set of intervals instead of a materialized morton coordinate. zagg leaves are dense within a shard, so the domain is pure arithmetic: shard word → one contiguous subtree run at cell_order, AOI intersection → interval intersection. No cell arrays are read to know the coordinate.

Rank space, not word space (the phase-5 probe finding): packed morton words at a fixed cell order are NOT unit-stride across a shard subtree — mortie packs the base+digit field MSB-aligned with an order marker in the low bits, so consecutive rank tails differ by a large power-of-two stride. But word >> shift (the base+digit field alone) IS unit-stride: it is a global rank coordinate K at the cell order, contiguous across rank-consecutive shard subtrees (verified across sibling and parent-crossing boundaries) and monotonic everywhere words are. Base blocks are mutually contiguous in K — mortie packs +1..+6 into blocks 1..6 and -1..-6 into blocks 7..12 densely, with only block 0 unused — so _coalesce may merge intervals straight across a base or hemisphere seam (the +6/-1 boundary merges into one interval; pinned in tests/test_ranges.py). Correctness rests on that adjacency-merging being safe, not on any inter-base gap existing. All intervals here therefore live in K space, inclusive [lo, hi]; words convert at the boundaries via word = (K << shift) | marker. The (shift, marker) pair is derived empirically from mortie's own packing at construction (two morton_word calls, cached) — never hardcoded — and subtree spans are re-checked against 4**depth, so packing drift raises instead of mis-ranking.

Single cell order by construction (a store's cell coordinate is one order); mixed-order domains (pyramids, zagg#262) are the named phase-5 seam — intervals-per-order is the natural extension, gated with issue #8 on mortie#116.

MortonRanges

A sorted disjoint interval set over morton cells at one fixed order.

The four ops the lazy index needs — membership, rank, positional take, interval intersect — are all searchsorted/cumsum arithmetic on the (n, 2) K-space intervals array. The concatenated ascending run of all covered cells is the domain: rank maps words to domain positions, take maps positions back, fabricate materializes the whole thing (the only op that allocates O(size)).

Source code in src/moczarr/ranges.py
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
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
class MortonRanges:
    """A sorted disjoint interval set over morton cells at one fixed order.

    The four ops the lazy index needs — membership, rank, positional take,
    interval intersect — are all searchsorted/cumsum arithmetic on the
    ``(n, 2)`` K-space ``intervals`` array. The concatenated ascending run of
    all covered cells is the *domain*: ``rank`` maps words to domain
    positions, ``take`` maps positions back, ``fabricate`` materializes the
    whole thing (the only op that allocates O(size)).
    """

    __slots__ = ("intervals", "cell_order", "_shift", "_marker", "_offsets")

    def __init__(self, intervals, cell_order: int):
        self.cell_order = int(cell_order)
        self._shift, self._marker = _shift_and_marker(self.cell_order)
        self.intervals = _coalesce(intervals)
        sizes = self.intervals[:, 1] - self.intervals[:, 0] + np.uint64(1)
        self._offsets = np.concatenate([np.zeros(1, dtype=np.uint64), np.cumsum(sizes)])

    # -- constructors -----------------------------------------------------

    @classmethod
    def from_shards(cls, shard_words, cell_order: int) -> "MortonRanges":
        """Subtree runs of shard words: one interval per shard at ``cell_order``.

        Shards may sit at any order <= ``cell_order`` (each word carries its
        own); duplicates and rank-adjacent shards merge. Every subtree span
        is re-checked against ``4**depth`` (the packing-drift guard).
        """
        shift, _ = _shift_and_marker(cell_order)
        intervals = []
        for word in np.unique(np.asarray(shard_words, dtype=np.uint64).ravel()):
            decimal = morton_decimal(int(word))
            depth = int(cell_order) - decimal_order(decimal)
            if depth < 0:
                raise ValueError(
                    f"shard {decimal} sits below cell_order {cell_order} "
                    f"(order {decimal_order(decimal)})"
                )
            lo = morton_word(decimal + "1" * depth) >> shift
            hi = morton_word(decimal + "4" * depth) >> shift
            if hi - lo + 1 != 4**depth:
                raise AssertionError(
                    f"mortie packing drift: subtree of {decimal} spans {hi - lo + 1} "
                    f"ranks at order {cell_order}, expected {4**depth}"
                )
            intervals.append((lo, hi))
        return cls(np.asarray(intervals, dtype=np.uint64).reshape(-1, 2), cell_order)

    @classmethod
    def from_root_coverage(cls, envelope: dict, cell_order: int) -> "MortonRanges":
        """The domain a root ``"ranges"`` envelope declares, at ``cell_order``.

        One interval per envelope range, WITHOUT the O(covered shards)
        expansion of :func:`moczarr.coverage.ranges_words`: consecutive-rank
        shard subtrees are contiguous in K space, so ``[lo_shard, hi_shard]``
        maps to ``[first cell of lo, last cell of hi]`` directly. Same
        validation posture as ``ranges_words`` — malformed ranges raise (a
        corrupt cache must never yield a plausible partial domain) — plus
        the span re-check as the packing-drift guard.
        """
        order = int(envelope["order"])
        depth = int(cell_order) - order
        if depth < 0:
            raise ValueError(f"envelope order {order} is below cell_order {cell_order}")
        shift, _ = _shift_and_marker(cell_order)
        intervals = []
        for lo_dec, hi_dec in envelope["ranges"]:
            base = decimal_base(lo_dec)
            lo_rank, hi_rank = decimal_rank(lo_dec), decimal_rank(hi_dec)
            ok = decimal_base(hi_dec) == base and lo_rank <= hi_rank
            ok = ok and decimal_order(lo_dec) == order and decimal_order(hi_dec) == order
            if not ok:
                raise ValueError(f"malformed coverage range [{lo_dec}, {hi_dec}] at order {order}")
            lo = morton_word(lo_dec + "1" * depth) >> shift
            hi = morton_word(hi_dec + "4" * depth) >> shift
            if hi - lo + 1 != (hi_rank - lo_rank + 1) * 4**depth:
                raise AssertionError(
                    f"mortie packing drift: range [{lo_dec}, {hi_dec}] spans {hi - lo + 1} "
                    f"ranks at order {cell_order}, expected {(hi_rank - lo_rank + 1) * 4**depth}"
                )
            intervals.append((lo, hi))
        return cls(np.asarray(intervals, dtype=np.uint64).reshape(-1, 2), cell_order)

    @classmethod
    def from_cell_words(cls, words, cell_order: int | None = None) -> "MortonRanges":
        """Run-detect an explicit strictly-ascending cell-word array.

        The materialized→lazy direction (``MortonMocIndex.from_variables``).
        ``cell_order`` defaults to the order the words themselves carry;
        mixed orders or a non-ascending array raise (mirroring ``aoi_mask``'s
        raise-on-ambiguity discipline).
        """
        words = np.asarray(words, dtype=np.uint64).ravel()
        if cell_order is None:
            if words.size == 0:
                raise ValueError("cannot infer cell_order from zero words; pass it explicitly")
            from mortie import infer_order_from_morton

            cell_order = int(infer_order_from_morton(words))
        shift, marker = _shift_and_marker(int(cell_order))
        if words.size == 0:
            return cls(np.empty((0, 2), dtype=np.uint64), cell_order)
        stride = np.uint64(1) << np.uint64(shift)
        if (words & (stride - np.uint64(1)) != np.uint64(marker)).any():
            raise ValueError(f"words are not all at cell_order {cell_order} (mixed orders?)")
        if (words[1:] <= words[:-1]).any():
            raise ValueError("cell words must be strictly ascending")
        ranks = words >> np.uint64(shift)
        breaks = np.flatnonzero(np.diff(ranks) > np.uint64(1))
        first = np.concatenate([[0], breaks + 1])
        last = np.concatenate([breaks, [ranks.size - 1]])
        return cls(np.stack([ranks[first], ranks[last]], axis=1), cell_order)

    # -- interval algebra -------------------------------------------------

    def _clip(self, clip_intervals: np.ndarray) -> "MortonRanges":
        """Intersection with a coalesced K-interval array (the sweep kernel)."""
        los, his = self.intervals[:, 0], self.intervals[:, 1]
        pieces = []
        for clip_lo, clip_hi in clip_intervals:
            k0 = np.searchsorted(his, clip_lo, side="left")  # first with hi >= clip_lo
            k1 = np.searchsorted(los, clip_hi, side="right")  # first with lo > clip_hi
            if k1 > k0:
                pieces.append(
                    np.stack(
                        [np.maximum(los[k0:k1], clip_lo), np.minimum(his[k0:k1], clip_hi)],
                        axis=1,
                    )
                )
        stacked = np.concatenate(pieces) if pieces else np.empty((0, 2), dtype=np.uint64)
        return type(self)(stacked, self.cell_order)

    def _aoi_intervals(self, aoi) -> np.ndarray:
        """An AOI morton cover as coalesced K intervals at ``cell_order``.

        The two-way containment semantics of :func:`moczarr.coverage.aoi_mask`
        in interval space: a coarser-or-equal member covers its whole subtree
        run; a finer member collapses to its containing cell (one rank).
        Members may be mixed-order; strings are accepted.
        """
        values = np.asarray(aoi).ravel() if np.asarray(aoi).ndim else np.asarray([aoi])
        intervals = []
        for value in values:
            word = morton_word(value.item() if hasattr(value, "item") else value)
            decimal = morton_decimal(word)
            depth = self.cell_order - decimal_order(decimal)
            if depth >= 0:
                lo = morton_word(decimal + "1" * depth) >> self._shift
                hi = morton_word(decimal + "4" * depth) >> self._shift
            else:
                from mortie import clip2order

                cell = clip2order(self.cell_order, np.asarray([word], dtype=np.uint64))[0]
                lo = hi = int(cell) >> self._shift
            intervals.append((lo, hi))
        return _coalesce(np.asarray(intervals, dtype=np.uint64).reshape(-1, 2))

    def intersect(self, aoi) -> "MortonRanges":
        """The sub-domain an AOI morton cover keeps — ``aoi_mask`` in interval space."""
        return self._clip(self._aoi_intervals(aoi))

    def intersection(self, other: "MortonRanges") -> "MortonRanges":
        """Set intersection with another interval set at the same order."""
        self._check_same_order(other)
        return self._clip(other.intervals)

    def union(self, other: "MortonRanges") -> "MortonRanges":
        """Set union with another interval set at the same order."""
        self._check_same_order(other)
        return type(self)(np.concatenate([self.intervals, other.intervals]), self.cell_order)

    def _check_same_order(self, other: "MortonRanges") -> None:
        if not isinstance(other, MortonRanges):
            raise TypeError(f"expected MortonRanges, got {type(other).__name__}")
        if other.cell_order != self.cell_order:
            raise ValueError(
                f"mixed cell orders ({self.cell_order} vs {other.cell_order}); "
                f"intervals-per-order is the deferred pyramid seam (issue #8)"
            )

    # -- domain arithmetic ------------------------------------------------

    @property
    def size(self) -> int:
        """Number of cells in the domain."""
        return int(self._offsets[-1])

    def _locate(self, words) -> tuple[np.ndarray, np.ndarray]:
        """``(interval index, member mask)`` of words; index only valid where member."""
        words = np.asarray(words, dtype=np.uint64).ravel()
        if self.intervals.size == 0:
            return np.zeros(words.size, dtype=np.intp), np.zeros(words.size, dtype=bool)
        stride = np.uint64(1) << np.uint64(self._shift)
        ranks = words >> np.uint64(self._shift)
        idx = np.searchsorted(self.intervals[:, 0], ranks, side="right")
        good = idx > 0
        idx = np.maximum(idx, 1) - 1
        good &= ranks <= self.intervals[idx, 1]
        good &= (words & (stride - np.uint64(1))) == np.uint64(self._marker)
        return idx, good

    def member(self, words) -> np.ndarray:
        """Boolean mask: which words the domain contains (order marker included)."""
        _, good = self._locate(words)
        return good

    def rank(self, words, missing: int | None = None) -> np.ndarray:
        """Positions of words in the ascending domain (``int64``).

        Non-members raise ``KeyError`` by default; ``missing=<fill>`` maps
        them to that value instead (the reindex posture).
        """
        words = np.asarray(words, dtype=np.uint64).ravel()
        idx, good = self._locate(words)
        if not good.all() and missing is None:
            bad = words[~good][0]
            raise KeyError(f"{morton_decimal(int(bad))} (word {int(bad)}) is not in the domain")
        if self.intervals.size == 0:
            return np.full(words.size, missing if missing is not None else 0, dtype=np.int64)
        ranks = words >> np.uint64(self._shift)
        positions = (self._offsets[idx] + (ranks - self.intervals[idx, 0])).astype(np.int64)
        if missing is not None:
            positions[~good] = missing
        return positions

    def take(self, positions) -> np.ndarray:
        """Words at domain positions (``uint64``); negatives wrap, OOB raises."""
        positions = np.asarray(positions, dtype=np.int64).ravel()
        positions = np.where(positions < 0, positions + self.size, positions)
        if positions.size and ((positions < 0).any() or (positions >= self.size).any()):
            raise IndexError(f"position out of bounds for domain of size {self.size}")
        upos = positions.astype(np.uint64)
        idx = np.searchsorted(self._offsets, upos, side="right") - 1
        ranks = self.intervals[idx, 0] + (upos - self._offsets[idx])
        return (ranks << np.uint64(self._shift)) | np.uint64(self._marker)

    def subset(self, indexer) -> "MortonRanges":
        """The sub-domain at positional ``indexer`` (slice or integer array).

        A unit-step slice clips intervals in position space (no
        materialization). Integer arrays must be strictly increasing after
        negative-wrap — an interval set has no reordering freedom — so a
        non-monotonic or duplicated indexer raises ``ValueError`` (the index
        layer degrades to dropping the lazy index in that case).
        """
        if isinstance(indexer, slice):
            start, stop, step = indexer.indices(self.size)
            if step == 1:
                if stop <= start:
                    return type(self)(np.empty((0, 2), dtype=np.uint64), self.cell_order)
                lo = self.take([start])[0] >> np.uint64(self._shift)
                hi = self.take([stop - 1])[0] >> np.uint64(self._shift)
                return self._clip(np.asarray([[lo, hi]], dtype=np.uint64))
            indexer = np.arange(start, stop, step, dtype=np.int64)
        positions = np.asarray(indexer, dtype=np.int64).ravel()
        positions = np.where(positions < 0, positions + self.size, positions)
        if positions.size and (np.diff(positions) <= 0).any():
            raise ValueError(
                "an interval set cannot represent a non-increasing or duplicated "
                "positional indexer; materialize the coordinate instead"
            )
        return type(self).from_cell_words(self.take(positions), self.cell_order)

    def fabricate(self) -> np.ndarray:
        """Materialize the whole domain as ascending packed words (``uint64``).

        The one O(size) allocation; byte-equal to the coordinate the eager
        opener builds (the phase-5 money property).
        """
        parts = [np.arange(lo, hi + np.uint64(1), dtype=np.uint64) for lo, hi in self.intervals]
        ranks = np.concatenate(parts) if parts else np.empty(0, dtype=np.uint64)
        return (ranks << np.uint64(self._shift)) | np.uint64(self._marker)

    # -- comparison / repr ------------------------------------------------

    def equals(self, other: object) -> bool:
        """Same domain: same cell order and identical intervals."""
        return (
            isinstance(other, MortonRanges)
            and other.cell_order == self.cell_order
            and np.array_equal(other.intervals, self.intervals)
        )

    def __repr__(self) -> str:
        return (
            f"MortonRanges(order={self.cell_order}, ranges={len(self.intervals)}, size={self.size})"
        )

size property

Number of cells in the domain.

equals(other)

Same domain: same cell order and identical intervals.

Source code in src/moczarr/ranges.py
382
383
384
385
386
387
388
def equals(self, other: object) -> bool:
    """Same domain: same cell order and identical intervals."""
    return (
        isinstance(other, MortonRanges)
        and other.cell_order == self.cell_order
        and np.array_equal(other.intervals, self.intervals)
    )

fabricate()

Materialize the whole domain as ascending packed words (uint64).

The one O(size) allocation; byte-equal to the coordinate the eager opener builds (the phase-5 money property).

Source code in src/moczarr/ranges.py
370
371
372
373
374
375
376
377
378
def fabricate(self) -> np.ndarray:
    """Materialize the whole domain as ascending packed words (``uint64``).

    The one O(size) allocation; byte-equal to the coordinate the eager
    opener builds (the phase-5 money property).
    """
    parts = [np.arange(lo, hi + np.uint64(1), dtype=np.uint64) for lo, hi in self.intervals]
    ranks = np.concatenate(parts) if parts else np.empty(0, dtype=np.uint64)
    return (ranks << np.uint64(self._shift)) | np.uint64(self._marker)

from_cell_words(words, cell_order=None) classmethod

Run-detect an explicit strictly-ascending cell-word array.

The materialized→lazy direction (MortonMocIndex.from_variables). cell_order defaults to the order the words themselves carry; mixed orders or a non-ascending array raise (mirroring aoi_mask's raise-on-ambiguity discipline).

Source code in src/moczarr/ranges.py
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
@classmethod
def from_cell_words(cls, words, cell_order: int | None = None) -> "MortonRanges":
    """Run-detect an explicit strictly-ascending cell-word array.

    The materialized→lazy direction (``MortonMocIndex.from_variables``).
    ``cell_order`` defaults to the order the words themselves carry;
    mixed orders or a non-ascending array raise (mirroring ``aoi_mask``'s
    raise-on-ambiguity discipline).
    """
    words = np.asarray(words, dtype=np.uint64).ravel()
    if cell_order is None:
        if words.size == 0:
            raise ValueError("cannot infer cell_order from zero words; pass it explicitly")
        from mortie import infer_order_from_morton

        cell_order = int(infer_order_from_morton(words))
    shift, marker = _shift_and_marker(int(cell_order))
    if words.size == 0:
        return cls(np.empty((0, 2), dtype=np.uint64), cell_order)
    stride = np.uint64(1) << np.uint64(shift)
    if (words & (stride - np.uint64(1)) != np.uint64(marker)).any():
        raise ValueError(f"words are not all at cell_order {cell_order} (mixed orders?)")
    if (words[1:] <= words[:-1]).any():
        raise ValueError("cell words must be strictly ascending")
    ranks = words >> np.uint64(shift)
    breaks = np.flatnonzero(np.diff(ranks) > np.uint64(1))
    first = np.concatenate([[0], breaks + 1])
    last = np.concatenate([breaks, [ranks.size - 1]])
    return cls(np.stack([ranks[first], ranks[last]], axis=1), cell_order)

from_root_coverage(envelope, cell_order) classmethod

The domain a root "ranges" envelope declares, at cell_order.

One interval per envelope range, WITHOUT the O(covered shards) expansion of :func:moczarr.coverage.ranges_words: consecutive-rank shard subtrees are contiguous in K space, so [lo_shard, hi_shard] maps to [first cell of lo, last cell of hi] directly. Same validation posture as ranges_words — malformed ranges raise (a corrupt cache must never yield a plausible partial domain) — plus the span re-check as the packing-drift guard.

Source code in src/moczarr/ranges.py
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
@classmethod
def from_root_coverage(cls, envelope: dict, cell_order: int) -> "MortonRanges":
    """The domain a root ``"ranges"`` envelope declares, at ``cell_order``.

    One interval per envelope range, WITHOUT the O(covered shards)
    expansion of :func:`moczarr.coverage.ranges_words`: consecutive-rank
    shard subtrees are contiguous in K space, so ``[lo_shard, hi_shard]``
    maps to ``[first cell of lo, last cell of hi]`` directly. Same
    validation posture as ``ranges_words`` — malformed ranges raise (a
    corrupt cache must never yield a plausible partial domain) — plus
    the span re-check as the packing-drift guard.
    """
    order = int(envelope["order"])
    depth = int(cell_order) - order
    if depth < 0:
        raise ValueError(f"envelope order {order} is below cell_order {cell_order}")
    shift, _ = _shift_and_marker(cell_order)
    intervals = []
    for lo_dec, hi_dec in envelope["ranges"]:
        base = decimal_base(lo_dec)
        lo_rank, hi_rank = decimal_rank(lo_dec), decimal_rank(hi_dec)
        ok = decimal_base(hi_dec) == base and lo_rank <= hi_rank
        ok = ok and decimal_order(lo_dec) == order and decimal_order(hi_dec) == order
        if not ok:
            raise ValueError(f"malformed coverage range [{lo_dec}, {hi_dec}] at order {order}")
        lo = morton_word(lo_dec + "1" * depth) >> shift
        hi = morton_word(hi_dec + "4" * depth) >> shift
        if hi - lo + 1 != (hi_rank - lo_rank + 1) * 4**depth:
            raise AssertionError(
                f"mortie packing drift: range [{lo_dec}, {hi_dec}] spans {hi - lo + 1} "
                f"ranks at order {cell_order}, expected {(hi_rank - lo_rank + 1) * 4**depth}"
            )
        intervals.append((lo, hi))
    return cls(np.asarray(intervals, dtype=np.uint64).reshape(-1, 2), cell_order)

from_shards(shard_words, cell_order) classmethod

Subtree runs of shard words: one interval per shard at cell_order.

Shards may sit at any order <= cell_order (each word carries its own); duplicates and rank-adjacent shards merge. Every subtree span is re-checked against 4**depth (the packing-drift guard).

Source code in src/moczarr/ranges.py
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
@classmethod
def from_shards(cls, shard_words, cell_order: int) -> "MortonRanges":
    """Subtree runs of shard words: one interval per shard at ``cell_order``.

    Shards may sit at any order <= ``cell_order`` (each word carries its
    own); duplicates and rank-adjacent shards merge. Every subtree span
    is re-checked against ``4**depth`` (the packing-drift guard).
    """
    shift, _ = _shift_and_marker(cell_order)
    intervals = []
    for word in np.unique(np.asarray(shard_words, dtype=np.uint64).ravel()):
        decimal = morton_decimal(int(word))
        depth = int(cell_order) - decimal_order(decimal)
        if depth < 0:
            raise ValueError(
                f"shard {decimal} sits below cell_order {cell_order} "
                f"(order {decimal_order(decimal)})"
            )
        lo = morton_word(decimal + "1" * depth) >> shift
        hi = morton_word(decimal + "4" * depth) >> shift
        if hi - lo + 1 != 4**depth:
            raise AssertionError(
                f"mortie packing drift: subtree of {decimal} spans {hi - lo + 1} "
                f"ranks at order {cell_order}, expected {4**depth}"
            )
        intervals.append((lo, hi))
    return cls(np.asarray(intervals, dtype=np.uint64).reshape(-1, 2), cell_order)

intersect(aoi)

The sub-domain an AOI morton cover keeps — aoi_mask in interval space.

Source code in src/moczarr/ranges.py
264
265
266
def intersect(self, aoi) -> "MortonRanges":
    """The sub-domain an AOI morton cover keeps — ``aoi_mask`` in interval space."""
    return self._clip(self._aoi_intervals(aoi))

intersection(other)

Set intersection with another interval set at the same order.

Source code in src/moczarr/ranges.py
268
269
270
271
def intersection(self, other: "MortonRanges") -> "MortonRanges":
    """Set intersection with another interval set at the same order."""
    self._check_same_order(other)
    return self._clip(other.intervals)

member(words)

Boolean mask: which words the domain contains (order marker included).

Source code in src/moczarr/ranges.py
308
309
310
311
def member(self, words) -> np.ndarray:
    """Boolean mask: which words the domain contains (order marker included)."""
    _, good = self._locate(words)
    return good

rank(words, missing=None)

Positions of words in the ascending domain (int64).

Non-members raise KeyError by default; missing=<fill> maps them to that value instead (the reindex posture).

Source code in src/moczarr/ranges.py
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
def rank(self, words, missing: int | None = None) -> np.ndarray:
    """Positions of words in the ascending domain (``int64``).

    Non-members raise ``KeyError`` by default; ``missing=<fill>`` maps
    them to that value instead (the reindex posture).
    """
    words = np.asarray(words, dtype=np.uint64).ravel()
    idx, good = self._locate(words)
    if not good.all() and missing is None:
        bad = words[~good][0]
        raise KeyError(f"{morton_decimal(int(bad))} (word {int(bad)}) is not in the domain")
    if self.intervals.size == 0:
        return np.full(words.size, missing if missing is not None else 0, dtype=np.int64)
    ranks = words >> np.uint64(self._shift)
    positions = (self._offsets[idx] + (ranks - self.intervals[idx, 0])).astype(np.int64)
    if missing is not None:
        positions[~good] = missing
    return positions

subset(indexer)

The sub-domain at positional indexer (slice or integer array).

A unit-step slice clips intervals in position space (no materialization). Integer arrays must be strictly increasing after negative-wrap — an interval set has no reordering freedom — so a non-monotonic or duplicated indexer raises ValueError (the index layer degrades to dropping the lazy index in that case).

Source code in src/moczarr/ranges.py
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
def subset(self, indexer) -> "MortonRanges":
    """The sub-domain at positional ``indexer`` (slice or integer array).

    A unit-step slice clips intervals in position space (no
    materialization). Integer arrays must be strictly increasing after
    negative-wrap — an interval set has no reordering freedom — so a
    non-monotonic or duplicated indexer raises ``ValueError`` (the index
    layer degrades to dropping the lazy index in that case).
    """
    if isinstance(indexer, slice):
        start, stop, step = indexer.indices(self.size)
        if step == 1:
            if stop <= start:
                return type(self)(np.empty((0, 2), dtype=np.uint64), self.cell_order)
            lo = self.take([start])[0] >> np.uint64(self._shift)
            hi = self.take([stop - 1])[0] >> np.uint64(self._shift)
            return self._clip(np.asarray([[lo, hi]], dtype=np.uint64))
        indexer = np.arange(start, stop, step, dtype=np.int64)
    positions = np.asarray(indexer, dtype=np.int64).ravel()
    positions = np.where(positions < 0, positions + self.size, positions)
    if positions.size and (np.diff(positions) <= 0).any():
        raise ValueError(
            "an interval set cannot represent a non-increasing or duplicated "
            "positional indexer; materialize the coordinate instead"
        )
    return type(self).from_cell_words(self.take(positions), self.cell_order)

take(positions)

Words at domain positions (uint64); negatives wrap, OOB raises.

Source code in src/moczarr/ranges.py
332
333
334
335
336
337
338
339
340
341
def take(self, positions) -> np.ndarray:
    """Words at domain positions (``uint64``); negatives wrap, OOB raises."""
    positions = np.asarray(positions, dtype=np.int64).ravel()
    positions = np.where(positions < 0, positions + self.size, positions)
    if positions.size and ((positions < 0).any() or (positions >= self.size).any()):
        raise IndexError(f"position out of bounds for domain of size {self.size}")
    upos = positions.astype(np.uint64)
    idx = np.searchsorted(self._offsets, upos, side="right") - 1
    ranks = self.intervals[idx, 0] + (upos - self._offsets[idx])
    return (ranks << np.uint64(self._shift)) | np.uint64(self._marker)

union(other)

Set union with another interval set at the same order.

Source code in src/moczarr/ranges.py
273
274
275
276
def union(self, other: "MortonRanges") -> "MortonRanges":
    """Set union with another interval set at the same order."""
    self._check_same_order(other)
    return type(self)(np.concatenate([self.intervals, other.intervals]), self.cell_order)