Skip to content

mortie.rank_xy

Subtree-local rank <-> face-local (x, y) bit deinterleave for 2-D block views (issue #149). A depth-d subtree holds 4**d cells whose ascending packed-word order is a Z-order (morton) curve over a 2**d x 2**d block; rank_to_xy / xy_to_rank convert between a cell's rank in that block and the deinterleaved pair, matching the healpy / HEALPix C++ pix2xyf convention (origin at the subtree's south corner). The input is rank-space, not packed morton words — strip the shard prefix down to the base-4 digit-tail rank first. Normative statement: specification.md §8; the public functions ship the Rust kernel (src_rust/src/rank_xy.rs). The names stay flat on the package (mortie.rank_to_xy, mortie.xy_to_rank).

Subtree-local rank <-> face-local (x, y) bit deinterleave (issue #149).

A depth-d subtree holds 4**d cells whose ascending packed-word order is a Z-order (morton) curve over a 2**d x 2**d block. A cell's rank is its position 0..4**d - 1 within that subtree -- the same base-4 digit-tail rank the coverage bitmaps index by (docs/specification.md §7.2) -- and it interleaves the bits of a face-local (x, y) pair: x occupies the even (LSB-side) interleave bits, y the odd bits, matching the healpy / HEALPix C++ pix2xyf convention (origin at the subtree's south corner, x toward north-east, y toward north-west). The input is rank-space, not packed morton words -- strip the shard prefix first (a word carries base cell, order, and kind that these pure bit transforms would scramble).

Normative statement: docs/specification.md §8. The pure-numpy mask/shift ladder kept here (:func:_rank_to_xy_numpy / :func:_xy_to_rank_numpy) is the spec's executable reference and the golden-vector generator; the public functions ship the Rust kernel (src_rust/src/rank_xy.rs, a thin binding over the vendored healpix crate's z-order curve) per the phase-2 gate decision on issue #149.

rank_to_xy(rank, depth)

Deinterleave subtree-local ranks into face-local (x, y).

The rank's even bits (bit 0, 2, 4, ...) become x and its odd bits become y -- the healpy / HEALPix C++ pix2xyf convention, so rank_to_xy(r, d) == healpy.pix2xyf(2**d, r, nest=True)[:2] for face-0 pixels. Input is the rank within a subtree (e.g. after stripping a shard prefix), never a packed morton word.

Batch vectorized: array in, arrays out, elementwise (one shared depth).

Parameters:

Name Type Description Default
rank int or array - like

Subtree-local rank(s), each in [0, 4**depth).

required
depth int

Subtree depth (levels below the subtree root), 0-MAX_ORDER.

required

Returns:

Name Type Description
x int or ndarray

Column coordinate(s) in [0, 2**depth), uint64 for array input (scalar in -> int out, matching :func:~.mort2healpix).

y int or ndarray

Row coordinate(s) in [0, 2**depth), same convention as x.

Raises:

Type Description
ValueError

If depth is outside 0..MAX_ORDER, or any rank is negative, non-integer-typed, or >= 4**depth.

See Also

xy_to_rank : the inverse interleave.

Source code in mortie/rank_xy.py
 95
 96
 97
 98
 99
100
101
102
103
104
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
def rank_to_xy(rank, depth):
    """Deinterleave subtree-local ranks into face-local ``(x, y)``.

    The rank's even bits (bit 0, 2, 4, ...) become ``x`` and its odd bits
    become ``y`` -- the healpy / HEALPix C++ ``pix2xyf`` convention, so
    ``rank_to_xy(r, d) == healpy.pix2xyf(2**d, r, nest=True)[:2]`` for
    face-0 pixels. Input is the rank *within* a subtree (e.g. after
    stripping a shard prefix), never a packed morton word.

    **Batch vectorized**: array in, arrays out, elementwise (one shared
    ``depth``).

    Parameters
    ----------
    rank : int or array-like
        Subtree-local rank(s), each in ``[0, 4**depth)``.
    depth : int
        Subtree depth (levels below the subtree root), 0-``MAX_ORDER``.

    Returns
    -------
    x : int or ndarray
        Column coordinate(s) in ``[0, 2**depth)``, ``uint64`` for array
        input (scalar in -> ``int`` out, matching :func:`~.mort2healpix`).
    y : int or ndarray
        Row coordinate(s) in ``[0, 2**depth)``, same convention as ``x``.

    Raises
    ------
    ValueError
        If ``depth`` is outside ``0..MAX_ORDER``, or any rank is negative,
        non-integer-typed, or ``>= 4**depth``.

    See Also
    --------
    xy_to_rank : the inverse interleave.
    """
    depth = _check_depth(depth)
    is_scalar = np.isscalar(rank)
    r = _as_uint64(rank, "rank", 1 << (2 * depth))
    x, y = _rust_rank_to_xy(np.ascontiguousarray(r.ravel()), depth)
    x, y = x.reshape(r.shape), y.reshape(r.shape)
    if is_scalar:
        return int(x[0]), int(y[0])
    return x, y

xy_to_rank(x, y, depth)

Interleave face-local (x, y) into subtree-local ranks.

The exact inverse of :func:rank_to_xy: x supplies the even bits of the rank, y the odd bits (healpy / HEALPix C++ xyf2pix convention). x and y broadcast against each other.

Batch vectorized: array in, array out, elementwise (one shared depth).

Parameters:

Name Type Description Default
x int or array - like

Column coordinate(s), each in [0, 2**depth).

required
y int or array - like

Row coordinate(s), each in [0, 2**depth).

required
depth int

Subtree depth (levels below the subtree root), 0-MAX_ORDER.

required

Returns:

Type Description
int or ndarray

Subtree-local rank(s) in [0, 4**depth), uint64 for array input (scalar in -> int out, matching :func:~.mort2healpix).

Raises:

Type Description
ValueError

If depth is outside 0..MAX_ORDER, or any coordinate is negative, non-integer-typed, or >= 2**depth.

See Also

rank_to_xy : the inverse deinterleave.

Source code in mortie/rank_xy.py
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
def xy_to_rank(x, y, depth):
    """Interleave face-local ``(x, y)`` into subtree-local ranks.

    The exact inverse of :func:`rank_to_xy`: ``x`` supplies the even bits
    of the rank, ``y`` the odd bits (healpy / HEALPix C++ ``xyf2pix``
    convention). ``x`` and ``y`` broadcast against each other.

    **Batch vectorized**: array in, array out, elementwise (one shared
    ``depth``).

    Parameters
    ----------
    x : int or array-like
        Column coordinate(s), each in ``[0, 2**depth)``.
    y : int or array-like
        Row coordinate(s), each in ``[0, 2**depth)``.
    depth : int
        Subtree depth (levels below the subtree root), 0-``MAX_ORDER``.

    Returns
    -------
    int or ndarray
        Subtree-local rank(s) in ``[0, 4**depth)``, ``uint64`` for array
        input (scalar in -> ``int`` out, matching :func:`~.mort2healpix`).

    Raises
    ------
    ValueError
        If ``depth`` is outside ``0..MAX_ORDER``, or any coordinate is
        negative, non-integer-typed, or ``>= 2**depth``.

    See Also
    --------
    rank_to_xy : the inverse deinterleave.
    """
    depth = _check_depth(depth)
    is_scalar = np.isscalar(x) and np.isscalar(y)
    xs, ys = np.broadcast_arrays(_as_uint64(x, "x", 1 << depth),
                                 _as_uint64(y, "y", 1 << depth))
    rank = _rust_xy_to_rank(np.ascontiguousarray(xs.ravel()),
                            np.ascontiguousarray(ys.ravel()), depth)
    rank = rank.reshape(xs.shape)
    if is_scalar:
        return int(rank[0])
    return rank