Commit 9400e0a3fda8bf3f90fee576d75ca9876fb13ebd
1 parent
dde1b854
accelerate Healpix conversion
Showing
4 changed files
with
99 additions
and
85 deletions
include/GHealpix.hpp
| @@ -39,6 +39,7 @@ class GHealpix { | @@ -39,6 +39,7 @@ class GHealpix { | ||
| 39 | public: | 39 | public: |
| 40 | // Constructors and destructors | 40 | // Constructors and destructors |
| 41 | GHealpix(); | 41 | GHealpix(); |
| 42 | + GHealpix(const GFitsHDU* hdu); | ||
| 42 | GHealpix(const GHealpix& pixels); | 43 | GHealpix(const GHealpix& pixels); |
| 43 | virtual ~GHealpix(); | 44 | virtual ~GHealpix(); |
| 44 | 45 | ||
| @@ -46,7 +47,7 @@ public: | @@ -46,7 +47,7 @@ public: | ||
| 46 | GHealpix& operator= (const GHealpix& pixels); | 47 | GHealpix& operator= (const GHealpix& pixels); |
| 47 | 48 | ||
| 48 | // Methods | 49 | // Methods |
| 49 | - void load(const GFitsHDU* hdu); | 50 | + void read(const GFitsHDU* hdu); |
| 50 | int nside(void) const; | 51 | int nside(void) const; |
| 51 | int num_pixels(void) const; | 52 | int num_pixels(void) const; |
| 52 | double omega(void) const; | 53 | double omega(void) const; |
| @@ -58,16 +59,20 @@ private: | @@ -58,16 +59,20 @@ private: | ||
| 58 | void copy_members(const GHealpix& pixels); | 59 | void copy_members(const GHealpix& pixels); |
| 59 | void free_members(void); | 60 | void free_members(void); |
| 60 | GHealpix* clone(void) const; | 61 | GHealpix* clone(void) const; |
| 61 | - void mk_pix2xy(void); | 62 | + void pix2xy(const int& ipix, int* x, int* y); |
| 62 | void pix2ang_ring(int ipix, double* theta, double* phi); | 63 | void pix2ang_ring(int ipix, double* theta, double* phi); |
| 63 | void pix2ang_nest(int ipix, double* theta, double* phi); | 64 | void pix2ang_nest(int ipix, double* theta, double* phi); |
| 64 | 65 | ||
| 65 | // Private data area | 66 | // Private data area |
| 66 | int m_nside; //!< Number of divisions of each base pixel (1-8192) | 67 | int m_nside; //!< Number of divisions of each base pixel (1-8192) |
| 68 | + int m_npface; //!< | ||
| 69 | + int m_ncap; //!< | ||
| 67 | int m_order; //!< Ordering (0=ring, 1=nested, -1=?) | 70 | int m_order; //!< Ordering (0=ring, 1=nested, -1=?) |
| 68 | int m_coordsys; //!< Coordinate system (0=equatorial, 1=galactic, -1=?) | 71 | int m_coordsys; //!< Coordinate system (0=equatorial, 1=galactic, -1=?) |
| 69 | int m_num_pixels; //!< Number of pixels | 72 | int m_num_pixels; //!< Number of pixels |
| 70 | int m_size_pixels; //!< Vector size of each pixel | 73 | int m_size_pixels; //!< Vector size of each pixel |
| 74 | + double m_fact1; //!< | ||
| 75 | + double m_fact2; //!< | ||
| 71 | double m_omega; //!< Solid angle of pixel | 76 | double m_omega; //!< Solid angle of pixel |
| 72 | double* m_pixels; //!< Pixel array | 77 | double* m_pixels; //!< Pixel array |
| 73 | GSkyDir* m_dir; //!< Sky direction for each pixel | 78 | GSkyDir* m_dir; //!< Sky direction for each pixel |
pyext/GHealpix.i
| @@ -30,11 +30,12 @@ class GHealpix { | @@ -30,11 +30,12 @@ class GHealpix { | ||
| 30 | public: | 30 | public: |
| 31 | // Constructors and destructors | 31 | // Constructors and destructors |
| 32 | GHealpix(); | 32 | GHealpix(); |
| 33 | + GHealpix(const GFitsHDU* hdu); | ||
| 33 | GHealpix(const GHealpix& pixels); | 34 | GHealpix(const GHealpix& pixels); |
| 34 | virtual ~GHealpix(); | 35 | virtual ~GHealpix(); |
| 35 | 36 | ||
| 36 | // Methods | 37 | // Methods |
| 37 | - void load(const GFitsHDU* hdu); | 38 | + void read(const GFitsHDU* hdu); |
| 38 | int nside(void) const; | 39 | int nside(void) const; |
| 39 | int num_pixels(void) const; | 40 | int num_pixels(void) const; |
| 40 | double omega(void) const; | 41 | double omega(void) const; |
src/GHealpix.cpp
| @@ -42,8 +42,8 @@ const int jrll[12] = {2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4}; | @@ -42,8 +42,8 @@ const int jrll[12] = {2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4}; | ||
| 42 | const int jpll[12] = {1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7}; | 42 | const int jpll[12] = {1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7}; |
| 43 | 43 | ||
| 44 | /* __ Static conversion arrays ___________________________________________ */ | 44 | /* __ Static conversion arrays ___________________________________________ */ |
| 45 | -static int pix2x[1024]; | ||
| 46 | -static int pix2y[1024]; | 45 | +static short ctab[0x100]; |
| 46 | +static short utab[0x100]; | ||
| 47 | 47 | ||
| 48 | 48 | ||
| 49 | /*========================================================================== | 49 | /*========================================================================== |
| @@ -57,9 +57,27 @@ static int pix2y[1024]; | @@ -57,9 +57,27 @@ static int pix2y[1024]; | ||
| 57 | ***************************************************************************/ | 57 | ***************************************************************************/ |
| 58 | GHealpix::GHealpix() | 58 | GHealpix::GHealpix() |
| 59 | { | 59 | { |
| 60 | - // Initialise class members for clean destruction | 60 | + // Initialise class members |
| 61 | + init_members(); | ||
| 62 | + | ||
| 63 | + // Return | ||
| 64 | + return; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | + | ||
| 68 | +/***********************************************************************//** | ||
| 69 | + * @brief Constructor from FITS HDU table | ||
| 70 | + * | ||
| 71 | + * @param[in] hdu Pointer to FITS HDU | ||
| 72 | + ***************************************************************************/ | ||
| 73 | +GHealpix::GHealpix(const GFitsHDU* hdu) | ||
| 74 | +{ | ||
| 75 | + // Initialise class members | ||
| 61 | init_members(); | 76 | init_members(); |
| 62 | 77 | ||
| 78 | + // Read pixels from FITS HDU | ||
| 79 | + read(hdu); | ||
| 80 | + | ||
| 63 | // Return | 81 | // Return |
| 64 | return; | 82 | return; |
| 65 | } | 83 | } |
| @@ -135,14 +153,14 @@ GHealpix& GHealpix::operator= (const GHealpix& pixels) | @@ -135,14 +153,14 @@ GHealpix& GHealpix::operator= (const GHealpix& pixels) | ||
| 135 | ==========================================================================*/ | 153 | ==========================================================================*/ |
| 136 | 154 | ||
| 137 | /***********************************************************************//** | 155 | /***********************************************************************//** |
| 138 | - * @brief Load Healpix data from table. | 156 | + * @brief Read Healpix data from table. |
| 139 | * | 157 | * |
| 140 | * @param[in] hdu FITS HDU containing the Healpix data | 158 | * @param[in] hdu FITS HDU containing the Healpix data |
| 141 | * | 159 | * |
| 142 | * @exception GException::healpix | 160 | * @exception GException::healpix |
| 143 | * Unable to load Healpix data from table. | 161 | * Unable to load Healpix data from table. |
| 144 | ***************************************************************************/ | 162 | ***************************************************************************/ |
| 145 | -void GHealpix::load(const GFitsHDU* hdu) | 163 | +void GHealpix::read(const GFitsHDU* hdu) |
| 146 | { | 164 | { |
| 147 | // Free memory and initialise members | 165 | // Free memory and initialise members |
| 148 | free_members(); | 166 | free_members(); |
| @@ -154,7 +172,11 @@ void GHealpix::load(const GFitsHDU* hdu) | @@ -154,7 +172,11 @@ void GHealpix::load(const GFitsHDU* hdu) | ||
| 154 | 172 | ||
| 155 | // Get Healpix resolution and determine number of pixels and solid angle | 173 | // Get Healpix resolution and determine number of pixels and solid angle |
| 156 | m_nside = hdu->card("NSIDE")->integer(); | 174 | m_nside = hdu->card("NSIDE")->integer(); |
| 157 | - m_num_pixels = 12 * m_nside * m_nside; | 175 | + m_npface = m_nside * m_nside; |
| 176 | + m_ncap = 2 * (m_npface - m_nside); | ||
| 177 | + m_num_pixels = 12 * m_npface; | ||
| 178 | + m_fact2 = 4.0 / m_num_pixels; | ||
| 179 | + m_fact1 = 2 * m_nside * m_fact2; | ||
| 158 | m_omega = fourpi / m_num_pixels; | 180 | m_omega = fourpi / m_num_pixels; |
| 159 | 181 | ||
| 160 | // Get ordering scheme from ORDERING keyword | 182 | // Get ordering scheme from ORDERING keyword |
| @@ -319,16 +341,27 @@ void GHealpix::init_members(void) | @@ -319,16 +341,27 @@ void GHealpix::init_members(void) | ||
| 319 | { | 341 | { |
| 320 | // Initialise members | 342 | // Initialise members |
| 321 | m_nside = 0; | 343 | m_nside = 0; |
| 344 | + m_npface = 0; | ||
| 345 | + m_ncap = 0; | ||
| 322 | m_order = 0; | 346 | m_order = 0; |
| 323 | m_coordsys = 0; | 347 | m_coordsys = 0; |
| 324 | m_num_pixels = 0; | 348 | m_num_pixels = 0; |
| 325 | m_size_pixels = 0; | 349 | m_size_pixels = 0; |
| 350 | + m_fact1 = 0.0; | ||
| 351 | + m_fact2 = 0.0; | ||
| 326 | m_omega = 0.0; | 352 | m_omega = 0.0; |
| 327 | m_pixels = NULL; | 353 | m_pixels = NULL; |
| 328 | m_dir = NULL; | 354 | m_dir = NULL; |
| 329 | 355 | ||
| 330 | - // Initiates the array for the pixel number -> (x,y) mapping | ||
| 331 | - mk_pix2xy(); | 356 | + // Construct conversion arrays |
| 357 | + for (int m = 0; m < 0x100; ++m) { | ||
| 358 | + ctab[m] = | ||
| 359 | + (m&0x1 ) | ((m&0x2 ) << 7) | ((m&0x4 ) >> 1) | ((m&0x8 ) << 6) | ||
| 360 | + | ((m&0x10) >> 2) | ((m&0x20) << 5) | ((m&0x40) >> 3) | ((m&0x80) << 4); | ||
| 361 | + utab[m] = | ||
| 362 | + (m&0x1 ) | ((m&0x2 ) << 1) | ((m&0x4 ) << 2) | ((m&0x8 ) << 3) | ||
| 363 | + | ((m&0x10) << 4) | ((m&0x20) << 5) | ((m&0x40) << 6) | ((m&0x80) << 7); | ||
| 364 | + } | ||
| 332 | 365 | ||
| 333 | // Return | 366 | // Return |
| 334 | return; | 367 | return; |
| @@ -344,10 +377,14 @@ void GHealpix::copy_members(const GHealpix& pixels) | @@ -344,10 +377,14 @@ void GHealpix::copy_members(const GHealpix& pixels) | ||
| 344 | { | 377 | { |
| 345 | // Copy attributes | 378 | // Copy attributes |
| 346 | m_nside = pixels.m_nside; | 379 | m_nside = pixels.m_nside; |
| 380 | + m_npface = pixels.m_npface; | ||
| 381 | + m_ncap = pixels.m_ncap; | ||
| 347 | m_order = pixels.m_order; | 382 | m_order = pixels.m_order; |
| 348 | m_coordsys = pixels.m_coordsys; | 383 | m_coordsys = pixels.m_coordsys; |
| 349 | m_num_pixels = pixels.m_num_pixels; | 384 | m_num_pixels = pixels.m_num_pixels; |
| 350 | m_size_pixels = pixels.m_size_pixels; | 385 | m_size_pixels = pixels.m_size_pixels; |
| 386 | + m_fact1 = pixels.m_fact1; | ||
| 387 | + m_fact2 = pixels.m_fact2; | ||
| 351 | m_omega = pixels.m_omega; | 388 | m_omega = pixels.m_omega; |
| 352 | 389 | ||
| 353 | // Copy arrays | 390 | // Copy arrays |
| @@ -397,41 +434,22 @@ GHealpix* GHealpix::clone(void) const | @@ -397,41 +434,22 @@ GHealpix* GHealpix::clone(void) const | ||
| 397 | 434 | ||
| 398 | 435 | ||
| 399 | /***********************************************************************//** | 436 | /***********************************************************************//** |
| 400 | - * @brief Constructs pixel to (x,y) conversion array | 437 | + * @brief Convert pixel index to (x,y) coordinate |
| 401 | * | 438 | * |
| 402 | - * Constructs the array giving x and y in the face from pixel number for the | ||
| 403 | - * nested (quad-cube like) ordering of pixels. The bits corresponding to x | ||
| 404 | - * and y are interleaved in the pixel number one breaks up the pixel number | ||
| 405 | - * by even and odd bits. | 439 | + * @param[in] ipix Pixel index for which (x,y) are to be computed. |
| 440 | + * @param[out] x Pointer to x coordinate. | ||
| 441 | + * @param[out] y Pointer to y coordinate. | ||
| 406 | ***************************************************************************/ | 442 | ***************************************************************************/ |
| 407 | -void GHealpix::mk_pix2xy(void) | 443 | +void GHealpix::pix2xy(const int& ipix, int* x, int* y) |
| 408 | { | 444 | { |
| 409 | - // Loop over all pixels of array | ||
| 410 | - for (int kpix = 0; kpix < 1024; ++kpix) { | ||
| 411 | - | ||
| 412 | - // Setup | ||
| 413 | - int jpix = kpix; | ||
| 414 | - int IX = 0; | ||
| 415 | - int IY = 0; | ||
| 416 | - int IP = 1; // Bit position (in x and y) | ||
| 417 | - | ||
| 418 | - // Go through all the bits | ||
| 419 | - while (jpix != 0) { | ||
| 420 | - int ID = (int)fmod(jpix,2); // Bit value (in kpix), goes in ix | ||
| 421 | - jpix = jpix/2; | ||
| 422 | - IX = ID*IP+IX; | ||
| 423 | - ID = (int)fmod(jpix,2); // Bit value (in kpix), goes in iy | ||
| 424 | - jpix = jpix/2; | ||
| 425 | - IY = ID*IP+IY; | ||
| 426 | - IP = 2*IP; // Next bit (in x and y) | ||
| 427 | - } | 445 | + // Set x coordinate |
| 446 | + int raw = (ipix & 0x5555) | ((ipix & 0x55550000) >> 15); | ||
| 447 | + *x = ctab[raw & 0xff] | (ctab[raw >> 8] << 4); | ||
| 448 | + | ||
| 449 | + // Set y coordinate | ||
| 450 | + raw = ((ipix & 0xaaaa) >> 1) | ((ipix & 0xaaaa0000) >> 16); | ||
| 451 | + *y = ctab[raw & 0xff] | (ctab[raw >> 8] << 4); | ||
| 428 | 452 | ||
| 429 | - // Set array elements | ||
| 430 | - pix2x[kpix] = IX; // in {0,31} | ||
| 431 | - pix2y[kpix] = IY; // in {0,31} | ||
| 432 | - | ||
| 433 | - } | ||
| 434 | - | ||
| 435 | // Return | 453 | // Return |
| 436 | return; | 454 | return; |
| 437 | } | 455 | } |
| @@ -514,60 +532,53 @@ void GHealpix::pix2ang_nest(int ipix, double* theta, double* phi) | @@ -514,60 +532,53 @@ void GHealpix::pix2ang_nest(int ipix, double* theta, double* phi) | ||
| 514 | if (ipix < 0 || ipix >= m_num_pixels) | 532 | if (ipix < 0 || ipix >= m_num_pixels) |
| 515 | throw GException::out_of_range(G_PIX2ANG_NEST, ipix, 0, m_num_pixels-1); | 533 | throw GException::out_of_range(G_PIX2ANG_NEST, ipix, 0, m_num_pixels-1); |
| 516 | 534 | ||
| 517 | - // ... | ||
| 518 | - double fn = 1. * m_nside; | ||
| 519 | - double fact1 = 1. / (3.*fn*fn); | ||
| 520 | - double fact2 = 2. / (3.*fn); | ||
| 521 | - int nl4 = 4 * m_nside; | ||
| 522 | - | ||
| 523 | - // Finds the face, and the number in the face | ||
| 524 | - int npface = m_nside*m_nside; | ||
| 525 | - int face_num = ipix/npface; // Face number in {0,11} | ||
| 526 | - int ipf = (int)fmod(ipix,npface); // Pixel number in the face {0,npface-1} | ||
| 527 | - | ||
| 528 | - // Finds the x,y on the face from the pixel number | ||
| 529 | - // (starting from the lowest corner) | ||
| 530 | - int ip_low = (int)fmod(ipf,1024); // Content of the last 10 bits | ||
| 531 | - int ip_trunc = ipf/1024; // Truncation of the last 10 bits | ||
| 532 | - int ip_med = (int)fmod(ip_trunc,1024); // Content of the next 10 bits | ||
| 533 | - int ip_hi = ip_trunc/1024; // Content of the high weight 10 bits | ||
| 534 | - int ix = 1024*pix2x[ip_hi] + 32*pix2x[ip_med] + pix2x[ip_low]; | ||
| 535 | - int iy = 1024*pix2y[ip_hi] + 32*pix2y[ip_med] + pix2y[ip_low]; | ||
| 536 | - | ||
| 537 | - // Transforms this in (horizontal, vertical) coordinates | ||
| 538 | - int jrt = ix + iy; // 'vertical' in {0,2*(m_nside-1)} | ||
| 539 | - int jpt = ix - iy; // 'horizontal' in {-m_nside+1,m_nside-1} | 535 | + // Get face number and index in face |
| 536 | + int nl4 = 4 * m_nside; | ||
| 537 | + int face_num = ipix/m_npface; // Face number in {0,11} | ||
| 538 | + int ipf = ipix & (m_npface - 1); | ||
| 539 | + | ||
| 540 | + // Get pixel coordinates | ||
| 541 | + int ix; | ||
| 542 | + int iy; | ||
| 543 | + pix2xy(ipf, &ix, &iy); | ||
| 540 | 544 | ||
| 541 | // Computes the z coordinate on the sphere | 545 | // Computes the z coordinate on the sphere |
| 542 | - int jr = jrll[face_num]*m_nside - jrt - 1; | ||
| 543 | - int nr = m_nside; // Equatorial region (the most frequent) | ||
| 544 | - double z = (2*m_nside-jr)*fact2; | ||
| 545 | - int kshift = (int)fmod(jr - m_nside, 2); | 546 | + int jr = jrll[face_num]*m_nside - ix - iy - 1; |
| 547 | + | ||
| 548 | + // Declare result variables | ||
| 549 | + int nr; | ||
| 550 | + double z; | ||
| 551 | + int kshift; | ||
| 546 | 552 | ||
| 547 | // North pole region | 553 | // North pole region |
| 548 | if (jr < m_nside) { | 554 | if (jr < m_nside) { |
| 549 | nr = jr; | 555 | nr = jr; |
| 550 | - z = 1. - nr*nr*fact1; | 556 | + z = 1. - nr*nr*m_fact2; |
| 551 | kshift = 0; | 557 | kshift = 0; |
| 552 | } | 558 | } |
| 553 | 559 | ||
| 554 | // South pole region | 560 | // South pole region |
| 555 | else if (jr > 3*m_nside) { | 561 | else if (jr > 3*m_nside) { |
| 556 | nr = nl4 - jr; | 562 | nr = nl4 - jr; |
| 557 | - z = - 1. + nr*nr*fact1; | 563 | + z = nr*nr*m_fact2 - 1; |
| 558 | kshift = 0; | 564 | kshift = 0; |
| 559 | } | 565 | } |
| 560 | 566 | ||
| 561 | - // Computes theta | ||
| 562 | - *theta = acos(z); | ||
| 563 | - | 567 | + // Equatorial region |
| 568 | + else { | ||
| 569 | + nr = m_nside; | ||
| 570 | + z = (2*m_nside-jr) * m_fact1; | ||
| 571 | + kshift = (jr-m_nside) & 1; | ||
| 572 | + } | ||
| 573 | + | ||
| 564 | // Computes the phi coordinate on the sphere, in [0,2Pi] | 574 | // Computes the phi coordinate on the sphere, in [0,2Pi] |
| 565 | - int jp = (jpll[face_num]*nr + jpt + 1 + kshift)/2; | ||
| 566 | - if (jp > nl4) jp = jp - nl4; | ||
| 567 | - if (jp < 1) jp = jp + nl4; | 575 | + int jp = (jpll[face_num]*nr + ix - iy + 1 + kshift) / 2; |
| 576 | + if (jp > nl4) jp -= nl4; | ||
| 577 | + if (jp < 1) jp += nl4; | ||
| 568 | 578 | ||
| 569 | - // Computes Phi | ||
| 570 | - *phi = (jp - (kshift+1)*0.5) * (pihalf / nr); | 579 | + // Computes Theta and Phi |
| 580 | + *theta = acos(z); | ||
| 581 | + *phi = (jp - (kshift+1)*0.5) * (pihalf / nr); | ||
| 571 | 582 | ||
| 572 | // Return | 583 | // Return |
| 573 | return; | 584 | return; |
test/test_python.py
| @@ -19,8 +19,7 @@ def test_fits(): | @@ -19,8 +19,7 @@ def test_fits(): | ||
| 19 | pass | 19 | pass |
| 20 | 20 | ||
| 21 | # Create FITS file | 21 | # Create FITS file |
| 22 | - fits = GFits() | ||
| 23 | - fits.open("test_python.fits") | 22 | + fits = GFits("test_python.fits") |
| 24 | 23 | ||
| 25 | # Print number of HDUs | 24 | # Print number of HDUs |
| 26 | print "Number of HDUs ..: " + str(fits.num_hdus()) | 25 | print "Number of HDUs ..: " + str(fits.num_hdus()) |
| @@ -197,12 +196,10 @@ def test_healpix(): | @@ -197,12 +196,10 @@ def test_healpix(): | ||
| 197 | Test GHealpix interface. | 196 | Test GHealpix interface. |
| 198 | """ | 197 | """ |
| 199 | # Open exposure cube | 198 | # Open exposure cube |
| 200 | - fits = GFits() | ||
| 201 | - fits.open("data/expCube_253582800.fits.gz") | 199 | + fits = GFits("data/expCube_253582800.fits.gz") |
| 202 | 200 | ||
| 203 | # Lood Healpix table | 201 | # Lood Healpix table |
| 204 | - pixels = GHealpix() | ||
| 205 | - pixels.load(fits.hdu("EXPOSURE")) | 202 | + pixels = GHealpix(fits.hdu("EXPOSURE")) |
| 206 | 203 | ||
| 207 | # Dump information | 204 | # Dump information |
| 208 | print pixels | 205 | print pixels |