Commit 9400e0a3fda8bf3f90fee576d75ca9876fb13ebd

Authored by knodlseder
1 parent dde1b854

accelerate Healpix conversion

include/GHealpix.hpp
... ... @@ -39,6 +39,7 @@ class GHealpix {
39 39 public:
40 40 // Constructors and destructors
41 41 GHealpix();
  42 + GHealpix(const GFitsHDU* hdu);
42 43 GHealpix(const GHealpix& pixels);
43 44 virtual ~GHealpix();
44 45  
... ... @@ -46,7 +47,7 @@ public:
46 47 GHealpix& operator= (const GHealpix& pixels);
47 48  
48 49 // Methods
49   - void load(const GFitsHDU* hdu);
  50 + void read(const GFitsHDU* hdu);
50 51 int nside(void) const;
51 52 int num_pixels(void) const;
52 53 double omega(void) const;
... ... @@ -58,16 +59,20 @@ private:
58 59 void copy_members(const GHealpix& pixels);
59 60 void free_members(void);
60 61 GHealpix* clone(void) const;
61   - void mk_pix2xy(void);
  62 + void pix2xy(const int& ipix, int* x, int* y);
62 63 void pix2ang_ring(int ipix, double* theta, double* phi);
63 64 void pix2ang_nest(int ipix, double* theta, double* phi);
64 65  
65 66 // Private data area
66 67 int m_nside; //!< Number of divisions of each base pixel (1-8192)
  68 + int m_npface; //!<
  69 + int m_ncap; //!<
67 70 int m_order; //!< Ordering (0=ring, 1=nested, -1=?)
68 71 int m_coordsys; //!< Coordinate system (0=equatorial, 1=galactic, -1=?)
69 72 int m_num_pixels; //!< Number of pixels
70 73 int m_size_pixels; //!< Vector size of each pixel
  74 + double m_fact1; //!<
  75 + double m_fact2; //!<
71 76 double m_omega; //!< Solid angle of pixel
72 77 double* m_pixels; //!< Pixel array
73 78 GSkyDir* m_dir; //!< Sky direction for each pixel
... ...
pyext/GHealpix.i
... ... @@ -30,11 +30,12 @@ class GHealpix {
30 30 public:
31 31 // Constructors and destructors
32 32 GHealpix();
  33 + GHealpix(const GFitsHDU* hdu);
33 34 GHealpix(const GHealpix& pixels);
34 35 virtual ~GHealpix();
35 36  
36 37 // Methods
37   - void load(const GFitsHDU* hdu);
  38 + void read(const GFitsHDU* hdu);
38 39 int nside(void) const;
39 40 int num_pixels(void) const;
40 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 42 const int jpll[12] = {1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};
43 43  
44 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 57 ***************************************************************************/
58 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 76 init_members();
62 77  
  78 + // Read pixels from FITS HDU
  79 + read(hdu);
  80 +
63 81 // Return
64 82 return;
65 83 }
... ... @@ -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 158 * @param[in] hdu FITS HDU containing the Healpix data
141 159 *
142 160 * @exception GException::healpix
143 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 165 // Free memory and initialise members
148 166 free_members();
... ... @@ -154,7 +172,11 @@ void GHealpix::load(const GFitsHDU* hdu)
154 172  
155 173 // Get Healpix resolution and determine number of pixels and solid angle
156 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 180 m_omega = fourpi / m_num_pixels;
159 181  
160 182 // Get ordering scheme from ORDERING keyword
... ... @@ -319,16 +341,27 @@ void GHealpix::init_members(void)
319 341 {
320 342 // Initialise members
321 343 m_nside = 0;
  344 + m_npface = 0;
  345 + m_ncap = 0;
322 346 m_order = 0;
323 347 m_coordsys = 0;
324 348 m_num_pixels = 0;
325 349 m_size_pixels = 0;
  350 + m_fact1 = 0.0;
  351 + m_fact2 = 0.0;
326 352 m_omega = 0.0;
327 353 m_pixels = NULL;
328 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 366 // Return
334 367 return;
... ... @@ -344,10 +377,14 @@ void GHealpix::copy_members(const GHealpix&amp; pixels)
344 377 {
345 378 // Copy attributes
346 379 m_nside = pixels.m_nside;
  380 + m_npface = pixels.m_npface;
  381 + m_ncap = pixels.m_ncap;
347 382 m_order = pixels.m_order;
348 383 m_coordsys = pixels.m_coordsys;
349 384 m_num_pixels = pixels.m_num_pixels;
350 385 m_size_pixels = pixels.m_size_pixels;
  386 + m_fact1 = pixels.m_fact1;
  387 + m_fact2 = pixels.m_fact2;
351 388 m_omega = pixels.m_omega;
352 389  
353 390 // Copy arrays
... ... @@ -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 453 // Return
436 454 return;
437 455 }
... ... @@ -514,60 +532,53 @@ void GHealpix::pix2ang_nest(int ipix, double* theta, double* phi)
514 532 if (ipix < 0 || ipix >= m_num_pixels)
515 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 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 553 // North pole region
548 554 if (jr < m_nside) {
549 555 nr = jr;
550   - z = 1. - nr*nr*fact1;
  556 + z = 1. - nr*nr*m_fact2;
551 557 kshift = 0;
552 558 }
553 559  
554 560 // South pole region
555 561 else if (jr > 3*m_nside) {
556 562 nr = nl4 - jr;
557   - z = - 1. + nr*nr*fact1;
  563 + z = nr*nr*m_fact2 - 1;
558 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 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 583 // Return
573 584 return;
... ...
test/test_python.py
... ... @@ -19,8 +19,7 @@ def test_fits():
19 19 pass
20 20  
21 21 # Create FITS file
22   - fits = GFits()
23   - fits.open("test_python.fits")
  22 + fits = GFits("test_python.fits")
24 23  
25 24 # Print number of HDUs
26 25 print "Number of HDUs ..: " + str(fits.num_hdus())
... ... @@ -197,12 +196,10 @@ def test_healpix():
197 196 Test GHealpix interface.
198 197 """
199 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 201 # Lood Healpix table
204   - pixels = GHealpix()
205   - pixels.load(fits.hdu("EXPOSURE"))
  202 + pixels = GHealpix(fits.hdu("EXPOSURE"))
206 203  
207 204 # Dump information
208 205 print pixels
... ...