#include "spherethetaphi.h" #include "nbmath.h" #include #include "piocmplx.h" #include //*************************************************************** //++ // Class SphereThetaPhi // // // include spherethetaphi.h nbmath.h // // sphere splitted with respect to theta, phi : each hemisphere is // splitted into (m-1) parallels (equator does not enter into account). // This operation defines m slices, each of which is splitted into // equidistant meridians. This splitting is realized in such a way that // all pixels have the same area and are as square as possible. // One begins with the hemisphere with positive z, starting from the pole // toward the equator. The first pixel is the polar cap ; it is circular // and centered on theta=0. //-- //++ // // Links Parents // // SphericalMap //-- /* --Methode-- */ //++ // Titre Constructors //-- //++ template SphereThetaPhi::SphereThetaPhi() //-- { InitNul(); pixels_.Reset(); } /* --Methode-- */ //++ template SphereThetaPhi::SphereThetaPhi(int_4 m) // m is the number of slices in theta on an hemisphere (the polar cap // forms the first slice). // pet is a dummy parameter at the moment. //-- { InitNul(); Pixelize(m); } template SphereThetaPhi::SphereThetaPhi(const SphereThetaPhi& s, bool share) : pixels_(s.pixels_ , share) { if(s.mInfo_) mInfo_= new DVList(*s.mInfo_); NTheta_= s.NTheta_; NPix_ = s.NPix_; NPhi_ = new int_4[NTheta_]; Theta_ = new double[NTheta_+1]; TNphi_ = new int_4[NTheta_+1]; for(int k = 0; k < NTheta_; k++) { NPhi_[k] = s.NPhi_[k]; Theta_[k]= s.Theta_[k]; TNphi_[k]= s.TNphi_[k]; } Theta_[NTheta_]= s.Theta_[NTheta_]; TNphi_[NTheta_]= s.TNphi_[NTheta_]; Omega_ = s.Omega_; } //++ // Titre Destructor //-- //++ template SphereThetaPhi::~SphereThetaPhi() //-- { Clear(); } //++ // Titre Public Méthods //-- template void SphereThetaPhi::InitNul() // // initialise à zéro les variables de classe pointeurs { NTheta_= 0; NPix_ = 0; Theta_ = NULL; NPhi_ = NULL; TNphi_ = NULL; // pixels_.Reset(); Pas de reset par InitNul (en cas de share) - Reza 20/11/99 $CHECK$ } /* --Methode-- */ template void SphereThetaPhi::Clear() { if(Theta_) delete[] Theta_; if(NPhi_ ) delete[] NPhi_; if(TNphi_) delete[] TNphi_; InitNul(); } //++ template void SphereThetaPhi::Resize(int_4 m) // re-pixelize the sphere //-- { Clear(); Pixelize(m); } /* --Methode-- */ //++ template int_4 SphereThetaPhi::NbPixels() const // Return total number of pixels //-- { return(NPix_); } /* --Methode-- */ //++ template T& SphereThetaPhi::PixVal(int_4 k) // Return value of pixel with index k //-- { if((k < 0) || (k >= NPix_)) { //THROW(out_of_range("SphereThetaPhi::PIxVal Pixel index out of range")); cout << " SphereThetaPhi::PIxVal : exceptions a mettre en place" < T const& SphereThetaPhi::PixVal(int_4 k) const // Return value of pixel with index k //-- { if((k < 0) || (k >= NPix_)) { cout << " SphereThetaPhi::PIxVal : exceptions a mettre en place" < bool SphereThetaPhi::ContainsSph(double /*theta*/, double /*phi*/) const //-- { return(true); } /* --Methode-- */ //++ template int_4 SphereThetaPhi::PixIndexSph(double theta, double phi) const // Return index of the pixel corresponding to // direction (theta, phi). //-- { double dphi; int i,k; bool fgzn = false; if((theta > Pi) || (theta < 0.)) return(-1); if((phi < 0.) || (phi > DeuxPi)) return(-1); if(theta > Pi*0.5) {fgzn = true; theta = Pi-theta;} // La bande d'indice kt est limitée par les valeurs de theta contenues dans // Theta_[kt] et Theta_[kt+1] for( i=1; i< NTheta_; i++ ) if( theta < Theta_[i] ) break; dphi= DeuxPi/(double)NPhi_[i-1]; if (fgzn) k= NPix_-TNphi_[i]+(int_4)(phi/dphi); else k= TNphi_[i-1]+(int_4)(phi/dphi); return(k); } /* --Methode-- */ //++ template void SphereThetaPhi::PixThetaPhi(int_4 k,double& theta,double& phi) const // Return (theta,phi) coordinates of middle of pixel with index k //-- { int i; bool fgzn = false; if((k < 0) || (k >= NPix_)) {theta = -99999.; phi = -99999.; return; } if( k >= NPix_/2) {fgzn = true; k = NPix_-1-k;} // recupère l'indice i de la tranche qui contient le pixel k for( i=0; i< NTheta_; i++ ) if( k < TNphi_[i+1] ) break; // angle theta theta= 0.5*(Theta_[i]+Theta_[i+1]); if (fgzn) theta= Pi-theta; // angle phi k -= TNphi_[i]; phi= DeuxPi/(double)NPhi_[i]*(double)(k+.5); if (fgzn) phi= DeuxPi-phi; } template T SphereThetaPhi::SetPixels(T v) { pixels_.Reset(v); return(v); } //++ template double SphereThetaPhi::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 Omega_; } /* --Methode-- */ //++ template void SphereThetaPhi::Limits(int_4 k,double& tetMin,double& tetMax,double& phiMin,double& phiMax) // Return values of theta,phi which limit the pixel with index k //-- { int j; double dphi; bool fgzn= false; if((k < 0) || (k >= NPix_)) { tetMin= -99999.; phiMin= -99999.; tetMax= -99999.; phiMax= -99999.; return; } // si on se trouve dans l'hémisphère Sud if(k >= NPix_/2) { fgzn= true; k= NPix_-1-k; } // on recupere l'indice i de la tranche qui contient le pixel k int i; for( i=0; i< NTheta_; i++ ) if(k < TNphi_[i+1]) break; // valeurs limites de theta dans l'hemisphere Nord tetMin= Theta_[i]; tetMax= Theta_[i+1]; // valeurs limites de theta dans l'hemisphere Sud if (fgzn) { tetMin= Pi-Theta_[i+1]; tetMax= Pi-Theta_[i]; } // pixel correspondant dans l'hemisphere Nord if (fgzn) k= TNphi_[i+1]-k+TNphi_[i]-1; // indice j de discretisation ( phi= j*dphi ) j= k-TNphi_[i]; dphi= DeuxPi/(double)NPhi_[i]; // valeurs limites de phi phiMin= dphi*(double)(j); phiMax= dphi*(double)(j+1); return; } /* --Methode-- */ //++ template int_4 SphereThetaPhi::NbThetaSlices() const // Return number of theta-slices on the sphere //-- { int nbslices; nbslices= 2*NTheta_; return(nbslices); } /* --Methode-- */ //++ template int_4 SphereThetaPhi::NPhi(int_4 kt) const // Return number of pixels in phi-direction of the kt-th slice //-- { int nbpix; // verification if((kt < 0) || (kt >= 2*NTheta_)) return(-1); // si on se trouve dans l'hemisphere Sud if(kt >= NTheta_) { kt= 2*NTheta_-1-kt; } // nombre de pixels nbpix= NPhi_[kt]; return(nbpix); } /* --Methode-- */ //++ template void SphereThetaPhi::Theta(int_4 kt,double& tetMin,double& tetMax) // Return theta values which limit the slice kt //-- { bool fgzn= false; // verification if( (kt< 0) || (kt>= 2*NTheta_) ) { tetMin= -99999.; tetMax= -99999.; return; } // si on se trouve dans l'hemisphere Sud if( kt >= NTheta_ ) { fgzn= true; kt= 2*NTheta_-1-kt; } // valeurs limites de theta dans l'hemisphere Nord tetMin= Theta_[kt]; tetMax= Theta_[kt+1]; // valeurs limites de theta dans l'hemisphere Sud if (fgzn) { tetMin= Pi-Theta_[kt+1]; tetMax= Pi-Theta_[kt]; } } /* --Methode-- */ //++ template void SphereThetaPhi::Phi(int_4 kt,int_4 jp,double& phiMin,double& phiMax) // Return values of phi which limit the jp-th pixel of the kt-th slice //-- { // verification if((kt < 0) || (kt >= 2*NTheta_)) { phiMin= -99999.; phiMax= -99999.; return; } // si on se trouve dans l'hemisphere Sud if(kt >= NTheta_) kt= 2*NTheta_-1-kt; // verifie si la tranche kt contient au moins jp pixels if( (jp< 0) || (jp >= NPhi_[kt]) ) { phiMin= -88888.; phiMax= -88888.; return; } double dphi= DeuxPi/(double)NPhi_[kt]; phiMin= dphi*(double)(jp); phiMax= dphi*(double)(jp+1); return; } /* --Methode-- */ //++ template int_4 SphereThetaPhi::Index(int_4 kt,int_4 jp) const // Return pixel index with sequence index jp in the slice kt //-- { int k; bool fgzn= false; // si on se trouve dans l'hemisphere Sud if(kt >= NTheta_) { fgzn= true; kt= 2*NTheta_-1-kt; } // si la tranche kt contient au moins i pixels if( (jp>=0) && (jp void SphereThetaPhi::ThetaPhiIndex(int_4 k,int_4& kt,int_4& jp) // Return indices kt (theta) and jp (phi) of pixel with index k //-- { bool fgzn= false; // si on se trouve dans l'hemisphere Sud if(k >= NPix_/2) { fgzn= true; k= NPix_-1-k; } // on recupere l'indice kt de la tranche qui contient le pixel k int i; for(i = 0; i < NTheta_; i++) if(k < TNphi_[i+1]) break; // indice kt de tranche if (fgzn) kt= 2*NTheta_-1-i; else kt= i; // indice jp de pixel if (fgzn) jp= TNphi_[i+1]-k-1; else jp= k-TNphi_[i]; } //++ template void SphereThetaPhi::Pixelize(int_4 m) // achieve the splitting into pixels (m has the same signification // as for the constructor) // // Each theta-slice of the north hemisphere will be spitted starting f // from phi=0 ... // // South hemisphere is scanned in the same direction according to phi // and from equator to the pole (the pixel following the last one of // the slice closest to the equator with z>0, is the pixel with lowest // phi of the slice closest of the equator with z<0). //-- { int ntotpix,j; // Decodage et controle des arguments d'appel : // au moins 2 et au plus 16384 bandes d'un hemisphere en theta if (m < 2) m = 2; if (m > 16384) m = 16384; // On memorise les arguments d'appel NTheta_ = m; // On commence par decouper l'hemisphere z>0. // Creation des vecteurs contenant : // Les valeurs limites de theta (une valeur de plus que le nombre de bandes...) Theta_= new double[m+1]; // Le nombre de pixels en phi de chacune des bandes en theta NPhi_ = new int_4[m]; // Le nombre/Deuxpi total des pixels contenus dans les bandes de z superieur a une // bande donnee (mTPphi[m] contient le nombre de pixels total de l'hemisphere) TNphi_= new int_4[m+1]; // Calcul du nombre total de pixels dans chaque bande pour optimiser // le rapport largeur/hauteur des pixels //calotte polaire TNphi_[0]= 0; NPhi_[0] = 1; //bandes jusqu'a l'equateur for(j = 1; j < m; j++) { TNphi_[j]= TNphi_[j-1]+NPhi_[j-1]; NPhi_[j] = (int_4)(.5+4.*(double)(m-.5)*sin(Pi*(double)j/(double)(2.*m-1.))) ; } // Nombre total de pixels sur l'hemisphere ntotpix = TNphi_[m-1]+NPhi_[m-1]; TNphi_[m]= ntotpix; // et sur la sphere entiere NPix_= 2*ntotpix; // Creation et initialisation du vecteur des contenus des pixels pixels_.ReSize(NPix_); pixels_.Reset(); // Determination des limites des bandes en theta : // omeg est l'angle solide couvert par chaque pixel, // une bande donnee kt couvre un angle solide NPhi_[kt]*omeg // egal a 2* Pi*(cos Theta_[kt]-cos Theta_[kt+1]). De meme, l'angle solide //de la // calotte allant du pole a la limite haute de la bande kt vaut // 2* Pi*(1.-cos Theta_[kt+1])= TNphi_[kt]*omeg... double omeg2pi= 1./(double)ntotpix; Omega_ = omeg2pi*DeuxPi; for(j=0; j <= m; j++) { Theta_[j]= acos(1.-(double)TNphi_[j]*omeg2pi); } } //++ template void SphereThetaPhi::GetThetaSlice(int_4 index,double& 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 //-- { cout << "entree GetThetaSlice, couche no " << index << endl; if(index < 0 || index > NbThetaSlices()) { // THROW(out_of_range("SphereThetaPhi::PIxVal Pixel index out of range")); cout << " SphereThetaPhi::GetThetaSlice : exceptions a mettre en place" <NPhi(index); int lring = bid; cout << " iring= " << iring << " lring= " << lring << endl; phi.ReSize(lring); value.ReSize(lring); double Te= 0.; double Fi= 0.; for(int kk = 0; kk < lring; kk++) { PixThetaPhi(kk+iring,Te,Fi); phi(kk)= Fi; value(kk)= PixVal(kk+iring); } theta= Te; } template void SphereThetaPhi::setmNPhi(int_4* array, int_4 m) //remplit le tableau contenant le nombre de pixels en phi de chacune des bandes en theta // { NPhi_= new int_4[m]; for(int k = 0; k < m; k++) NPhi_[k]= array[k]; } template void SphereThetaPhi::setmTNphi(int_4* array, int_4 m) //remplit le tableau contenant le nombre/Deuxpi total des pixels contenus dans les bandes // { TNphi_= new int_4[m]; for(int k = 0; k < m; k++) TNphi_[k]= array[k]; } template void SphereThetaPhi::setmTheta(double* array, int_4 m) //remplit le tableau contenant les valeurs limites de theta // { Theta_= new double[m]; for(int k = 0; k < m; k++) Theta_[k]= array[k]; } template void SphereThetaPhi::setDataBlock(T* data, int_4 m) // remplit le vecteur des contenus des pixels { pixels_.FillFrom(m,data); } template void SphereThetaPhi::print(ostream& os) const { if(mInfo_) os << " DVList Info= " << *mInfo_ << endl; // os << " NTheta_= " << NTheta_ << endl; os << " NPix_ = " << NPix_ << endl; os << " Omega_ = " << Omega_ << endl; os << " contenu de NPhi_ : "; int i; for(i=0; i < NTheta_; i++) { if(i%5 == 0) os << endl; os << NPhi_[i] <<", "; } os << endl; os << " contenu de Theta_ : "; for(i=0; i < NTheta_+1; i++) { if(i%5 == 0) os << endl; os << Theta_[i] <<", "; } os << endl; os << " contenu de TNphi_ : "; for(i=0; i < NTheta_+1; i++) { if(i%5 == 0) os << endl; os << TNphi_[i] <<", "; } os << endl; os << " contenu de pixels : "; for(i=0; i < NPix_; i++) { if(i%5 == 0) os << endl; os << pixels_(i) <<", "; } os << endl; } /////////////////////////////////////////////////////////// // -------------------------------------------------------- // Les objets delegues pour la gestion de persistance // -------------------------------------------------------- ////////////////////////////////////////////////////////// template FIO_SphereThetaPhi::FIO_SphereThetaPhi() { dobj= new SphereThetaPhi; ownobj= true; } template FIO_SphereThetaPhi::FIO_SphereThetaPhi(string const& filename) { dobj= new SphereThetaPhi; dobj->DataBlock().SetTemp(true); ownobj= true; Read(filename); } template FIO_SphereThetaPhi::FIO_SphereThetaPhi(const SphereThetaPhi& obj) { dobj= new SphereThetaPhi(obj, true); dobj->DataBlock().SetTemp(true); ownobj= true; } template FIO_SphereThetaPhi::FIO_SphereThetaPhi(SphereThetaPhi* obj) { dobj= obj; ownobj= false; } template FIO_SphereThetaPhi::~FIO_SphereThetaPhi() { if (ownobj && dobj) delete dobj; } template AnyDataObj* FIO_SphereThetaPhi::DataObj() { return(dobj); } template void FIO_SphereThetaPhi::ReadSelf(PInPersist& is) { if(dobj == NULL) { dobj= new SphereThetaPhi; dobj->DataBlock().SetTemp(true); ownobj= true; } // Let's Read the SphereCoordSys object -- ATTENTIOn - $CHECK$ SphereCoordSys* cs = dynamic_cast(is.ReadObject()); dobj->SetCoordSys(cs); // Pour savoir s'il y avait un DVList Info associe char strg[256]; is.GetLine(strg, 255); bool hadinfo= false; if(strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0) hadinfo= true; if(hadinfo) { // Lecture eventuelle du DVList Info is >> dobj->Info(); } int_4 mNTheta; is.GetI4(mNTheta); dobj->setSizeIndex(mNTheta); int_4 mNPix; is.GetI4(mNPix); dobj->setNbPixels(mNPix); double mOmeg; is.GetR8(mOmeg); dobj->setPixSolAngle(mOmeg); int_4* mNphi= new int_4[mNTheta]; is.GetI4s(mNphi, mNTheta); dobj->setmNPhi(mNphi, mNTheta); delete [] mNphi; int_4* mTNphi= new int_4[mNTheta+1]; is.GetI4s(mTNphi, mNTheta+1); dobj->setmTNphi(mTNphi, mNTheta+1); delete [] mTNphi; double* mTheta= new double[mNTheta+1]; is.GetR8s(mTheta, mNTheta+1); dobj->setmTheta(mTheta, mNTheta+1); delete [] mTheta; // On lit le DataBlock; is >> dobj->DataBlock(); } template void FIO_SphereThetaPhi::WriteSelf(POutPersist& os) const { if(dobj == NULL) { cout << " WriteSelf:: dobj= null " << endl; return; } // Let's write the SphereCoordSys object dobj->GetCoordSys()->Write(os); char strg[256]; int_4 mNTheta= dobj->SizeIndex(); int_4 mNPix = dobj->NbPixels(); if(dobj->ptrInfo()) { sprintf(strg,"SphereThetaPhi: NSlices=%6d NPix=%9d HasInfo",mNTheta,mNPix); os.PutLine(strg); os << dobj->Info(); } else { sprintf(strg,"SphereThetaPhi: NSlices=%6d NPix=%9d ",mNTheta,mNPix); os.PutLine(strg); } os.PutI4(mNTheta); os.PutI4(mNPix); os.PutR8(dobj->PixSolAngle(0)); os.PutI4s(dobj->getmNPhi() , mNTheta); os.PutI4s(dobj->getmTNphi(), mNTheta+1); os.PutR8s(dobj->getmTheta(), mNTheta+1); // On ecrit le datablock os << dobj->DataBlock(); } #ifdef __CXX_PRAGMA_TEMPLATES__ #pragma define_template SphereThetaPhi #pragma define_template SphereThetaPhi #pragma define_template SphereThetaPhi< complex > #pragma define_template SphereThetaPhi< complex > #pragma define_template FIO_SphereThetaPhi #pragma define_template FIO_SphereThetaPhi #pragma define_template FIO_SphereThetaPhi< complex > #pragma define_template FIO_SphereThetaPhi< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class SphereThetaPhi; template class SphereThetaPhi; template class SphereThetaPhi< complex >; template class SphereThetaPhi< complex >; template class FIO_SphereThetaPhi; template class FIO_SphereThetaPhi; template class FIO_SphereThetaPhi< complex >; template class FIO_SphereThetaPhi< complex >; #endif