Coverage for python/lsst/sims/utils/htmModule.py : 94%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" This module implements utilities to convert between RA, Dec and indexes on the Hierarchical Triangular Mesh (HTM), a system of tiling the unit sphere with nested triangles. The HTM is described in these references
Kunszt P., Szalay A., Thakar A. (2006) in "Mining The Sky", Banday A, Zaroubi S, Bartelmann M. eds. ESO Astrophysics Symposia https://www.researchgate.net/publication/226072008_The_Hierarchical_Triangular_Mesh
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """
"basic_trixels", "halfSpaceFromRaDec", "levelFromHtmid", "getAllTrixels"]
""" A trixel is a single triangle in the Hierarchical Triangular Mesh (HTM) tiling scheme. It is defined by its three corners on the unit sphere.
Instantiating this class directly is a bad idea. __init__() does nothing to ensure that the parameters you give it are self-consistent. Instead, use the trixelFromHtmid() or getAllTrixels() methods in this module to instantiate trixels. """
""" Initialize the current Trixel
Parameters ---------- present_htmid is the htmid of this Trixel
present_corners is a numpy array. Each row contains the Cartesian coordinates of one of this Trixel's corners.
WARNING ------- No effort is made to ensure that the parameters passed in are self consistent. You should probably not being calling __init__() directly. Use the trixelFromHtmid() or getAllTrixels() methods to instantiate trixels. """
def htmid(self): """ The unique integer identifying this trixel. """
""" Returns True if the specified RA, Dec are inside this trixel; False if not.
RA and Dec are in degrees. """
def cross01(self): """ The cross product of the unit vectors defining the zeroth and first corners of this trixel. """
def cross12(self): """ The cross product of the unit vectors defining the first and second corners of this trixel. """
def cross20(self): """ The cross product of the unit vectors defining the second and zeroth corners of this trixel. """
""" pt is a Cartesian point (not necessarily on the unit sphere).
Returns True if the point projected onto the unit sphere is contained within this trixel; False if not.
See equation 5 of
Kunszt P., Szalay A., Thakar A. (2006) in "Mining The Sky", Banday A, Zaroubi S, Bartelmann M. eds. ESO Astrophysics Symposia https://www.researchgate.net/publication/226072008_The_Hierarchical_Triangular_Mesh """
""" pts is an array of Cartesian points (pts[0] is the zeroth point, pts[1] is the first point, etc.; not necessarily on the unit sphere).
Returns an array of booleans denoting whether or not the projection of each point onto the unit sphere is contained within this trixel.
See equation 5 of
Kunszt P., Szalay A., Thakar A. (2006) in "Mining The Sky", Banday A, Zaroubi S, Bartelmann M. eds. ESO Astrophysics Symposia https://www.researchgate.net/publication/226072008_The_Hierarchical_Triangular_Mesh """ np.logical_and(np.dot(pts, self.cross12) >= 0.0, np.dot(pts, self.cross20) >= 0.0)), True, False)
""" pt is either a single Cartesian point or an array of Cartesian points (pt[0] is the zeroth point, pt[1] is the first point, etc.).
Return a boolean or array of booleans denoting whether this point(s) projected onto the unit sphere is/are contained within the current trixel. """
def w_arr(self): """ An array of vectors needed to define the child trixels of this trixel. See equation (3) of
Kunszt P., Szalay A., Thakar A. (2006) in "Mining The Sky", Banday A, Zaroubi S, Bartelmann M. eds. ESO Astrophysics Symposia httpd://www.researchgate.net/publication/226072008_The_Hierarchical_Triangular_Mesh """
def t0(self): """ The zeroth child trixel of this trixel.
See Figure 2 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """ [self._corners[0], self.w_arr[2], self.w_arr[1]])
def t1(self): """ The first child trixel of this trixel.
See Figure 2 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """ [self._corners[1], self.w_arr[0], self.w_arr[2]])
def t2(self): """ The second child trixel of this trixel.
See Figure 2 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """ [self._corners[2], self.w_arr[1], self.w_arr[0]])
def t3(self): """ The third child trixel of this trixel.
See Figure 2 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """ [self.w_arr[0], self.w_arr[1], self.w_arr[2]])
""" Return a list of all of the child trixels of this trixel. """
""" Return a specific child trixel of this trixel.
dex is an integer in the range [0,3] denoting which child to return
See Figure 1 of
Kunszt P., Szalay A., Thakar A. (2006) in "Mining The Sky", Banday A, Zaroubi S, Bartelmann M. eds. ESO Astrophysics Symposia https://www.researchgate.net/publication/226072008_The_Hierarchical_Triangular_Mesh
for an explanation of which trixel corresponds to whic index. """ else: raise RuntimeError("Trixel has no %d child" % dex)
""" Return the RA, Dec of the center of the circle bounding this trixel (RA, Dec both in degrees) """
""" Return the angular radius in degrees of the circle bounding this trixel. """
def level(self): """ Return the level of subdivision for this trixel. A higher level means a finer subdivision of the unit sphere and smaller trixels. What we refer to as 'level' is denoted by 'd' in equation 2.5 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164
For a given level == ell, there are 8*4**(ell-1) trixels in the entire unit sphere.
The htmid values of trixels with level==ell will consist of 4 + 2*(ell-1) bits """
def corners(self): """ A numpy array containing the unit vectors pointing to the corners of this trixel. corners[0] is the zeroth corner, corners[1] is the first corner, etc. """
def bounding_circle(self): """ The circle on the unit sphere that bounds this trixel.
See equation 4.2 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164
Returns ------- A tuple: Zeroth element is the unit vector pointing at the center of the bounding circle
First element is the distance from the center of the unit sphere to the plane of the bounding circle (i.e. the dot product of the zeroth element with the most distant corner of the trixel).
Second element is the half angular extent of the bounding circle. """ # find the unit vector pointing to the center of the trixel
# find the distance from the center of the trixel # to the most distant corner of the trixel
raise RuntimeError("Bounding circle has dd %e (should be between -1 and 1)" % dd)
# Below are defined the initial Trixels # # See equations (1) and (2) of # # Kunszt P., Szalay A., Thakar A. (2006) in "Mining The Sky", # Banday A, Zaroubi S, Bartelmann M. eds. # ESO Astrophysics Symposia # https://www.researchgate.net/publication/226072008_The_Hierarchical_Triangular_Mesh
np.array([0.0, 0.0, 1.0]), np.array([0.0, -1.0, 0.0])])
np.array([0.0, 0.0, 1.0]), np.array([-1.0, 0.0, 0.0])])
np.array([0.0, 0.0, 1.0]), np.array([0.0, 1.0, 0.0])])
np.array([0.0, 0.0, 1.0]), np.array([1.0, 0.0, 0.0])])
np.array([0.0, 0.0, -1.0]), np.array([0.0, 1.0, 0.0])])
np.array([0.0, 0.0, -1.0]), np.array([-1.0, 0.0, 0.0])])
np.array([0.0, 0.0, -1.0]), np.array([0.0, -1.0, 0.0])])
np.array([0.0, 0.0, -1.0]), np.array([1.0, 0.0, 0.0])])
'N1': _N1_trixel, 'N2': _N2_trixel, 'N3': _N3_trixel, 'S0': _S0_trixel, 'S1': _S1_trixel, 'S2': _S2_trixel, 'S3': _S3_trixel}
""" Find the level of a trixel from its htmid. The level indicates how refined the triangular mesh is.
There are 8*4**(d-1) triangles in a mesh of level=d
(equation 2.5 of Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164)
Note: valid htmids have 4+2n bits with a leading bit of 1 """
+ 'Valid htmids will have 4+2n bits\n' + 'with a leading bit of 1\n')
""" Return the trixel corresponding to the given htmid (htmid is the unique integer identifying each trixel).
Note: this method is not efficient for finding many trixels. It recursively generates trixels and their children until it finds the right htmid without remembering which trixels it has already generated. To generate many trixels, use the getAllTrixels() method, which efficiently generates all of the trixels up to a given mesh level.
Note: valid htmids have 4+2n bits with a leading bit of 1 """
raise RuntimeError("Unable to find trixel for id %d" % htmid)
# create an integer that is 4 bits # shorter than htmid (so it excludes # the bits corresponding to the base # trixel),with 11 in the two leading # positions
# Use bitwise and to figure out what the # two bits to the right of the bits # corresponding to the trixel currently # stored in ans are. These two bits # determine which child of ans we need # to return.
raise RuntimeError("target %d" % target)
""" Return a dict of all of the trixels up to a given mesh level. The dict is keyed on htmid, unique integer identifying each trixel on the unit sphere. This method is efficient at generating many trixels at once. """
# find how many bits should be added to the htmids # of the base trixels to get up to the desired level
# first, put the base trixels into the dict
# find the highest-level ancestor trixel # of htmid that has already # been generated and added to trixel_dict
# generate the next highest level ancestor # of the current htmid else:
# add the children of to_gen to trixel_dict
# add all of the children of parent_id to # trixel_dict
""" Method to iteratively find the htmid of the trixel containing a point.
Parameters ---------- pt is a Cartesian point (not necessarily on the unit sphere)
parent is the largest trixel currently known to contain the point
max_level is the level of the triangular mesh at which we want to find the htmid. Higher levels correspond to finer meshes. A mesh with level == ell contains 8*4**(ell-1) trixels.
Returns ------- The htmid at the desired level of the trixel containing the unit sphere projection of the point in pt. """ else:
""" Find the htmid (the unique integer identifying each trixel) of the trixel containing a given RA, Dec pair.
Parameters ---------- ra in degrees
dec in degrees
max_level is an integer denoting the mesh level of the trixel you want found
Note: This method only works one point at a time. It cannot take arrays of RA and Dec.
Returns ------- An int (the htmid) """
else: raise RuntimeError("could not find parent Trixel")
""" HalfSpaces are circles on the unit sphere defined by intersecting a plane with the unit sphere. They are specified by the unit vector pointing to their center on the unit sphere and the distance from the center of the unit sphere to the plane along that unit vector.
See Section 3.1 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164
Note that the specifying distance can be negative. In this case, the halfspace is defined as the larger of the two regions on the unit sphere divided by the circle where the plane of the halfspace intersects the unit sphere. """
""" Parameters ---------- vector is the unit vector pointing to the center of the halfspace on the unit sphere
length is the distance from the center of the unit sphere to theplane defining the half space along vector. This length can be negative, in which case, the halfspace is defined as the larger of the two regions on the unit sphere divided by the circle where the plane of the halfspace intersects the unit sphere. """ else: if self._d > 0.0: self._phi = np.pi else: self._phi = 0.0
def vector(self): """ The unit vector from the origin to the center of the Half Space. """
def dd(self): """ The distance along the Half Space's vector that defines the extent of the Half Space. """
def phi(self): """ The angular radius of the Half Space on the surface of the sphere in radians. """
""" pt is a cartesian point (not necessarily on the unit sphere). The method returns True if the projection of that point onto the unit sphere is contained in the halfspace; False otherwise. """
""" pt1 and pt2 are two unit vectors; the edge goes from pt1 to pt2. Return True if the edge intersects this halfspace; False otherwise.
see equation 4.8 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """
return True
""" tx is a Trixel. Return True if this halfspace intersects the bounding circle of the trixel; False otherwise.
See the discussion around equation 4.2 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """
elif dotproduct > -1.000000001: theta = np.pi else: raise RuntimeError("Dot product between unit vectors is %e" % dotproduct)
""" tx is a Trixel.
Return "full" if the Trixel is fully contained by this halfspace.
Return "partial" if the Trixel is only partially contained by this halfspace
Return "outside" if no part of the Trixel is contained by this halfspace.
See section 4.1 of
Szalay A. et al. (2007) "Indexing the Sphere with the Hierarchical Triangular Mesh" arXiv:cs/0701164 """
# check if the trixel's bounding circle intersects # the halfspace
# need to test that the bounding circle intersect the halfspace # boundary
(tx.corners[1], tx.corners[2]), (tx.corners[2], tx.corners[0])):
""" Find the HTMIDs of all of the trixels filling the half space
Parameters ---------- level is an integer denoting the resolution of the trixel grid
Returns ------- A list of tuples. Each tuple gives an inclusive range of HTMIDs corresponding to trixels within the HalfSpace """
global basic_trixels
# Once we establish that a given trixel is completely # contained within a the HalfSpace, we will need to # convert that trixel into a (min_htmid, max_htmid) pair. # This will involve evolving up from the current level # of trixel resolution to the desired level of trixel # resolution, setting the resulting 2-bit pairs to 0 for # min_htmid and 3 for max_htmid. We can get min_htmid by # taking the base trixel's level and multiplying by an # appropriate power of 2. We can get max_htmid by adding # an integer that, in binary, is wholly comprised of 1s # to min_htmid. Here we construct that integer of 1s, # starting out at level-2, since the first trixels # to which we will need to add max_d_htmid will be # at least at level 2 (the children of the base trixels).
# start iterating at level 2 because level 1 is the base trixels, # where we are already starting, and i_level reallly refers to # the level of the child trixels we are investigating
# need to investigate more fully # all of this trixels children, and their children are contained
######################################## # some assertions for debugging purposes # assert min_htmid<max_htmid # try: # test_trix = trixelFromHtmid(min_htmid) # assert self.contains_trixel(test_trix) != 'outside' # test_trix = trixelFromHtmid(max_htmid) # assert self.contains_trixel(test_trix) != 'outside' # except AssertionError: # print('is_contained %s' % is_contained) # print('level %d' % levelFromHtmid(tt._htmid)) # raise else: break
# final pass over the active_trixels to see which of their # children are inside this HalfSpace
# sort output by htmid_min
""" Take an RA, Dec and radius of a circular field of view and return a HalfSpace
Parameters ---------- ra in degrees
dec in degrees
radius in degrees
Returns ------- HalfSpace corresponding to the circular field of view """ |