#include "machdefs.h" #include #include #include "pexceptions.h" #include "fiondblock.h" #include "spherehealpix.h" #include "strutil.h" #include "HEALPixUtils.h" extern "C" { #include #include #include } using namespace SOPHYA; //******************************************************************* //++ // Class SphereHEALPix // // include SphereHealpix.h strutil.h // // Pixelisation Gorski // // //| ----------------------------------------------------------------------- //| version 0.8.2 Aug97 TAC Eric Hivon, Kris Gorski //| ----------------------------------------------------------------------- // // the sphere is split in 12 diamond-faces containing nside**2 pixels each // // the numbering of the pixels (in the nested scheme) is similar to // quad-cube // In each face the first pixel is in the lowest corner of the diamond // // the faces are (x,y) coordinate on each face //| . . . . <--- North Pole //| / \ / \ / \ / \ ^ ^ //| . 0 . 1 . 2 . 3 . <--- z = 2/3 \ / //| \ / \ / \ / \ / y \ / x //| 4 . 5 . 6 . 7 . 4 <--- equator \ / //| / \ / \ / \ / \ \/ //| . 8 . 9 .10 .11 . <--- z = -2/3 (0,0) : lowest corner //| \ / \ / \ / \ / //| . . . . <--- South Pole //| // phi:0 2Pi // // in the ring scheme pixels are numbered along the parallels // the first parallel is the one closest to the north pole and so on // on each parallel, pixels are numbered starting from the one closest // to phi = 0 // // nside MUST be a power of 2 (<= 8192) //-- //++ // // Links Parents // // SphericalMap //-- /* --Methode-- */ //++ // Titre Constructors //-- //++ template SphereHEALPix::SphereHEALPix() : pixels_(), sliceBeginIndex_(), sliceLenght_() //-- { InitNul(); // SetTemp(false); } //++ template SphereHEALPix::SphereHEALPix(int_4 m) // m is the "nside" of the Gorski algorithm // // The total number of pixels will be Npix = 12*nside**2 // // nside MUST be a power of 2 (<= 8192) //-- { if(m <= 0 || m > 8192) { cout << "SphereHEALPix : m hors bornes [0,8192], m= " << m << endl; throw RangeCheckError("SphereHEALPix::SphereHEALPix() - Out of bound nside (< 8192)!"); } // verifier que m est une puissance de deux int x= m; while(x%2 == 0) x/=2; if(x != 1) { cout<<"SphereHEALPix: m doit etre une puissance de deux, m= "<::SphereHEALPix() - nside != 2^n !"); } InitNul(); // SetTemp(false); Pixelize(m); SetThetaSlices(); } //++ template SphereHEALPix::SphereHEALPix(const SphereHEALPix& s, bool share) : pixels_(s.pixels_, share), sliceBeginIndex_(s.sliceBeginIndex_, share), sliceLenght_(s.sliceLenght_, share) // copy constructor //-- { nSide_= s.nSide_; nPix_ = s.nPix_; omeg_ = s.omeg_; if(s.mInfo_) mInfo_= new DVList(*s.mInfo_); } //++ template SphereHEALPix::SphereHEALPix(const SphereHEALPix& s) : pixels_(s.pixels_), sliceBeginIndex_(s.sliceBeginIndex_), sliceLenght_(s.sliceLenght_) // copy constructor //-- { nSide_= s.nSide_; nPix_ = s.nPix_; omeg_ = s.omeg_; if(s.mInfo_) mInfo_= new DVList(*s.mInfo_); // CloneOrShare(s); } template void SphereHEALPix::CloneOrShare(const SphereHEALPix& a) { nSide_= a.nSide_; nPix_ = a.nPix_; omeg_ = a.omeg_; pixels_.CloneOrShare(a.pixels_); sliceBeginIndex_.CloneOrShare(a.sliceBeginIndex_); sliceLenght_.CloneOrShare(a.sliceLenght_); // pas forcement a conserver, pas forcement a cet endroit (GLM) // if (a.IsTemp() ) SetTemp(true); } ////////////////////////// methodes de copie/share template SphereHEALPix& SphereHEALPix::Set(const SphereHEALPix& a) { if (this != &a) { if (a.NbPixels() < 1) throw RangeCheckError("SphereHEALPix::Set(a ) - Array a not allocated ! "); if (NbPixels() < 1) CloneOrShare(a); else CopyElt(a); if (mInfo_) delete mInfo_; mInfo_ = NULL; if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_)); } return(*this); } template SphereHEALPix& SphereHEALPix::CopyElt(const SphereHEALPix& a) { if (NbPixels() < 1) throw RangeCheckError("SphereHEALPix::CopyElt(const SphereHEALPix& ) - Not Allocated Array ! "); if (NbPixels() != a.NbPixels()) throw(SzMismatchError("SphereHEALPix::CopyElt(const SphereHEALPix&) SizeMismatch")) ; nSide_= a.nSide_; nPix_ = a.nPix_; omeg_ = a.omeg_; int k; for (k=0; k< nPix_; k++) pixels_(k) = a.pixels_(k); for (k=0; k< a.sliceBeginIndex_.Size(); k++) sliceBeginIndex_(k) = a.sliceBeginIndex_(k); for (k=0; k< a.sliceLenght_.Size(); k++) sliceLenght_(k) = a.sliceLenght_(k); return(*this); } //++ // Titre Destructor //-- //++ template SphereHEALPix::~SphereHEALPix() //-- { } //++ // Titre Public Methods //-- //++ template void SphereHEALPix::Resize(int_4 m) // m is the "nside" of the Gorski algorithm // // The total number of pixels will be Npix = 12*nside**2 // // nside MUST be a power of 2 (<= 8192) //-- { if (m<=0 || m> 8192) { cout << "SphereHEALPix : m hors bornes [0,8192], m= " << m << endl; exit(1); } // verifier que m est une puissance de deux int x= m; while (x%2==0) x/=2; if(x != 1) { cout<<"SphereHEALPix: m doit etre une puissance de deux, m= "< void SphereHEALPix::Pixelize( int_4 m) // prépare la pixelisation Gorski (m a la même signification // que pour le constructeur) // // { // On memorise les arguments d'appel nSide_= m; // Nombre total de pixels sur la sphere entiere nPix_= 12*nSide_*nSide_; // pour le moment les tableaux qui suivent seront ranges dans l'ordre // de l'indexation GORSKY "RING" // on pourra ulterieurement changer de strategie et tirer profit // de la dualite d'indexation GORSKY (RING et NEST) : tout dependra // de pourquoi c'est faire // Creation et initialisation du vecteur des contenus des pixels pixels_.ReSize(nPix_); pixels_.Reset(); // solid angle per pixel omeg_= 4.0*Pi/nPix_; } template void SphereHEALPix::InitNul() // // initialise à zéro les variables de classe { nSide_= 0; nPix_ = 0; omeg_ = 0.; // pixels_.Reset(); - Il ne faut pas mettre les pixels a zero si share ! } /* --Methode-- */ //++ template int_4 SphereHEALPix::NbPixels() const // Retourne le nombre de pixels du découpage //-- { return(nPix_); } //++ template uint_4 SphereHEALPix::NbThetaSlices() const // Return number of slices in theta direction on the sphere //-- { uint_4 nbslices = uint_4(4*nSide_-1); if (nSide_<=0) { nbslices = 0; throw PException(" sphere not pixelized, NbSlice=0 "); } return nbslices; } //++ template void SphereHEALPix::GetThetaSlice(int_4 index,r_8& theta,TVector& phi,TVector& value) const // For a theta-slice with index 'index', return : // // the corresponding "theta" // // a vector containing the phi's of the pixels of the slice // // a vector containing the corresponding values of pixels // //-- { if (index<0 || index >= NbThetaSlices()) { // THROW(out_of_range("SphereHEALPix::PIxVal Pixel index out of range")); cout << " SphereHEALPix::GetThetaSlice : Pixel index out of range" < void SphereHEALPix::GetThetaSlice(int_4 sliceIndex,r_8& theta, r_8& phi0, TVector& pixelIndices,TVector& value) const // For a theta-slice with index 'sliceIndex', return : // // the corresponding "theta" // the corresponding "phi" for first pixel of the slice // // a vector containing the indices of the pixels of the slice // (equally distributed in phi) // // a vector containing the corresponding values of pixels // //-- { if (sliceIndex<0 || sliceIndex >= NbThetaSlices()) { // THROW(out_of_range("SphereHEALPix::PIxVal Pixel index out of range")); cout << " SphereHEALPix::GetThetaSlice : Pixel index out of range" < void SphereHEALPix::SetThetaSlices() //-- { sliceBeginIndex_.ReSize(4*nSide_-1); sliceLenght_.ReSize(4*nSide_-1); int sliceIndex; for (sliceIndex=0; sliceIndex< nSide_-1; sliceIndex++) { sliceBeginIndex_(sliceIndex) = 2*sliceIndex*(sliceIndex+1); sliceLenght_(sliceIndex) = 4*(sliceIndex+1); } for (sliceIndex= nSide_-1; sliceIndex< 3*nSide_; sliceIndex++) { sliceBeginIndex_(sliceIndex) = 2*nSide_*(2*sliceIndex-nSide_+1); sliceLenght_(sliceIndex) = 4*nSide_; } for (sliceIndex= 3*nSide_; sliceIndex< 4*nSide_-1; sliceIndex++) { int_4 nc= 4*nSide_-1-sliceIndex; sliceBeginIndex_(sliceIndex) = nPix_-2*nc*(nc+1); sliceLenght_(sliceIndex) = 4*nc; } } /* --Methode-- */ //++ template T& SphereHEALPix::PixVal(int_4 k) // Return value of pixel with "RING" index k //-- { if((k < 0) || (k >= nPix_)) { throw RangeCheckError("SphereHEALPix::PIxVal Pixel index out of range"); } return pixels_(k); } /* --Methode-- */ //++ template T const& SphereHEALPix::PixVal(int_4 k) const // Return value of pixel with "RING" index k //-- { if((k < 0) || (k >= nPix_)) { throw RangeCheckError("SphereHEALPix::PIxVal Pixel index out of range"); } return *(pixels_.Data()+k); } //++ template T& SphereHEALPix::PixValNest(int_4 k) // Return value of pixel with "NESTED" index k //-- { if((k < 0) || (k >= nPix_)) { throw RangeCheckError("SphereHEALPix::PIxValNest Pixel index out of range"); } return pixels_(nest2ring(nSide_,k)); } //++ template T const& SphereHEALPix::PixValNest(int_4 k) const // Return value of pixel with "NESTED" index k //-- { if((k < 0) || (k >= nPix_)) { throw RangeCheckError("SphereHEALPix::PIxValNest Pixel index out of range"); } int_4 pix= nest2ring(nSide_,k); return *(pixels_.Data()+pix); } /* --Methode-- */ //++ template bool SphereHEALPix::ContainsSph(double /*theta*/, double /*phi*/) const //-- { return(true); } /* --Methode-- */ //++ template int_4 SphereHEALPix::PixIndexSph(double theta,double phi) const // Return "RING" index of the pixel corresponding to // direction (theta, phi). //-- { return ang2pix_ring(nSide_,theta,phi); } //++ template int_4 SphereHEALPix::PixIndexSphNest(double theta,double phi) const // Return "NESTED" index of the pixel corresponding to // direction (theta, phi). //-- { return ang2pix_nest(nSide_,theta,phi); } /* --Methode-- */ //++ template void SphereHEALPix::PixThetaPhi(int_4 k,double& theta,double& phi) const // Return (theta,phi) coordinates of middle of pixel with "RING" index k //-- { pix2ang_ring(nSide_,k,theta,phi); } template T SphereHEALPix::SetPixels(T v) { pixels_.Reset(v); return(v); } //++ template double SphereHEALPix::PixSolAngle(int_4 /*dummy*/) const // Pixel Solid angle (steradians) // All the pixels have the same solid angle. The dummy argument is // for compatibility with eventual pixelizations which would not // fulfil this requirement. //-- { return omeg_; } //++ template void SphereHEALPix::PixThetaPhiNest(int_4 k,double& theta,double& phi) const // Return (theta,phi) coordinates of middle of pixel with "NESTED" index k //-- { pix2ang_nest(nSide_,k,theta,phi); } //++ template int_4 SphereHEALPix::NestToRing(int_4 k) const // translation from NESTED index into RING index // //-- { return nest2ring(nSide_,k); } //++ template int_4 SphereHEALPix::RingToNest(int_4 k) const // // translation from RING index into NESTED index // //-- { return ring2nest(nSide_,k); } template void SphereHEALPix::print(ostream& os) const { if(mInfo_) os << " DVList Info= " << *mInfo_ << endl; // os << " nSide_ = " << nSide_ << endl; os << " nPix_ = " << nPix_ << endl; os << " omeg_ = " << omeg_ << endl; os << " content of pixels : "; for(int i=0; i < nPix_; i++) { if(i%5 == 0) os << endl; os << pixels_(i) <<", "; } os << endl; os << endl; //const PIXELS_XY& PXY= PIXELS_XY::instance(); //os << endl; os << " contenu des tableaux conversions "< #pragma define_template SphereHEALPix #pragma define_template SphereHEALPix #pragma define_template SphereHEALPix< complex > #pragma define_template SphereHEALPix< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class SphereHEALPix; template class SphereHEALPix; template class SphereHEALPix; template class SphereHEALPix< complex >; template class SphereHEALPix< complex >; #endif