Main Page | Modules | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

healpix_base.cc

00001 /*
00002  *  This file is part of Healpix_cxx.
00003  *
00004  *  Healpix_cxx is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  Healpix_cxx is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with Healpix_cxx; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  *
00018  *  For more information about HEALPix, see http://healpix.jpl.nasa.gov
00019  */
00020 
00021 /*
00022  *  Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik
00023  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00024  *  (DLR).
00025  */
00026 
00027 /*
00028  *  Copyright (C) 2003, 2004 Max-Planck-Society
00029  *  Author: Martin Reinecke
00030  */
00031 
00032 #include "healpix_base.h"
00033 #include "cxxutils.h"
00034 #include "pointing.h"
00035 #include "arr.h"
00036 
00037 using namespace std;
00038 
00039 short Healpix_Base::ctab[];
00040 short Healpix_Base::utab[];
00041 
00042 const nside_dummy SET_NSIDE=nside_dummy();
00043 
00044 Healpix_Base::Tablefiller::Tablefiller()
00045   {
00046   for (int m=0; m<0x100; ++m)
00047     {
00048     ctab[m] =
00049          (m&0x1 )       | ((m&0x2 ) << 7) | ((m&0x4 ) >> 1) | ((m&0x8 ) << 6)
00050       | ((m&0x10) >> 2) | ((m&0x20) << 5) | ((m&0x40) >> 3) | ((m&0x80) << 4);
00051     utab[m] =
00052          (m&0x1 )       | ((m&0x2 ) << 1) | ((m&0x4 ) << 2) | ((m&0x8 ) << 3)
00053       | ((m&0x10) << 4) | ((m&0x20) << 5) | ((m&0x40) << 6) | ((m&0x80) << 7);
00054     }
00055   }
00056 
00057 Healpix_Base::Tablefiller Healpix_Base::Filler;
00058 
00059 const int Healpix_Base::jrll[] = { 2,2,2,2,3,3,3,3,4,4,4,4 };
00060 const int Healpix_Base::jpll[] = { 1,3,5,7,0,2,4,6,1,3,5,7 };
00061 
00062 int Healpix_Base::nside2order (int nside)
00063   {
00064   for (int m=0; m<=order_max; ++m)
00065     {
00066     int nstest = 1<<m;
00067     if (nside == nstest) return m;
00068     if (nside < nstest) return -1;
00069     }
00070   return -1;
00071   }
00072 int Healpix_Base::npix2nside (int npix)
00073   {
00074   int res=isqrt(npix/12);
00075   planck_assert (npix==res*res*12, "npix2nside: invalid argument");
00076   return res;
00077   }
00078 
00079 int Healpix_Base::xy2pix (int x, int y)
00080   {
00081   return utab[x&0xff] | (utab[x>>8]<<16) | (utab[y&0xff]<<1) | (utab[y>>8]<<17);
00082   }
00083 int Healpix_Base::x2pix (int x)
00084   {
00085   return utab[x&0xff] | (utab[x>>8]<<16);
00086   }
00087 int Healpix_Base::y2pix (int y)
00088   {
00089   return (utab[y&0xff]<<1) | (utab[y>>8]<<17);
00090   }
00091 
00092 void Healpix_Base::pix2xy (int pix, int &x, int &y)
00093   {
00094   int raw = (pix&0x5555) | ((pix&0x55550000)>>15);
00095   x = ctab[raw&0xff] | (ctab[raw>>8]<<4);
00096   raw = ((pix&0xaaaa)>>1) | ((pix&0xaaaa0000)>>16);
00097   y = ctab[raw&0xff] | (ctab[raw>>8]<<4);
00098   }
00099 
00100 int Healpix_Base::ring_above (double z) const
00101   {
00102   double az=abs(z);
00103   if (az>twothird) // polar caps
00104     {
00105     int iring = int(nside_*sqrt(3*(1-az)));
00106     return (z>0) ? iring : 4*nside_-iring-1;
00107     }
00108   else // ----- equatorial region ---------
00109     return int(nside_*(2-1.5*z));
00110   }
00111 
00112 void Healpix_Base::in_ring(int iz, double phi0, double dphi,
00113   vector<int> &listir) const
00114   {
00115   int nr, ir, ipix1;
00116   double shift=0.5;
00117 
00118   if (iz<nside_) // north pole
00119     {
00120     ir = iz;
00121     nr = ir*4;
00122     ipix1 = 2*ir*(ir-1);        //    lowest pixel number in the ring
00123     }
00124   else if (iz>(3*nside_)) // south pole
00125     {
00126     ir = 4*nside_ - iz;
00127     nr = ir*4;
00128     ipix1 = npix_ - 2*ir*(ir+1); // lowest pixel number in the ring
00129     }
00130   else // equatorial region
00131     {
00132     ir = iz - nside_ + 1;           //    within {1, 2*nside + 1}
00133     nr = nside_*4;
00134     if ((ir&1)==0) shift = 0;
00135     ipix1 = ncap_ + (ir-1)*nr; // lowest pixel number in the ring
00136     }
00137 
00138   int ipix2 = ipix1 + nr - 1;       //    highest pixel number in the ring
00139 
00140    // ----------- constructs the pixel list --------------
00141   if (dphi > (pi-1e-7))
00142     for (int i=ipix1; i<=ipix2; ++i) listir.push_back(i);
00143   else
00144     {
00145     int ip_lo = intfloor(nr*inv_twopi*(phi0-dphi) - shift)+1;
00146     int ip_hi = intfloor(nr*inv_twopi*(phi0+dphi) - shift);
00147     int pixnum = ip_lo+ipix1;
00148     if (pixnum<ipix1) pixnum += nr;
00149     for (int i=ip_lo; i<=ip_hi; ++i, ++pixnum)
00150       {
00151       if (pixnum>ipix2) pixnum -= nr;
00152       listir.push_back(pixnum);
00153       }
00154     }
00155   }
00156 
00157 void Healpix_Base::nest2xyf (int pix, int &ix, int &iy, int &face_num) const
00158   {
00159   face_num = pix>>(2*order_);
00160   pix2xy(pix&(npface_-1),ix,iy);
00161   }
00162 
00163 int Healpix_Base::xyf2nest (int ix, int iy, int face_num) const
00164   {
00165   return (face_num<<(2*order_))+xy2pix(ix,iy);
00166   }
00167 
00168 void Healpix_Base::ring2xyf (int pix, int &ix, int &iy, int &face_num) const
00169   {
00170   int iring, iphi, kshift, nr;
00171 
00172   int nl2 = 2*nside_;
00173 
00174   if (pix<ncap_) // North Polar cap
00175     {
00176     iring = int(0.5*(1+isqrt(1+2*pix))); //counted from North pole
00177     iphi  = (pix+1) - 2*iring*(iring-1);
00178     kshift = 0;
00179     nr = iring;
00180     face_num=0;
00181     int tmp = iphi-1;
00182     if (tmp>=(2*iring))
00183       {
00184       face_num=2;
00185       tmp-=2*iring;
00186       }
00187     if (tmp>=iring) ++face_num;
00188     }
00189   else if (pix<(npix_-ncap_)) // Equatorial region
00190     {
00191     int ip = pix - ncap_;
00192     if (order_>=0)
00193       {
00194       iring = (ip>>(order_+2)) + nside_; // counted from North pole
00195       iphi  = (ip&(4*nside_-1)) + 1;
00196       }
00197     else
00198       {
00199       iring = (ip/(4*nside_)) + nside_; // counted from North pole
00200       iphi  = (ip%(4*nside_)) + 1;
00201       }
00202     kshift = (iring+nside_)&1;
00203     nr = nside_;
00204     unsigned int ire = iring-nside_+1;
00205     unsigned int irm = nl2+2-ire;
00206     int ifm, ifp;
00207     if (order_>=0)
00208       {
00209       ifm = (iphi - ire/2 + nside_ -1) >> order_;
00210       ifp = (iphi - irm/2 + nside_ -1) >> order_;
00211       }
00212     else
00213       {
00214       ifm = (iphi - ire/2 + nside_ -1) / nside_;
00215       ifp = (iphi - irm/2 + nside_ -1) / nside_;
00216       }
00217     if (ifp == ifm) // faces 4 to 7
00218       face_num = (ifp==4) ? 4 : ifp+4;
00219     else if (ifp<ifm) // (half-)faces 0 to 3
00220       face_num = ifp;
00221     else // (half-)faces 8 to 11
00222       face_num = ifm + 8;
00223     }
00224   else // South Polar cap
00225     {
00226     int ip = npix_ - pix;
00227     iring = int(0.5*(1+isqrt(2*ip-1))); //counted from South pole
00228     iphi  = 4*iring + 1 - (ip - 2*iring*(iring-1));
00229     kshift = 0;
00230     nr = iring;
00231     iring = 2*nl2-iring;
00232     face_num=8;
00233     int tmp = iphi-1;
00234     if (tmp>=(2*nr))
00235       {
00236       face_num=10;
00237       tmp-=2*nr;
00238       }
00239     if (tmp>=nr) ++face_num;
00240     }
00241 
00242   int irt = iring - (jrll[face_num]*nside_) + 1;
00243   int ipt = 2*iphi- jpll[face_num]*nr - kshift -1;
00244   if (ipt>=nl2) ipt-=8*nside_;
00245 
00246   ix =  (ipt-irt) >>1;
00247   iy =(-(ipt+irt))>>1;
00248   }
00249 
00250 int Healpix_Base::xyf2ring (int ix, int iy, int face_num) const
00251   {
00252   int nl4 = 4*nside_;
00253   int jr = (jrll[face_num]*nside_) - ix - iy  - 1;
00254 
00255   int nr, kshift, n_before;
00256   if (jr<nside_)
00257     {
00258     nr = jr;
00259     n_before = 2*nr*(nr-1);
00260     kshift = 0;
00261     }
00262   else if (jr > 3*nside_)
00263     {
00264     nr = nl4-jr;
00265     n_before = npix_ - 2*(nr+1)*nr;
00266     kshift = 0;
00267     }
00268   else
00269     {
00270     nr = nside_;
00271     n_before = ncap_ + (jr-nside_)*nl4;
00272     kshift = (jr-nside_)&1;
00273     }
00274 
00275   int jp = (jpll[face_num]*nr + ix - iy + 1 + kshift) / 2;
00276   if (jp>nl4)
00277     jp-=nl4;
00278   else
00279     if (jp<1) jp+=nl4;
00280 
00281   return n_before + jp - 1;
00282   }
00283 
00284 int Healpix_Base::nest2ring (int pix) const
00285   {
00286   planck_assert(order_>=0, "nest2ring: need hierarchical map");
00287   int ix, iy, face_num;
00288   nest2xyf (pix, ix, iy, face_num);
00289   return xyf2ring (ix, iy, face_num);
00290   }
00291 
00292 int Healpix_Base::ring2nest (int pix) const
00293   {
00294   planck_assert(order_>=0, "ring2nest: need hierarchical map");
00295   int ix, iy, face_num;
00296   ring2xyf (pix, ix, iy, face_num);
00297   return xyf2nest (ix, iy, face_num);
00298   }
00299 
00300 int Healpix_Base::ang2pix_z_phi (double z, double phi) const
00301   {
00302   double za = abs(z);
00303   double tt = modulo(phi,twopi) * inv_halfpi; // in [0,4)
00304 
00305   if (scheme_==RING)
00306     {
00307     if (za<=twothird) // Equatorial region
00308       {
00309       double temp1 = nside_*(0.5+tt);
00310       double temp2 = nside_*z*0.75;
00311       int jp = int(temp1-temp2); // index of  ascending edge line
00312       int jm = int(temp1+temp2); // index of descending edge line
00313 
00314       // ring number counted from z=2/3
00315       int ir = nside_ + 1 + jp - jm; // in {1,2n+1}
00316       int kshift = 1-(ir&1); // kshift=1 if ir even, 0 otherwise
00317 
00318       int ip = (jp+jm-nside_+kshift+1)/2; // in {0,4n-1}
00319       ip = modulo(ip,4*nside_);
00320 
00321       return ncap_ + (ir-1)*4*nside_ + ip;
00322       }
00323     else  // North & South polar caps
00324       {
00325       double tp = tt-int(tt);
00326       double tmp = nside_*sqrt(3*(1-za));
00327 
00328       int jp = int(tp*tmp); // increasing edge line index
00329       int jm = int((1.0-tp)*tmp); // decreasing edge line index
00330 
00331       int ir = jp+jm+1; // ring number counted from the closest pole
00332       int ip = int(tt*ir); // in {0,4*ir-1}
00333       ip = modulo(ip,4*ir);
00334 
00335       if (z>0)
00336         return 2*ir*(ir-1) + ip;
00337       else
00338         return npix_ - 2*ir*(ir+1) + ip;
00339       }
00340     }
00341   else // scheme_ == NEST
00342     {
00343     const int ns_max = 1<<order_max;
00344     int face_num, ix, iy;
00345 
00346     if (za<=twothird) // Equatorial region
00347       {
00348       double temp1 = ns_max*(0.5+tt);
00349       double temp2 = ns_max*z*0.75;
00350       int jp = int(temp1-temp2); // index of  ascending edge line
00351       int jm = int(temp1+temp2); // index of descending edge line
00352       int ifp = jp >> order_max;  // in {0,4}
00353       int ifm = jm >> order_max;
00354       if (ifp == ifm)           // faces 4 to 7
00355         face_num = (ifp==4) ? 4: ifp+4;
00356       else if (ifp < ifm)       // (half-)faces 0 to 3
00357         face_num = ifp;
00358       else                      // (half-)faces 8 to 11
00359         face_num = ifm + 8;
00360 
00361       ix = jm & (ns_max-1);
00362       iy = ns_max - (jp & (ns_max-1)) - 1;
00363       }
00364     else // polar region, za > 2/3
00365       {
00366       int ntt = int(tt);
00367       double tp = tt-ntt;
00368       double tmp = ns_max*sqrt(3*(1-za));
00369 
00370       int jp = int(tp*tmp); // increasing edge line index
00371       int jm = int((1.0-tp)*tmp); // decreasing edge line index
00372       if (jp>=ns_max) jp = ns_max-1; // for points too close to the boundary
00373       if (jm>=ns_max) jm = ns_max-1;
00374       if (z >= 0)
00375         {
00376         face_num = ntt;  // in {0,3}
00377         ix = ns_max - jm - 1;
00378         iy = ns_max - jp - 1;
00379         }
00380       else
00381         {
00382         face_num = ntt + 8; // in {8,11}
00383         ix =  jp;
00384         iy =  jm;
00385         }
00386       }
00387 
00388     int ipf = xy2pix (ix, iy);
00389 
00390     ipf >>= (2*(order_max-order_));  // in {0, nside**2 - 1}
00391 
00392     return ipf + (face_num<<(2*order_));    // in {0, 12*nside**2 - 1}
00393     }
00394   }
00395 
00396 pointing Healpix_Base::pix2ang (int pix) const
00397   {
00398   if (scheme_==RING)
00399     {
00400     if (pix<ncap_) // North Polar cap
00401       {
00402       int iring = int(0.5*(1+isqrt(1+2*pix))); //counted from North pole
00403       int iphi  = (pix+1) - 2*iring*(iring-1);
00404 
00405       return pointing (acos(1.0 - (iring*iring)*fact2_),
00406                        (iphi-0.5) * pi/(2.0*iring));
00407       }
00408     else if (pix<(npix_-ncap_)) // Equatorial region
00409       {
00410       int ip  = pix - ncap_;
00411       int iring = ip/(4*nside_) + nside_; // counted from North pole
00412       int iphi  = ip%(4*nside_) + 1;
00413       // 1 if iring+nside is odd, 1/2 otherwise
00414       double fodd = ((iring+nside_)&1) ? 1 : 0.5;
00415 
00416       int nl2 = 2*nside_;
00417       return pointing (acos((nl2-iring)*fact1_),
00418                        (iphi-fodd) * pi/nl2);
00419       }
00420     else // South Polar cap
00421       {
00422       int ip = npix_ - pix;
00423       int iring = int(0.5*(1+isqrt(2*ip-1))); //counted from South pole
00424       int iphi  = 4*iring + 1 - (ip - 2*iring*(iring-1));
00425 
00426       return pointing (acos(-1.0 + (iring*iring)*fact2_),
00427                        (iphi-0.5) * pi/(2*iring));
00428       }
00429     }
00430   else
00431     {
00432     int nl4 = nside_*4;
00433 
00434     int face_num = pix>>(2*order_);
00435     int ipf = pix&(npface_-1);
00436 
00437     int ix, iy;
00438     pix2xy(ipf,ix,iy);
00439 
00440     int jr = (jrll[face_num]<<order_) - ix - iy - 1;
00441 
00442     int nr, kshift;
00443     double z;
00444     if (jr<nside_)
00445       {
00446       nr = jr;
00447       z = 1 - nr*nr*fact2_;
00448       kshift = 0;
00449       }
00450     else if (jr > 3*nside_)
00451       {
00452       nr = nl4-jr;
00453       z = nr*nr*fact2_ - 1;
00454       kshift = 0;
00455       }
00456     else
00457       {
00458       nr = nside_;
00459       z = (2*nside_-jr)*fact1_;
00460       kshift = (jr-nside_)&1;
00461       }
00462 
00463     int jp = (jpll[face_num]*nr + ix -iy + 1 + kshift) / 2;
00464     if (jp>nl4) jp-=nl4;
00465     if (jp<1) jp+=nl4;
00466 
00467     return pointing (acos(z), (jp-(kshift+1)*0.5)*(halfpi/nr));
00468     }
00469   }
00470 
00471 void Healpix_Base::query_disc (const pointing &ptg, double radius,
00472   vector<int>& listpix) const
00473   {
00474   listpix.clear();
00475 
00476   double dth1 = fact2_;
00477   double dth2 = fact1_;
00478   double cosang = cos(radius);
00479 
00480   double z0 = cos(ptg.theta);
00481   double xa = 1./sqrt((1-z0)*(1+z0));
00482 
00483   double rlat1  = ptg.theta - radius;
00484   double zmax = cos(rlat1);
00485   int irmin = ring_above (zmax)+1;
00486 
00487   if (rlat1<=0) // north pole in the disc
00488     for (int m=1; m<irmin; ++m) // rings completely in the disc
00489       in_ring (m, 0, pi, listpix);
00490 
00491   double rlat2  = ptg.theta + radius;
00492   double zmin = cos(rlat2);
00493   int irmax = ring_above (zmin);
00494 
00495 // ------------- loop on ring number ---------------------
00496   for (int iz=irmin; iz<=irmax; ++iz) // rings partially in the disc
00497     {
00498     double z;
00499     if (iz<nside_) // north polar cap
00500       z = 1.0 - iz*iz*dth1;
00501     else if (iz <= (3*nside_)) // tropical band + equat.
00502       z = (2*nside_-iz) * dth2;
00503     else
00504       z = -1.0 + (4*nside_-iz)*(4*nside_-iz)*dth1;
00505 
00506 // --------- phi range in the disc for each z ---------
00507     double x = (cosang-z*z0)*xa;
00508     double ysq = 1-z*z-x*x;
00509     planck_assert(ysq>=0, "error in query_disc()");
00510     double dphi=atan2(sqrt(ysq),x);
00511     in_ring (iz, ptg.phi, dphi, listpix);
00512     }
00513 
00514   if (rlat2>=pi) // south pole in the disc
00515     for (int m=irmax+1; m<(4*nside_); ++m)  // rings completely in the disc
00516       in_ring (m, 0, pi, listpix);
00517 
00518   if (scheme_==NEST)
00519     for (unsigned int m=0; m<listpix.size(); ++m)
00520       listpix[m] = ring2nest(listpix[m]);
00521   }
00522 
00523 void Healpix_Base::get_ring_info (int ring, int &startpix, int &ringpix,
00524   double &costheta, double &sintheta, bool &shifted) const
00525   {
00526   planck_assert(scheme_==RING,"map must be in RING scheme");
00527   int northring = (ring>2*nside_) ? 4*nside_-ring : ring;
00528   if (northring < nside_)
00529     {
00530     costheta = 1 - northring*northring*fact2_;
00531     sintheta = sin(2*asin(northring/(sqrt(6.)*nside_)));
00532     ringpix = 4*northring;
00533     shifted = true;
00534     startpix = 2*northring*(northring-1);
00535     }
00536   else
00537     {
00538     costheta = (2*nside_-northring)*fact1_;
00539     sintheta = sqrt((1+costheta)*(1-costheta));
00540     ringpix = 4*nside_;
00541     shifted = ((northring-nside_) & 1) == 0;
00542     startpix = ncap_ + (northring-nside_)*ringpix;
00543     }
00544   if (northring != ring) // southern hemisphere
00545     {
00546     costheta = -costheta;
00547     startpix = npix_ - startpix - ringpix;
00548     }
00549   }
00550 
00551 void Healpix_Base::neighbors (int pix, fix_arr<int,8> &result) const
00552   {
00553   static const int xoffset[] = { -1,-1, 0, 1, 1, 1, 0,-1 };
00554   static const int yoffset[] = {  0, 1, 1, 1, 0,-1,-1,-1 };
00555   static const int facearray[][12] =
00556         { {  8, 9,10,11,-1,-1,-1,-1,10,11, 8, 9 },   // S
00557           {  5, 6, 7, 4, 8, 9,10,11, 9,10,11, 8 },   // SE
00558           { -1,-1,-1,-1, 5, 6, 7, 4,-1,-1,-1,-1 },   // E
00559           {  4, 5, 6, 7,11, 8, 9,10,11, 8, 9,10 },   // SW
00560           {  0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 },   // center
00561           {  1, 2, 3, 0, 0, 1, 2, 3, 5, 6, 7, 4 },   // NE
00562           { -1,-1,-1,-1, 7, 4, 5, 6,-1,-1,-1,-1 },   // W
00563           {  3, 0, 1, 2, 3, 0, 1, 2, 4, 5, 6, 7 },   // NW
00564           {  2, 3, 0, 1,-1,-1,-1,-1, 0, 1, 2, 3 } }; // N
00565   static const int swaparray[][12] =
00566         { {  0,0,0,0,0,0,0,0,3,3,3,3 },   // S
00567           {  0,0,0,0,0,0,0,0,6,6,6,6 },   // SE
00568           {  0,0,0,0,0,0,0,0,0,0,0,0 },   // E
00569           {  0,0,0,0,0,0,0,0,5,5,5,5 },   // SW
00570           {  0,0,0,0,0,0,0,0,0,0,0,0 },   // center
00571           {  5,5,5,5,0,0,0,0,0,0,0,0 },   // NE
00572           {  0,0,0,0,0,0,0,0,0,0,0,0 },   // W
00573           {  6,6,6,6,0,0,0,0,0,0,0,0 },   // NW
00574           {  3,3,3,3,0,0,0,0,0,0,0,0 } }; // N
00575 
00576   int ix, iy, face_num;
00577   (scheme_==RING) ?
00578     ring2xyf(pix,ix,iy,face_num) : nest2xyf(pix,ix,iy,face_num);
00579 
00580   const int nsm1 = nside_-1;
00581   if ((ix>0)&&(ix<nsm1)&&(iy>0)&&(iy<nsm1))
00582     {
00583     if (scheme_==RING)
00584       for (int m=0; m<8; ++m)
00585         result[m] = xyf2ring(ix+xoffset[m],iy+xoffset[m],face_num);
00586     else
00587       for (int m=0; m<8; ++m)
00588         result[m] = xyf2nest(ix+xoffset[m],iy+xoffset[m],face_num);
00589     }
00590   else
00591     {
00592     for (int i=0; i<8; ++i)
00593       {
00594       int x=ix+xoffset[i];
00595       int y=iy+yoffset[i];
00596       int nbnum=4;
00597       if (x<0)
00598         { x+=nside_; nbnum-=1; }
00599       else if (x>=nside_)
00600         { x-=nside_; nbnum+=1; }
00601       if (y<0)
00602         { y+=nside_; nbnum-=3; }
00603       else if (y>=nside_)
00604         { y-=nside_; nbnum+=3; }
00605 
00606       int f = facearray[nbnum][face_num];
00607       if (f>=0)
00608         {
00609         if (swaparray[nbnum][face_num]&1) x=nside_-x-1;
00610         if (swaparray[nbnum][face_num]&2) y=nside_-y-1;
00611         if (swaparray[nbnum][face_num]&4) std::swap(x,y);
00612         result[i] = (scheme_==RING) ? xyf2ring(x,y,f) : xyf2nest(x,y,f);
00613         }
00614       else
00615         result[i] = -1;
00616       }
00617     }
00618   }
00619 
00620 namespace {
00621 
00622 void add_weights (int p1, int p2, int p3, int p4, double xdiff, double ydiff,
00623                   fix_arr<int,4> &pix, fix_arr<double,4> &wgt)
00624   {
00625   pix[0] = p1;
00626   pix[1] = p2;
00627   pix[2] = p3;
00628 
00629   if (p4>=0)
00630     {
00631     wgt[0] = (1-xdiff)*(1-ydiff);
00632     wgt[1] = xdiff*(1-ydiff);
00633     wgt[2] = ydiff*(1-xdiff);
00634     pix[3] = p4;
00635     wgt[3] = xdiff*ydiff;
00636     }
00637   else
00638     {
00639     wgt[0] = 1-xdiff-ydiff+fourthird*xdiff*ydiff;
00640     wgt[1] = xdiff-twothird*xdiff*ydiff;
00641     wgt[2] = ydiff-twothird*xdiff*ydiff;
00642     pix[3] = 0;
00643     wgt[3] = 0;
00644     }
00645   }
00646 
00647 } // namespace
00648 
00649 void Healpix_Base::get_interpol (const pointing &ptg, fix_arr<int,4> &pix,
00650   fix_arr<double,4> &wgt) const
00651   {
00652   double z = cos(ptg.theta);
00653   double za = abs(z);
00654   double tt = modulo(ptg.phi,twopi) / halfpi; // in [0,4)
00655 
00656   int face_num;
00657   double ix, iy;
00658   if (za<=twothird) // Equatorial region
00659     {
00660     double temp1 = nside_*(0.5+tt);
00661     double temp2 = nside_*z*0.75;
00662     double jp = temp1-temp2; // index of  ascending edge line
00663     double jm = temp1+temp2; // index of descending edge line
00664     int ifp = int(jp/nside_);  // in {0,4}
00665     int ifm = int(jm/nside_);
00666     if (ifp == ifm)           // faces 4 to 7
00667       face_num = (ifp==4) ? 4 : (ifp+4);
00668     else if (ifp < ifm)       // (half-)faces 0 to 3
00669       face_num = ifp;
00670     else                      // (half-)faces 8 to 11
00671       face_num = ifm + 8;
00672 
00673     ix = modulo(jm, double(nside_));
00674     iy = nside_ - modulo(jp, double(nside_));
00675     }
00676   else // polar region, za > 2/3
00677     {
00678     int ntt = int(tt);
00679     double tp = tt-ntt;
00680     double tmp = nside_*sqrt(3*(1-za));
00681 
00682     double jp = tp*tmp; // increasing edge line index
00683     double jm = (1.0-tp)*tmp; // decreasing edge line index
00684     if (jp>=nside_) jp = nside_; // for points too close to the boundary
00685     if (jm>=nside_) jm = nside_;
00686     if (z >= 0)
00687       {
00688       face_num = ntt;  // in {0,3}
00689       ix = nside_ - jm;
00690       iy = nside_ - jp;
00691       }
00692     else
00693       {
00694       face_num = ntt + 8; // in {8,11}
00695       ix = jp;
00696       iy = jm;
00697       }
00698     }
00699 
00700   if ((ix>0.5) && (ix<(nside_-0.5)) && (iy>0.5) && (iy<(nside_-0.5)))
00701     {
00702     int xpix=int(ix-0.5), ypix=int(iy-0.5);
00703     double xdiff=ix-0.5-xpix, ydiff=iy-0.5-ypix;
00704     wgt[0] = (1-xdiff)*(1-ydiff);
00705     wgt[1] = xdiff*(1-ydiff);
00706     wgt[2] = (1-xdiff)*ydiff;
00707     wgt[3] = xdiff*ydiff;
00708     if (scheme_==RING)
00709       {
00710       pix[0] = xyf2ring(xpix  ,ypix  ,face_num);
00711       pix[1] = xyf2ring(xpix+1,ypix  ,face_num);
00712       pix[2] = xyf2ring(xpix  ,ypix+1,face_num);
00713       pix[3] = xyf2ring(xpix+1,ypix+1,face_num);
00714       }
00715     else
00716       {
00717       pix[0] = xyf2nest(xpix  ,ypix  ,face_num);
00718       pix[1] = xyf2nest(xpix+1,ypix  ,face_num);
00719       pix[2] = xyf2nest(xpix  ,ypix+1,face_num);
00720       pix[3] = xyf2nest(xpix+1,ypix+1,face_num);
00721       }
00722     }
00723   else
00724     {
00725     int xpix=int(ix-0.5), ypix=int(iy-0.5);
00726     xpix=max(0,min(nside_-1,xpix));
00727     ypix=max(0,min(nside_-1,ypix));
00728     int pixnr = (scheme_==RING) ?
00729       xyf2ring(xpix,ypix,face_num) : xyf2nest(xpix,ypix,face_num);
00730     fix_arr<int,8> nb;
00731     neighbors (pixnr,nb);
00732 
00733     double xdiff=ix-0.5-xpix, ydiff=iy-0.5-ypix;
00734     if (xdiff>0)
00735       {
00736       if (ydiff>0)
00737         add_weights(pixnr,nb[4],nb[2],nb[3], xdiff, ydiff,pix,wgt);
00738       else
00739         add_weights(pixnr,nb[4],nb[6],nb[5], xdiff,-ydiff,pix,wgt);
00740       }
00741     else
00742       {
00743       if (ydiff>0)
00744         add_weights(pixnr,nb[0],nb[2],nb[1],-xdiff, ydiff,pix,wgt);
00745       else
00746         add_weights(pixnr,nb[0],nb[6],nb[7],-xdiff,-ydiff,pix,wgt);
00747       }
00748     }
00749   }
00750 
00751 void Healpix_Base::get_ring_info2 (int ring, int &startpix, int &ringpix,
00752   double &theta, bool &shifted) const
00753   {
00754   int northring = (ring>2*nside_) ? 4*nside_-ring : ring;
00755   if (northring < nside_)
00756     {
00757     theta = acos(1 - northring*northring*fact2_);
00758     ringpix = 4*northring;
00759     shifted = true;
00760     startpix = 2*northring*(northring-1);
00761     }
00762   else
00763     {
00764     theta = acos((2*nside_-northring)*fact1_);
00765     ringpix = 4*nside_;
00766     shifted = ((northring-nside_) & 1) == 0;
00767     startpix = ncap_ + (northring-nside_)*ringpix;
00768     }
00769   if (northring != ring) // southern hemisphere
00770     {
00771     theta = pi-theta;
00772     startpix = npix_ - startpix - ringpix;
00773     }
00774   }
00775 
00776 void Healpix_Base::get_interpol2 (const pointing &ptg, fix_arr<int,4> &pix,
00777   fix_arr<double,4> &wgt) const
00778   {
00779   double z = cos (ptg.theta);
00780   int ir1 = ring_above(z);
00781   int ir2 = ir1+1;
00782   double theta1, theta2, w1, tmp, dphi;
00783   int sp,nr;
00784   bool shift;
00785   int i1,i2;
00786   if (ir1>0)
00787     {
00788     get_ring_info2 (ir1, sp, nr, theta1, shift);
00789     dphi = twopi/nr;
00790     tmp = (ptg.phi/dphi - .5*shift);
00791     i1 = (tmp<0) ? int(tmp)-1 : int(tmp);
00792     w1 = (ptg.phi-(i1+.5*shift)*dphi)/dphi;
00793     i2 = i1+1;
00794     if (i1<0) i1 +=nr;
00795     if (i2>=nr) i2 -=nr;
00796     pix[0] = sp+i1; pix[1] = sp+i2;
00797     wgt[0] = 1-w1; wgt[1] = w1;
00798     }
00799   if (ir2<(4*nside_))
00800     {
00801     get_ring_info2 (ir2, sp, nr, theta2, shift);
00802     dphi = twopi/nr;
00803     tmp = (ptg.phi/dphi - .5*shift);
00804     i1 = (tmp<0) ? int(tmp)-1 : int(tmp);
00805     w1 = (ptg.phi-(i1+.5*shift)*dphi)/dphi;
00806     i2 = i1+1;
00807     if (i1<0) i1 +=nr;
00808     if (i2>=nr) i2 -=nr;
00809     pix[2] = sp+i1; pix[3] = sp+i2;
00810     wgt[2] = 1-w1; wgt[3] = w1;
00811     }
00812 
00813   if (ir1==0)
00814     {
00815     double wtheta = ptg.theta/theta2;
00816     wgt[2] *= wtheta; wgt[3] *= wtheta;
00817     double fac = (1-wtheta)*0.25;
00818     wgt[0] = fac; wgt[1] = fac; wgt[2] += fac; wgt[3] +=fac;
00819     pix[0] = (pix[2]+2)%4;
00820     pix[1] = (pix[3]+2)%4;
00821     }
00822   else if (ir2==4*nside_)
00823     {
00824     double wtheta = (ptg.theta-theta1)/(pi-theta1);
00825     wgt[0] *= (1-wtheta); wgt[1] *= (1-wtheta);
00826     double fac = wtheta*0.25;
00827     wgt[0] += fac; wgt[1] += fac; wgt[2] = fac; wgt[3] =fac;
00828     pix[2] = ((pix[0]+2)&3)+npix_-4;
00829     pix[3] = ((pix[1]+2)&3)+npix_-4;
00830     }
00831   else
00832     {
00833     double wtheta = (ptg.theta-theta1)/(theta2-theta1);
00834     wgt[0] *= (1-wtheta); wgt[1] *= (1-wtheta);
00835     wgt[2] *= wtheta; wgt[3] *= wtheta;
00836     }
00837 
00838   if (scheme_==NEST)
00839     for (int m=0; m<pix.size(); ++m)
00840       pix[m] = ring2nest(pix[m]);
00841   }

Generated on Fri Jul 8 09:37:15 2005 for Healpix C++