inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/healpix
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_healpix
00005 #define inlib_healpix
00006 
00007 //from HEALPix/2.15a.
00008 // Copyright (C) 1997-2010 Krzysztof M. Gorski, Eric Hivon, 
00009 //                         Benjamin D. Wandelt, Anthony J. Banday, 
00010 //                         Matthias Bartelmann, 
00011 //                         Reza Ansari & Kenneth M. Ganga 
00012 
00013 #include <cmath>
00014 #include <ostream>
00015 
00016 #include "math"
00017 
00018 namespace inlib {
00019 namespace healpix {
00020 
00021 inline int fmodi(int a_x,int a_y) {
00022   return (int)::fmod((double)a_x,(double)a_y); 
00023 }
00024 
00025 inline void mk_xy2pix(int *x2pix, int *y2pix) {
00026    // sets the array giving the number of the pixel lying in (x,y)
00027    // x and y are in {1,128}
00028    // the pixel number is in {0,128**2-1}
00029    //   
00030    // if  i-1 = sum_p=0  b_p * 2^p
00031    // then ix = sum_p=0  b_p * 4^p
00032    // iy = 2*ix
00033    // ix + iy in {0, 128**2 -1}
00034 
00035   int i, K,IP,I,J,ID;
00036   
00037   for(i = 0; i < 127; i++) x2pix[i] = 0;
00038   for( I=1;I<=128;I++ ) {
00039     J  = I-1;//            !pixel numbers
00040     K  = 0;//
00041     IP = 1;//
00042     truc : if( J==0 ) {
00043       x2pix[I-1] = K;
00044       y2pix[I-1] = 2*K;
00045     }
00046     else {
00047       ID = fmodi(J,2);
00048       J  = J/2;
00049       K  = IP*ID+K;
00050       IP = IP*4;
00051       goto truc;
00052     }
00053   }     
00054   
00055 }
00056 
00057 inline bool ang2pix_nest(std::ostream& a_out,
00058                          long a_nside,
00059                          double a_theta,double a_phi,
00060                          long& a_ipix) {
00061 
00062   // gives the pixel number ipix (NESTED) corresponding to angles theta and phi
00063   //
00064   // the computation is made to the highest resolution available (nside=8192)
00065   // and then degraded to that required (by integer division)
00066   // this doesn't cost more, and it makes sure that the treatement of
00067   // round-off will be consistent for every resolution
00068   
00069   int ns_max = 8192;
00070 
00071   if( a_nside<1 || a_nside>long(ns_max) ) {
00072     a_out << "inlib::healpix::ang2pix_nest :"
00073           << " nside out of range " << (int)a_nside
00074           << std::endl;
00075     return false;
00076   }
00077   if( a_theta<0. || a_theta>pi() ) {
00078     a_out << "inlib::healpix::ang2pix_nest :"
00079           << " theta out of range " << a_theta
00080           << std::endl;
00081     return false;
00082   }
00083 
00084   static int x2pix[128], y2pix[128];
00085   static bool setup_done = false;
00086   if(!setup_done ) {
00087     mk_xy2pix(x2pix,y2pix);
00088     setup_done = true;
00089   }
00090   
00091   if( a_phi>=two_pi() ) a_phi = a_phi - two_pi();
00092   else if( a_phi<0. )   a_phi = a_phi + two_pi();
00093 
00094   double tt = a_phi / half_pi(); // in [0,4[
00095   
00096   double z  = ::cos(a_theta);
00097   double za = ::fabs(z);
00098   double z0 = 2./3.;
00099 
00100   int    face_num,jp,jm;
00101   long   ifp, ifm;
00102   int    ix, iy, ipf, ntt;
00103 
00104   if( za<=z0 ) { // equatorial region
00105     
00106     // (the index of edge lines increase when the longitude=phi goes up)
00107     jp = (int)::floor(ns_max*(0.5 + tt - z*0.75));// ascending edge line index
00108     jm = (int)::floor(ns_max*(0.5 + tt + z*0.75));// descending edge line index
00109     
00110     // finds the face
00111     ifp = jp / ns_max; // in {0,4}
00112     ifm = jm / ns_max;
00113     
00114     if( ifp==ifm ) face_num = fmodi(ifp,4) + 4; // faces 4 to 7
00115     else if( ifp<ifm ) face_num = fmodi(ifp,4); // (half-)faces 0 to 3
00116     else face_num = fmodi(ifm,4) + 8;           // (half-)faces 8 to 11
00117     
00118     ix = fmodi(jm, ns_max);
00119     iy = ns_max - fmodi(jp, ns_max) - 1;
00120 
00121   } else { // polar region, za > 2/3
00122     
00123     ntt = (int)::floor(tt);
00124     if( ntt>=4 ) ntt = 3;
00125     double tp = tt - ntt;
00126     double tmp = ::sqrt( 3.*(1. - za) ); // in ]0,1]
00127     
00128     // (the index of edge lines increase when distance from the closest pole
00129     // goes up)
00130     // line going toward the pole as phi increases
00131 
00132     jp = (int)::floor( ns_max * tp          * tmp ); 
00133 
00134     // that one goes away of the closest pole
00135     jm = (int)::floor( ns_max * (1. - tp) * tmp );
00136     jp = (int)(jp < ns_max-1 ? jp : ns_max-1);
00137     jm = (int)(jm < ns_max-1 ? jm : ns_max-1);
00138     
00139     // finds the face and pixel's (x,y)
00140     if( z>=0 ) {
00141       face_num = ntt; // in {0,3}
00142       ix = ns_max - jm - 1;
00143       iy = ns_max - jp - 1;
00144     }
00145     else {
00146       face_num = ntt + 8; // in {8,11}
00147       ix =  jp;
00148       iy =  jm;
00149     }
00150   }
00151   
00152   int ix_low = fmodi(ix,128);
00153   int ix_hi  =     ix/128;
00154   int iy_low = fmodi(iy,128);
00155   int iy_hi  =     iy/128;
00156 
00157   ipf = (x2pix[ix_hi]+y2pix[iy_hi]) * (128 * 128)+
00158         (x2pix[ix_low]+y2pix[iy_low]);
00159   ipf = (long)(ipf / ::pow(ns_max/a_nside,2));     // in {0, a_nside**2 - 1}
00160   a_ipix =(long)( ipf + face_num*::pow(a_nside,2)); // in {0, 12*a_nside**2-1}
00161   return true;
00162 }
00163 
00164 inline bool ang2pix_ring(std::ostream& a_out,
00165                          long a_nside,
00166                          double a_theta,double a_phi,
00167                          long& a_ipix) {
00168   // gives the pixel number ipix (RING) 
00169   // corresponding to angles theta and phi
00170   
00171   long ns_max=8192;
00172 
00173   if( a_nside<1 || a_nside>ns_max ) {
00174     a_out << "inlib::healpix::ang2pix_ring :"
00175           << " nside out of range " << (int)a_nside
00176           << std::endl;
00177     return false;
00178   }
00179   if( a_theta<0. || a_theta>pi() ) {
00180     a_out << "inlib::healpix::ang2pix_ring :"
00181           << " theta out of range " << a_theta
00182           << std::endl;
00183     return false;
00184   }
00185   
00186   if( a_phi>=two_pi() ) a_phi = a_phi - two_pi();
00187   else if( a_phi<0. )   a_phi = a_phi + two_pi();
00188 
00189   double z = ::cos(a_theta);
00190   double za = ::fabs(z);
00191 
00192   double tt = a_phi / half_pi();//  ! in [0,4)
00193   
00194   double z0=2.0/3.0;
00195   
00196   int nl2 = 2*a_nside;
00197   int nl4 = 4*a_nside;
00198   int ncap  = nl2*(a_nside-1);// ! number of pixels in the north polar cap
00199   int npix  = 12*a_nside*a_nside;
00200   
00201   int jp, jm, ipix1;
00202   int ir, ip, kshift;
00203   
00204   if( za <= z0 ) {
00205     
00206     jp = (int)::floor(a_nside*(0.5+tt-z*0.75)); //index of ascending edge line
00207     jm = (int)::floor(a_nside*(0.5+tt+z*0.75)); //index of descending edge line
00208     
00209     ir = a_nside + 1 + jp - jm; //in {1,2n+1} (ring number counted from z=2/3)
00210     kshift = 0;
00211     if (fmodi(ir,2)==0) kshift = 1;// ! kshift=1 if ir even, 0 otherwise
00212     
00213     ip = (int)::floor( double(jp+jm-a_nside+kshift+1)/2) + 1; //in {1,4n}
00214     if( ip>nl4 ) ip = ip - nl4;
00215     
00216     ipix1 = ncap + nl4*(ir-1) + ip ;
00217 
00218   } else {
00219     
00220     double tp = tt - ::floor(tt); 
00221     double tmp = ::sqrt( 3.*(1. - za) );
00222     
00223     jp = (int)::floor( a_nside * tp * tmp ); //increasing edge line index
00224     jm = (int)::floor( a_nside * (1. - tp) * tmp );//decreasing edge line index
00225     
00226     ir = jp + jm + 1; //ring number counted from the closest pole
00227     ip = (int)::floor( tt * ir ) + 1;// ! in {1,4*ir}
00228     if( ip>4*ir ) ip = ip - 4*ir;
00229     
00230     ipix1 = 2*ir*(ir-1) + ip;
00231     if( z<=0. ) {
00232       ipix1 = npix - 2*ir*(ir+1) + ip;
00233     }
00234   }
00235   a_ipix = ipix1 - 1;// ! in {0, npix-1}
00236   
00237   return true;
00238 }
00239 
00240 }}
00241 
00242 #endif
00243 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines