Commit f834a1a96955e57f199542132efbd331a93dbf85

Authored by knodlseder
1 parent 86674206

enhance class

include/GHealpix.hpp
... ... @@ -49,9 +49,11 @@ public:
49 49 // Methods
50 50 void read(const GFitsHDU* hdu);
51 51 int nside(void) const;
  52 + int order(void) const;
52 53 int num_pixels(void) const;
53 54 double omega(void) const;
54 55 GSkyDir pix2ang(const int& ipix);
  56 + int ang2pix(GSkyDir dir) const;
55 57  
56 58 private:
57 59 // Private methods
... ... @@ -59,15 +61,20 @@ private:
59 61 void copy_members(const GHealpix& pixels);
60 62 void free_members(void);
61 63 GHealpix* clone(void) const;
  64 + int nside2order(int nside);
62 65 void pix2xy(const int& ipix, int* x, int* y);
  66 + int xy2pix(int x, int y) const;
63 67 void pix2ang_ring(int ipix, double* theta, double* phi);
64 68 void pix2ang_nest(int ipix, double* theta, double* phi);
  69 + int ang2pix_z_phi_ring(double z, double phi) const;
  70 + int ang2pix_z_phi_nest(double z, double phi) const;
65 71  
66 72 // Private data area
67 73 int m_nside; //!< Number of divisions of each base pixel (1-8192)
68 74 int m_npface; //!<
69 75 int m_ncap; //!<
70   - int m_order; //!< Ordering (0=ring, 1=nested, -1=?)
  76 + int m_order; //!< Order
  77 + int m_scheme; //!< Ordering scheme (0=ring, 1=nested, -1=?)
71 78 int m_coordsys; //!< Coordinate system (0=equatorial, 1=galactic, -1=?)
72 79 int m_num_pixels; //!< Number of pixels
73 80 int m_size_pixels; //!< Vector size of each pixel
... ...
pyext/GHealpix.i
... ... @@ -40,6 +40,7 @@ public:
40 40 int num_pixels(void) const;
41 41 double omega(void) const;
42 42 GSkyDir pix2ang(const int& ipix);
  43 + int ang2pix(GSkyDir dir) const;
43 44 };
44 45  
45 46  
... ...
src/GHealpix.cpp
... ... @@ -19,7 +19,8 @@
19 19  
20 20 /* __ Includes ___________________________________________________________ */
21 21 #include <iostream>
22   -#include <math.h>
  22 +//#include <math.h>
  23 +#include <cmath>
23 24 #include "GException.hpp"
24 25 #include "GTools.hpp"
25 26 #include "GHealpix.hpp"
... ... @@ -37,15 +38,19 @@
37 38  
38 39 /* __ Debug definitions __________________________________________________ */
39 40  
  41 +/* __ Local prototypes ___________________________________________________ */
  42 +unsigned int isqrt(unsigned int arg);
  43 +
40 44 /* __ Constants __________________________________________________________ */
41   -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};
  45 +const int jrll[12] = {2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};
  46 +const int jpll[12] = {1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};
  47 +const int order_max = 13;
  48 +const int ns_max = 1 << order_max;
43 49  
44 50 /* __ Static conversion arrays ___________________________________________ */
45 51 static short ctab[0x100];
46 52 static short utab[0x100];
47 53  
48   -
49 54 /*==========================================================================
50 55 = =
51 56 = GHealpix constructors/destructors =
... ... @@ -178,6 +183,8 @@ void GHealpix::read(const GFitsHDU* hdu)
178 183 m_fact2 = 4.0 / m_num_pixels;
179 184 m_fact1 = 2 * m_nside * m_fact2;
180 185 m_omega = fourpi / m_num_pixels;
  186 + m_order = nside2order(m_nside);
  187 +
181 188  
182 189 // Get ordering scheme from ORDERING keyword
183 190 std::string ordering;
... ... @@ -185,14 +192,14 @@ void GHealpix::read(const GFitsHDU* hdu)
185 192 ordering = hdu->card("ORDERING")->string();
186 193 }
187 194 catch (GException::fits_key_not_found &e) {
188   - m_order = -1; // Flag unknown ordering
  195 + m_scheme = -1; // Flag unknown ordering
189 196 }
190 197  
191 198 // Decode ordering scheme string
192 199 if (ordering == "RING")
193   - m_order = 0;
  200 + m_scheme = 0;
194 201 else if (ordering == "NESTED")
195   - m_order = 1;
  202 + m_scheme = 1;
196 203 else
197 204 throw GException::healpix(G_LOAD, "Invalid ordering");
198 205  
... ... @@ -268,6 +275,16 @@ int GHealpix::nside(void) const
268 275  
269 276  
270 277 /***********************************************************************//**
  278 + * @brief Returns ordering parameter.
  279 + ***************************************************************************/
  280 +int GHealpix::order(void) const
  281 +{
  282 + // Return order
  283 + return m_order;
  284 +}
  285 +
  286 +
  287 +/***********************************************************************//**
271 288 * @brief Returns number of pixels.
272 289 ***************************************************************************/
273 290 int GHealpix::num_pixels(void) const
... ... @@ -300,7 +317,7 @@ GSkyDir GHealpix::pix2ang(const int&amp; ipix)
300 317 double phi = 0.0;
301 318  
302 319 // Perform ordering dependent conversion
303   - switch (m_order) {
  320 + switch (m_scheme) {
304 321 case 0:
305 322 pix2ang_ring(ipix, &theta, &phi);
306 323 break;
... ... @@ -328,6 +345,49 @@ GSkyDir GHealpix::pix2ang(const int&amp; ipix)
328 345 }
329 346  
330 347  
  348 +/***********************************************************************//**
  349 + * @brief Returns pixel for a given sky direction
  350 + *
  351 + * @param[in] ipix Pixel number (0,1,...,num_pixels)
  352 + ***************************************************************************/
  353 +int GHealpix::ang2pix(GSkyDir dir) const
  354 +{
  355 + // Declare result
  356 + int ipix;
  357 + double z;
  358 + double phi;
  359 +
  360 + // Compute coordinate system dependent (z,phi)
  361 + switch (m_coordsys) {
  362 + case 0:
  363 + z = cos(pihalf-dir.dec());
  364 + phi = dir.ra();
  365 + break;
  366 + case 1:
  367 + z = cos(pihalf-dir.b());
  368 + phi = dir.l();
  369 + break;
  370 + default:
  371 + break;
  372 + }
  373 +
  374 + // Perform ordering dependent conversion
  375 + switch (m_scheme) {
  376 + case 0:
  377 + ipix = ang2pix_z_phi_ring(z, phi);
  378 + break;
  379 + case 1:
  380 + ipix = ang2pix_z_phi_nest(z, phi);
  381 + break;
  382 + default:
  383 + break;
  384 + }
  385 +
  386 + // Return pixel index
  387 + return ipix;
  388 +}
  389 +
  390 +
331 391 /*==========================================================================
332 392 = =
333 393 = GHealpix private methods =
... ... @@ -344,6 +404,7 @@ void GHealpix::init_members(void)
344 404 m_npface = 0;
345 405 m_ncap = 0;
346 406 m_order = 0;
  407 + m_scheme = 0;
347 408 m_coordsys = 0;
348 409 m_num_pixels = 0;
349 410 m_size_pixels = 0;
... ... @@ -380,6 +441,7 @@ void GHealpix::copy_members(const GHealpix&amp; pixels)
380 441 m_npface = pixels.m_npface;
381 442 m_ncap = pixels.m_ncap;
382 443 m_order = pixels.m_order;
  444 + m_scheme = pixels.m_scheme;
383 445 m_coordsys = pixels.m_coordsys;
384 446 m_num_pixels = pixels.m_num_pixels;
385 447 m_size_pixels = pixels.m_size_pixels;
... ... @@ -434,6 +496,32 @@ GHealpix* GHealpix::clone(void) const
434 496  
435 497  
436 498 /***********************************************************************//**
  499 + * @brief Convert nside to order
  500 + *
  501 + * @param[in] nside Number of sides.
  502 + ***************************************************************************/
  503 +int GHealpix::nside2order(int nside)
  504 +{
  505 + // Initialise order
  506 + int order = -1;
  507 +
  508 + // Determine order
  509 + for (int m = 0; m <= order_max; ++m) {
  510 + int nstest = 1 << m;
  511 + if (nside == nstest) {
  512 + order = m;
  513 + break;
  514 + }
  515 + if (nside < nstest)
  516 + break;
  517 + }
  518 +
  519 + // Return order
  520 + return order;
  521 +}
  522 +
  523 +
  524 +/***********************************************************************//**
437 525 * @brief Convert pixel index to (x,y) coordinate
438 526 *
439 527 * @param[in] ipix Pixel index for which (x,y) are to be computed.
... ... @@ -456,6 +544,19 @@ void GHealpix::pix2xy(const int&amp; ipix, int* x, int* y)
456 544  
457 545  
458 546 /***********************************************************************//**
  547 + * @brief Convert (x,y) coordinate to pixel
  548 + *
  549 + * @param[in] x x coordinate.
  550 + * @param[in] y y coordinate.
  551 + ***************************************************************************/
  552 +int GHealpix::xy2pix(int x, int y) const
  553 +{
  554 + // Return pixel
  555 + return utab[x&0xff] | (utab[x>>8]<<16) | (utab[y&0xff]<<1) | (utab[y>>8]<<17);
  556 +}
  557 +
  558 +
  559 +/***********************************************************************//**
459 560 * @brief Convert pixel index to (theta,phi) angles for ring ordering
460 561 *
461 562 * @param[in] ipix Pixel index for which (theta,phi) are to be computed.
... ... @@ -470,48 +571,34 @@ void GHealpix::pix2ang_ring(int ipix, double* theta, double* phi)
470 571 if (ipix < 0 || ipix >= m_num_pixels)
471 572 throw GException::out_of_range(G_PIX2ANG_RING, ipix, 0, m_num_pixels-1);
472 573  
473   - // Setup
474   - int ipix1 = ipix + 1; // in {1, m_num_pixels}
475   - int nl2 = 2 * m_nside;
476   - int nl4 = 4 * m_nside;
477   -
478   - // Determine points in each polar cap (0 for nside=1)
479   - int ncap = 2 * m_nside * (m_nside-1);
480   -
481   - double fact1 = 1.5 * m_nside;
482   - double fact2 = 3.0 * m_nside * m_nside;
483   -
484 574 // Handle North Polar cap
485   - if (ipix1 <= ncap) {
486   - double hip = ipix1/2.;
487   - double fihip = floor(hip);
488   - int iring = (int)floor(sqrt(hip - sqrt(fihip)))+1;
489   - int iphi = ipix1 - 2*iring*(iring - 1);
490   - *theta = acos(1. - iring*iring / fact2);
491   - *phi = (1.*iphi - 0.5) * pi/(2.*iring);
  575 + if (ipix < m_ncap) {
  576 + int iring = int(0.5*(1+isqrt(1+2*ipix))); // counted from North pole
  577 + int iphi = (ipix+1) - 2*iring*(iring-1);
  578 + *theta = acos(1.0 - iring*iring / m_fact2);
  579 + *phi = (iphi - 0.5) * pi/(2.0*iring);
492 580 }
493 581  
494 582 // Handle Equatorial region
495   - else if(ipix1 <= nl2*(5*m_nside+1)) {
496   - int ip = ipix1 - ncap - 1;
497   - int iring = (int)floor(ip/nl4) + m_nside;
498   - int iphi = (int)fmod(ip,nl4) + 1;
499   - double fodd = 0.5 * (1 + fmod((double)(iring+m_nside),2));
500   - *theta = acos((nl2 - iring) / fact1);
501   - *phi = (1.*iphi - fodd) * pi/(2.*m_nside);
  583 + else if (ipix < (m_num_pixels - m_ncap)) {
  584 + int ip = ipix - m_ncap;
  585 + int iring = ip/(4*m_nside) + m_nside; // counted from North pole
  586 + int iphi = ip%(4*m_nside) + 1;
  587 + double fodd = ((iring+m_nside)&1) ? 1 : 0.5;
  588 + int nl2 = 2*m_nside;
  589 + *theta = acos((nl2 - iring) / m_fact1);
  590 + *phi = (iphi - fodd) * pi/nl2;
502 591 }
503 592  
504   - // Handle South Polar cap
  593 + // Handle South Polar cap
505 594 else {
506   - int ip = m_num_pixels - ipix1 + 1;
507   - double hip = ip/2.;
508   - double fihip = floor(hip);
509   - int iring = (int)floor(sqrt( hip - sqrt(fihip))) + 1;
510   - int iphi = (int)(4.*iring + 1 - (ip - 2.*iring*(iring-1)));
511   - *theta = acos( -1. + iring*iring / fact2 );
512   - *phi = (1.*iphi - 0.5) * pi/(2.*iring);
  595 + int ip = m_num_pixels - ipix;
  596 + int iring = int(0.5*(1+isqrt(2*ip-1))); // Counted from South pole
  597 + int iphi = 4*iring + 1 - (ip - 2*iring*(iring-1));
  598 + *theta = acos(iring*iring / m_fact2 - 1.0);
  599 + *phi = (iphi - 0.5) * pi/(2.*iring);
513 600 }
514   -
  601 +
515 602 // Return
516 603 return;
517 604 }
... ... @@ -534,7 +621,7 @@ void GHealpix::pix2ang_nest(int ipix, double* theta, double* phi)
534 621  
535 622 // Get face number and index in face
536 623 int nl4 = 4 * m_nside;
537   - int face_num = ipix/m_npface; // Face number in {0,11}
  624 + int face_num = ipix >> (2*m_order); // Face number in {0,11}
538 625 int ipf = ipix & (m_npface - 1);
539 626  
540 627 // Get pixel coordinates
... ... @@ -543,7 +630,7 @@ void GHealpix::pix2ang_nest(int ipix, double* theta, double* phi)
543 630 pix2xy(ipf, &ix, &iy);
544 631  
545 632 // Computes the z coordinate on the sphere
546   - int jr = jrll[face_num]*m_nside - ix - iy - 1;
  633 + int jr = (jrll[face_num] << m_order) - ix - iy - 1;
547 634  
548 635 // Declare result variables
549 636 int nr;
... ... @@ -585,6 +672,118 @@ void GHealpix::pix2ang_nest(int ipix, double* theta, double* phi)
585 672 }
586 673  
587 674  
  675 +/***********************************************************************//**
  676 + * @brief Returns pixels which contains angular coordinates (z,phi)
  677 + *
  678 + * @param[in] z Cosine of zenith angle - cos(theta).
  679 + * @param[in] phi Azimuth angle in radians.
  680 + ***************************************************************************/
  681 +int GHealpix::ang2pix_z_phi_ring(double z, double phi) const
  682 +{
  683 + // Initialise pixel
  684 + int ipix = 0;
  685 +
  686 + // Setup
  687 + double za = abs(z);
  688 + double tt = modulo(phi,twopi) * inv_pihalf; // in [0,4)
  689 +
  690 + // Equatorial region
  691 + if (za <= twothird) {
  692 + double temp1 = m_nside*(0.5+tt);
  693 + double temp2 = m_nside*z*0.75;
  694 + int jp = int(temp1-temp2); // index of ascending edge line
  695 + int jm = int(temp1+temp2); // index of descending edge line
  696 + int ir = m_nside + 1 + jp - jm; // in {1,2n+1}
  697 + int kshift = 1 - (ir & 1); // kshift=1 if ir even, 0 otherwise
  698 + int ip = (jp+jm-m_nside+kshift+1)/2; // in {0,4n-1}
  699 + ip = modulo(ip,4*m_nside);
  700 + ipix = m_ncap + (ir-1)*4*m_nside + ip;
  701 + }
  702 +
  703 + // North & South polar caps
  704 + else {
  705 + double tp = tt - int(tt);
  706 + double tmp = m_nside * sqrt(3*(1-za));
  707 + int jp = int(tp*tmp); // increasing edge line index
  708 + int jm = int((1.0-tp)*tmp); // decreasing edge line index
  709 + int ir = jp + jm + 1; // ring number counted from the closest pole
  710 + int ip = int(tt*ir); // in {0,4*ir-1}
  711 + ip = modulo(ip,4*ir);
  712 + if (z>0)
  713 + ipix = 2*ir*(ir-1) + ip;
  714 + else
  715 + ipix = m_num_pixels - 2*ir*(ir+1) + ip;
  716 + }
  717 +
  718 + // Return pixel
  719 + return ipix;
  720 +}
  721 +
  722 +
  723 +/***********************************************************************//**
  724 + * @brief Returns pixels which contains angular coordinates (z,phi)
  725 + *
  726 + * @param[in] z Cosine of zenith angle - cos(theta).
  727 + * @param[in] phi Azimuth angle in radians.
  728 + ***************************************************************************/
  729 +int GHealpix::ang2pix_z_phi_nest(double z, double phi) const
  730 +{
  731 + // Initialise face and pixel numbers
  732 + int face_num;
  733 + int ix;
  734 + int iy;
  735 +
  736 + // Setup
  737 + double za = abs(z);
  738 + double tt = modulo(phi,twopi) * inv_pihalf; // in [0,4)
  739 +
  740 + // Equatorial region
  741 + if (za <= twothird) {
  742 + double temp1 = ns_max*(0.5+tt);
  743 + double temp2 = ns_max*z*0.75;
  744 + int jp = int(temp1-temp2); // index of ascending edge line
  745 + int jm = int(temp1+temp2); // index of descending edge line
  746 + int ifp = jp >> order_max; // in {0,4}
  747 + int ifm = jm >> order_max;
  748 + if (ifp == ifm) // faces 4 to 7
  749 + face_num = (ifp==4) ? 4: ifp+4;
  750 + else if (ifp < ifm) // (half-)faces 0 to 3
  751 + face_num = ifp;
  752 + else // (half-)faces 8 to 11
  753 + face_num = ifm + 8;
  754 + ix = jm & (ns_max-1);
  755 + iy = ns_max - (jp & (ns_max-1)) - 1;
  756 + }
  757 +
  758 + // Polar region, za > 2/3
  759 + else {
  760 + int ntt = int(tt);
  761 + double tp = tt-ntt;
  762 + double tmp = ns_max*sqrt(3*(1-za));
  763 + int jp = int(tp*tmp); // increasing edge line index
  764 + int jm = int((1.0-tp)*tmp); // decreasing edge line index
  765 + if (jp >= ns_max) jp = ns_max-1; // for points too close to the boundary
  766 + if (jm >= ns_max) jm = ns_max-1;
  767 + if (z >= 0) {
  768 + face_num = ntt; // in {0,3}
  769 + ix = ns_max - jm - 1;
  770 + iy = ns_max - jp - 1;
  771 + }
  772 + else {
  773 + face_num = ntt + 8; // in {8,11}
  774 + ix = jp;
  775 + iy = jm;
  776 + }
  777 + }
  778 +
  779 + // Get pixel
  780 + int ipf = xy2pix(ix, iy);
  781 + ipf >>= (2*(order_max - m_order)); // in {0, nside**2 - 1}
  782 + return ipf + (face_num<<(2*m_order)); // in {0, 12*nside**2 - 1}
  783 +}
  784 +
  785 +
  786 +
588 787 /*==========================================================================
589 788 = =
590 789 = GHealpix friends =
... ... @@ -601,15 +800,18 @@ ostream&amp; operator&lt;&lt; (ostream&amp; os, const GHealpix&amp; pixels)
601 800 {
602 801 // Put header in stream
603 802 os << "=== GHealpix ===" << endl;
604   - os << " Number of base pixel div. .: " << pixels.m_nside << endl;
605   - os << " Number of pixels ..........: " << pixels.m_num_pixels << endl;
  803 + os << " Nside (number of divisions): " << pixels.m_nside << endl;
  804 + os << " Npface (pixels per face) ..: " << pixels.m_npface << endl;
  805 + os << " Ncap (number of cap pixels): " << pixels.m_ncap << endl;
  806 + os << " Npix (number of pixels) ...: " << pixels.m_num_pixels << endl;
  807 + os << " Order .....................: " << pixels.m_order << endl;
606 808 os << " Pixel vector size .........: " << pixels.m_size_pixels << endl;
607 809 os << " Solid angle ...............: " << scientific << pixels.m_omega
608   - << fixed << endl;
  810 + << fixed << " sr" << endl;
609 811  
610 812 // Put ordering in stream
611 813 os << " Ordering ..................: ";
612   - switch (pixels.m_order) {
  814 + switch (pixels.m_scheme) {
613 815 case 0:
614 816 os << "Ring" << endl;
615 817 break;
... ... @@ -628,22 +830,19 @@ ostream&amp; operator&lt;&lt; (ostream&amp; os, const GHealpix&amp; pixels)
628 830 os << " Coordinate system .........: ";
629 831 switch (pixels.m_coordsys) {
630 832 case 0:
631   - os << "Equatorial (RA,Dec)" << endl;
  833 + os << "Equatorial (RA,Dec)";
632 834 break;
633 835 case 1:
634   - os << "Galactic (l,b)" << endl;
  836 + os << "Galactic (l,b)";
635 837 break;
636 838 case -1:
637   - os << "*** Unknown ***" << endl;
  839 + os << "*** Unknown ***";
638 840 break;
639 841 default:
640   - os << "*** Invalid ***" << endl;
  842 + os << "*** Invalid ***";
641 843 break;
642 844 }
643 845  
644   - for (int i = 0; i < pixels.m_num_pixels; ++i)
645   - os << pixels.m_dir[i] << " ";
646   -
647 846 // Return output stream
648 847 return os;
649 848 }
... ... @@ -654,3 +853,16 @@ ostream&amp; operator&lt;&lt; (ostream&amp; os, const GHealpix&amp; pixels)
654 853 = Other functions used by GHealpix =
655 854 = =
656 855 ==========================================================================*/
  856 +
  857 +/***********************************************************************//**
  858 + * @brief Integer n that fulfills n*n <= arg < (n+1)*(n+1)
  859 + *
  860 + * @param[in] arg Argument.
  861 + *
  862 + * Returns the integer \a n, which fulfills \a n*n <= arg < (n+1)*(n+1).
  863 + ***************************************************************************/
  864 +unsigned int isqrt(unsigned int arg)
  865 +{
  866 + // Return
  867 + return unsigned(sqrt(arg+0.5));
  868 +}
... ...