Commit 9400e0a3fda8bf3f90fee576d75ca9876fb13ebd

Authored by knodlseder
1 parent dde1b854

accelerate Healpix conversion

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&amp; GHealpix::operator= (const GHealpix&amp; pixels) @@ -135,14 +153,14 @@ GHealpix&amp; GHealpix::operator= (const GHealpix&amp; 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&amp; pixels) @@ -344,10 +377,14 @@ void GHealpix::copy_members(const GHealpix&amp; 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