Pixel functions
In this section we document the functions that convert from a direction in the sky into a pixel index, and vice versa.
First of all, Healpix.jl implements the most basic functions to convert between spherical and Cartesian coordinates. Note that Healpix uses co-latitude instead of latitude:
julia> ang2vec(0.0, 0.0)
(0.0, 0.0, 1.0)
julia> vec2ang(0.0, 0.0, 1.0)
(0.0, 0.0)
More interesting functions return the index of the pixel on a Healpix-tessellated sphere. For these functions to work, you have to provide a Resolution
object:
julia> res = Resolution(16)
Healpix resolution(NSIDE = 16)
julia> ang2pixRing(res, π/2, 0)
1441
julia> ang2pixNest(res, π/2, 0)
1217
Ring functions
The Healpix projection has the advantage of storing pixels along iso-latitude rings; this allows to implement efficient spherical-transform functions. Healpix.jl provides a number of functions that manage rings. Many of them use the RingInfo
structure, which encodes details about a ring.
Healpix.RingInfo
— TypeRingInfo
Information about a ring of pixels, i.e., the set of pixels on a Healpix map which have the same colatitude. The type is "mutable", so that one object can begin reused many times without further memory allocations.
The list of fields defined in this structure is the following:
ring
: an integer index, running fromfirstPixIdx
: index of the first pixel (using theRING
scheme) belonging to this ringnumOfPixels
: number of consecutive pixels within the ringcolatitude_rad
: value of the colatitude for this ring (in radians)shifted
: Boolean flag; it istrue
if the longitude of the first pixel in the ring is not zero.
References
See also getringinfo!
and getringinfo
.
Example
import Healpix
res = Healpix.Resolution(256)
# Show information about ring #10
print(getringinfo(res, 10))
Healpix.getringinfo
— Functiongetringinfo(resol::Resolution, ring; kwargs...) :: RingInfo
Return a RingInfo structure containing information about the specified ring. For the list of accepted keyword arguments, see getringinfo!.
Healpix.getringinfo!
— Functiongetringinfo!(resol::Resolution, ring, ringinfo::RingInfo; full=true) :: RingInfo
Fill the RingInfo structure with information about the specified ring. If full
is false
, the field colatitude_rad
(the most expensive in terms of computation) is set to NaN
.
Healpix.getinterpolRing
— FunctiongetinterpolRing(resol::Resolution, θ, ϕ) -> (Array{Int,1}, Array{Float64, 1})
getinterpolRing!(resol::Resolution, θ, ϕ, pix, weights) -> (Array{Int,1}, Array{Float64, 1})
Return the indices and the weights of the four neighbour pixels for the given direction (θ, ϕ) in a map with the specified resolution.
If provided, the parameters pix
and weights
should point to two 4-element arrays of integers and floating-points, respectively. They can be reused in multiple calls to avoid heap allocations and speed up the code.
Pixel boundaries
It is sometimes useful to be able to trace the border of a pixel: this can be useful for plotting purposes. Healpix.jl implements the boundariesRing!
and boundariesRing
functions for this purpose. They calculate a set of $N$ vectors pointing to a number of points along the border of a given pixel and return them as a $N\times 3$ matrix.
Here is a visual example:
using Plots
pyplot() # hide
using Healpix # hide
pointsperside = 10
matr = boundariesRing(Resolution(2), 3, pointsperside, Float32)
scatter(matr[:, 1], matr[:, 2], matr[:, 3])
savefig(joinpath("images", "pixelboundaries1.png")) # hide
We can cycle this over all the pixels in a map; however, using boundariesRing
will require the result matrix to be allocated again and again for each pixel. Here boundariesRing!
comes to the rescue, as we can pre-allocate the matrix and then pass it to each call within the for
loop:
using Plots
pyplot() # hide
using Healpix # hide
pointsperside = 10
matr = Matrix{Float32}(undef, 4pointsperside, 3)
resol = Resolution(2)
scatter()
for pixidx in 1:resol.numOfPixels
boundariesRing!(resol, pixidx, pointsperside, matr)
scatter!(matr[:, 1], matr[:, 2], matr[:, 3], label="")
end
savefig(joinpath("images", "pixelboundariesall.png")) # hide
Reference
Healpix.ang2vec
— Methodang2vec(theta, phi) -> Array{Float64}
Given a direction in the sky with colatitude theta
and longitude phi
(in radians), return an array of 3 elements containing the x
, y
, and z
components of the one-length vector pointing to that direction.
Healpix.vec2ang
— Methodvec2ang(x, y, z) -> (Number, Number)
Given a vector (not necessarily normalized) whose Cartesian components are x
, y
, and z
, return a pair (theta
, phi
) containing the colatitude theta
and the longitude phi
(in radians) of the direction in the sky the vector is pointing at.
Healpix.ang2pixNest
— Methodang2pixNest(resol::Resolution, theta, phi) -> Integer
Return the index of the pixel which contains the point with coordinates (theta
, the colatitude, and phi
, the longitude), in radians, for a Healpix map with pixels in nested order. Note that pixel indexes are 1-based (this is Julia)!
Healpix.zphi2pixRing
— Methodzphi2pixRing(resol::Resolution, theta, phi) -> Integer
Return the index of the pixel which contains the point with coordinates (theta
, the colatitude, and phi
, the longitude), in radians, for a Healpix map with pixels in ring order. Note that pixel indexes are 1-based (this is Julia)!
Healpix.ang2pixRing
— Methodang2pixRing(resol::Resolution, theta, phi) -> Integer
Return the index of the pixel which contains the point with coordinates (theta
, the colatitude, and phi
, the longitude), in radians, for a Healpix map with pixels in ring order. Note that pixel indexes are 1-based (this is Julia)!
Healpix.pix2angNest
— Methodpix2angNest(resol::Resolution, pixel) -> (Float64, Float64)
Given the (1-based) index of a pixel in a Healpix map in nested order, return a pair containing the (colatitude
, longitude
) angles corresponding to its center, both expressed in radians.
Healpix.pix2angRing
— Methodpix2angRing(resol::Resolution, pixel) -> (Float64, Float64)
Given the (1-based) index of a pixel in a Healpix map in ring order, return a pair containing the (colatitude
, longitude
) angles corresponding to its center, both expressed in radians.
Healpix.ring2nest
— Methodring2nest(resol::Resolution, ipix) :: Int
Convert the number of a pixel from RING to NESTED scheme.
Healpix.nest2ring
— Methodnest2ring(resol::Resolution, ipix) :: Int
Convert the number of a pixel from NESTED to RING scheme.
Healpix.pix2ringpos
— Methodpix2ringpos(resol::Resolution, pixel)
Given the (1-based) index of a pixel in a Healpix map in ring order, return a pair of numbers (n, i, j) whose meaning is the following:
n
can be one of the symbols:northcap
,:equator
, or:southcap
, representing the region of the skyi
is the ring index, from 1 to 4NSIDE - 1j
is the pixel-in-ring index
Healpix.pix2xyfNest
— Methodpix2xyfNest(resol::Resolution, ipix) :: (Int, Int, Int)
Convert a pixel number into (x, y, face), using NESTED ordering.
Healpix.pix2xyfRing
— Methodpix2xyfRing(resol::Resolution, ipix) :: (Int, Int, Int)
Convert a pixel number into (x, y, face), using RING ordering.
Healpix.xyf2pixNest
— Methodxyf2pixNest(resol::Resolution, ix, iy, facenum) :: Int
Convert (x, y, face) into a pixel number, using NESTED ordering.
Healpix.xyf2pixRing
— Methodxyf2pixRing(resol::Resolution, ix, iy, facenum) :: Int
Convert (x, y, face) into a pixel number, using RING ordering.
Healpix.xyf2loc
— Functionxyf2loc(x, y, face) -> (z, phi, sintheta, have_sintheta)
Given a position encoded as XYF, return the tuple containing $z = cos(\theta)$, \phi
, and optionally an accurate estimate for $sin(\theta)$ (if have_sintheta
is true
), where $\theta$ is the colatitude and $\phi$ is the longitude, both expressed in radians.
Healpix.pix2zphiRing
— Methodpix2zphiRing(res::Resolution, pix) -> (z, phi)
Compute the angular coordinates z = cos(θ), ϕ
of the center of the pixel with number pix
, assuming the RING
numbering scheme for pixels. Caution: this method is inaccurate near the poles at high resolutions.
Healpix.pix2zphiNest
— Methodpix2zphiNest(res::Resolution, pix) -> (z, phi)
Compute the angular coordinates z = cos(θ), ϕ
of the center of the pixel with number pix
, assuming the NEST
numbering scheme for pixels. Caution: this method is inaccurate near the poles at high resolutions.
Healpix.ringAbove
— FunctionringAbove(res::Resolution, z) -> (ring_number)
Return the number of the next ring to the north of z = cos(θ)
. If z
lies north of all rings, the function returns 0.
Healpix.ring2z
— Functionring2z(res::Resolution, ring) -> z
Return the value of z = \cos(\theta)
for the given ring.
Healpix.numOfRings
— FunctionnumOfRings(resol::Resolution)
numOfRings(nside::Integer)
Return the number of horizontal rings in a Healpix map.
Healpix.max_pixrad
— Functionmax_pixrad(res::Resolution, ring)
max_pixrad(res::Resolution)
Return the maximum angular distance (in radians) between a pixel center and any of its corners. If ring
is specified, the result applies to all the pixels of the given ring; otherwise, all the pixels on the sphere are considered.
Healpix.boundariesRing
— FunctionboundariesRing(resol::Resolution, pix, step, T::Type{<:Real})
boundariesRing!(resol::Resolution, pix, step, buf::Matrix{T}) where {T <: Real}
Compute a set of directions (3D vectors) along the boundaries of a given pixel in the RING scheme at some resolution.
The function boundariesRing
returns a $N \times 3$ matrix of type T
containing $N$ vectors pointing towards the border of the pixel with index pix
in RING scheme. Each edge of the pixel contains step
points, and, as every pixel has a diamond-like shape with four edges, the number $N$ is equal to 4 * step
.
If you plan to call this function again and again, you should allocate your own matrix with the results and call boundariesRing!
, which accepts the parameter buf
where the result will be stored. The shape of this matrix must be (4step, 3)
, for instance, and its element can be left undefined:
step = 10
buf = Matrix{Float64}(undef, 4step, 3)
boundariesRing!(res, pixidx, step, buf) # This sets `buf`
Examples
Here we show how to use boundariesRing
and boundariesRing!
together to avoid allocating a matrix twice.
julia> matr = boundariesRing(Resolution(16), 534, 2, Float16)
8×3 Matrix{Float16}:
0.3535 -0.6123 0.707
0.3525 -0.6353 0.687
0.3513 -0.657 0.6665
0.3762 -0.664 0.646
0.4014 -0.6694 0.625
0.4084 -0.645 0.646
0.414 -0.6196 0.6665
0.3843 -0.6167 0.687
julia> boundariesRing!(Resolution(16), 535, 2, matr) # Reuse `matr`
julia> matr
8×3 Matrix{Float16}:
0.4158 -0.5723 0.707
0.415 -0.596 0.687
0.414 -0.6196 0.6665
0.4397 -0.624 0.646
0.465 -0.627 0.625
0.4697 -0.602 0.646
0.473 -0.576 0.6665
0.4446 -0.5747 0.687
Healpix.boundariesRing!
— FunctionboundariesRing!(resol::Resolution, pix, step, buf::Matrix{T}) where {T <: Real}
See the documentation for boundariesRing
.