inlib
1.2.0
|
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