source: Sophya/trunk/SophyaLib/SkyMap/spherethetaphi.cc@ 980

Last change on this file since 980 was 980, checked in by ansari, 25 years ago

modifs constructeurs copie et operateur =

File size: 16.4 KB
RevLine 
[764]1#include "spherethetaphi.h"
2#include "smathconst.h"
3#include <complex>
4#include "piocmplx.h"
[809]5#include "fiondblock.h"
[764]6#include <iostream.h>
7
8
9//***************************************************************
10//++
11// Class SphereThetaPhi
12//
13//
14// include spherethetaphi.h
15//
16// sphere splitted with respect to theta, phi : each hemisphere is
17// splitted into (m-1) parallels (equator does not enter into account).
18// This operation defines m slices, each of which is splitted into
19// equidistant meridians. This splitting is realized in such a way that
20// all pixels have the same area and are as square as possible.
21
22// One begins with the hemisphere with positive z, starting from the pole
23// toward the equator. The first pixel is the polar cap ; it is circular
24// and centered on theta=0.
25//--
26//++
27//
28// Links Parents
29//
30// SphericalMap
31//--
32
33/* --Methode-- */
34//++
35// Titre Constructors
36//--
37//++
38
39template <class T>
40SphereThetaPhi<T>::SphereThetaPhi()
[980]41 : NPhi_(), TNphi_(), Theta_(), pixels_()
[764]42
43//--
44{
45 InitNul();
46}
47
48
49/* --Methode-- */
50
51//++
52template <class T>
53SphereThetaPhi<T>::SphereThetaPhi(int_4 m)
54
55// m is the number of slices in theta on an hemisphere (the polar cap
56// forms the first slice).
57// pet is a dummy parameter at the moment.
58//--
59{
60 InitNul();
61 Pixelize(m);
62}
63
64template <class T>
65SphereThetaPhi<T>::SphereThetaPhi(const SphereThetaPhi<T>& s, bool share)
[908]66 : NPhi_(s.NPhi_, share), TNphi_(s.TNphi_, share), Theta_(s.Theta_, share),
67 pixels_(s.pixels_ , share)
[764]68{
[908]69
[764]70 NTheta_= s.NTheta_;
71 NPix_ = s.NPix_;
[908]72 Omega_ = s.Omega_;
[980]73 if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
[908]74}
[764]75
[908]76template <class T>
77SphereThetaPhi<T>::SphereThetaPhi(const SphereThetaPhi<T>& s)
78 : NPhi_(s.NPhi_), TNphi_(s.TNphi_), Theta_(s.Theta_), pixels_(s.pixels_)
79{
80
81 NTheta_= s.NTheta_;
82 NPix_ = s.NPix_;
[764]83 Omega_ = s.Omega_;
[980]84 if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
[764]85}
86
87//++
88// Titre Destructor
89//--
90//++
91template <class T>
92SphereThetaPhi<T>::~SphereThetaPhi()
93
94//--
95{}
96
97//++
98// Titre Public Méthods
99//--
100template <class T>
101void SphereThetaPhi<T>::InitNul()
102//
103{
104 NTheta_= 0;
105 NPix_ = 0;
106// pixels_.Reset(); Pas de reset par InitNul (en cas de share) - Reza 20/11/99 $CHECK$
107}
108
109
110//++
111template <class T>
112void SphereThetaPhi<T>::Resize(int_4 m)
113// re-pixelize the sphere
114//--
115{
116 InitNul();
117 Pixelize(m);
118}
119
[908]120template<class T>
121void SphereThetaPhi<T>::CloneOrShare(const SphereThetaPhi<T>& a)
122{
123
[980]124 NTheta_= a.NTheta_;
125 NPix_ = a.NPix_;
126 Omega_ = a.Omega_;
127 NPhi_.CloneOrShare(a.NPhi_);
128 TNphi_.CloneOrShare(a.TNphi_);
129 Theta_.CloneOrShare(a.Theta_);
130 pixels_.CloneOrShare(a.pixels_);
[908]131}
132
[980]133////////////////////////// methodes de copie/share
[908]134template<class T>
135SphereThetaPhi<T>& SphereThetaPhi<T>::Set(const SphereThetaPhi<T>& a)
[980]136{
[908]137 if (this != &a)
138 {
[980]139
140
141 if (a.NbPixels() < 1)
142 throw RangeCheckError("SphereThetaPhi<T>::Set(a ) - Array a not allocated ! ");
143 if (NbPixels() < 1) CloneOrShare(a);
144 else CopyElt(a);
[908]145 if (mInfo_) delete mInfo_;
146 mInfo_ = NULL;
147 if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_));
148 }
149 return(*this);
[980]150}
[908]151
[980]152template<class T>
153SphereThetaPhi<T>& SphereThetaPhi<T>::CopyElt(const SphereThetaPhi<T>& a)
154{
155 if (NbPixels() < 1)
156 throw RangeCheckError("SphereThetaPhi<T>::CopyElt(const SphereThetaPhi<T>& ) - Not Allocated Array ! ");
157 if (NbPixels() != a.NbPixels())
158 throw(SzMismatchError("SphereThetaPhi<T>::CopyElt(const SphereThetaPhi<T>&) SizeMismatch")) ;
[908]159
[980]160 NTheta_= a.NTheta_;
161 NPix_ = a.NPix_;
162 Omega_ = a.Omega_;
163 int k;
164 for (k=0; k< NPix_; k++) pixels_(k) = a.pixels_(k);
165 for (k=0; k< a.NPhi_.Size(); k++) NPhi_(k) = a.NPhi_(k);
166 for (k=0; k< a.TNphi_.Size(); k++) TNphi_(k) = a.TNphi_(k);
167 for (k=0; k< a.Theta_.Size(); k++) Theta_(k) = a.Theta_(k);
168 return(*this);
[908]169
[980]170}
171
[764]172/* --Methode-- */
173//++
174template <class T>
175int_4 SphereThetaPhi<T>::NbPixels() const
176
177// Return total number of pixels
178//--
179{
180 return(NPix_);
181}
182
183/* --Methode-- */
184//++
185template <class T>
186T& SphereThetaPhi<T>::PixVal(int_4 k)
187
188// Return value of pixel with index k
189//--
190{
191 if((k < 0) || (k >= NPix_))
192 {
193 throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range");
194 }
195 return pixels_(k);
196}
197
198//++
199template <class T>
200T const& SphereThetaPhi<T>::PixVal(int_4 k) const
201
202// Return value of pixel with index k
203//--
204{
205 if((k < 0) || (k >= NPix_))
206 {
207 throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range");
208 }
209 return *(pixels_.Data()+k);
210}
211
212/* --Methode-- */
213//++
214template <class T>
215bool SphereThetaPhi<T>::ContainsSph(double /*theta*/, double /*phi*/) const
216//--
217{
218 return(true);
219}
220
221/* --Methode-- */
222//++
223template <class T>
224int_4 SphereThetaPhi<T>::PixIndexSph(double theta, double phi) const
225
226// Return index of the pixel corresponding to
227// direction (theta, phi).
228//--
229{
230 double dphi;
231 int i,k;
232 bool fgzn = false;
233
234 if((theta > Pi) || (theta < 0.)) return(-1);
235 if((phi < 0.) || (phi > DeuxPi)) return(-1);
236 if(theta > Pi*0.5) {fgzn = true; theta = Pi-theta;}
237
238 // La bande d'indice kt est limitée par les valeurs de theta contenues dans
239 // Theta_[kt] et Theta_[kt+1]
240 for( i=1; i< NTheta_; i++ )
241 if( theta < Theta_(i) ) break;
242
243 dphi= DeuxPi/(double)NPhi_(i-1);
244
245 if (fgzn) k= NPix_-TNphi_(i)+(int_4)(phi/dphi);
246 else k= TNphi_(i-1)+(int_4)(phi/dphi);
247 return(k);
248}
249
250/* --Methode-- */
251//++
252template <class T>
253void SphereThetaPhi<T>::PixThetaPhi(int_4 k,double& theta,double& phi) const
254
255// Return (theta,phi) coordinates of middle of pixel with index k
256//--
257{
258 int i;
259 bool fgzn = false;
260
261 if((k < 0) || (k >= NPix_)) {theta = -99999.; phi = -99999.; return; }
262 if( k >= NPix_/2) {fgzn = true; k = NPix_-1-k;}
263
264 // recupère l'indice i de la tranche qui contient le pixel k
265 for( i=0; i< NTheta_; i++ )
266 if( k < TNphi_(i+1) ) break;
267
268 // angle theta
269 theta= 0.5*(Theta_(i)+Theta_(i+1));
270 if (fgzn) theta= Pi-theta;
271
272 // angle phi
273 k -= TNphi_(i);
274 phi= DeuxPi/(double)NPhi_(i)*(double)(k+.5);
275 if (fgzn) phi= DeuxPi-phi;
276}
277
278template <class T>
279T SphereThetaPhi<T>::SetPixels(T v)
280{
281pixels_.Reset(v);
282return(v);
283}
284
285//++
286template <class T>
287double SphereThetaPhi<T>::PixSolAngle(int_4 /*dummy*/) const
288
289// Pixel Solid angle (steradians)
290// All the pixels have the same solid angle. The dummy argument is
291// for compatibility with eventual pixelizations which would not
292// fulfil this requirement.
293//--
294{
295 return Omega_;
296}
297
298/* --Methode-- */
299//++
300template <class T>
301void SphereThetaPhi<T>::Limits(int_4 k,double& tetMin,double& tetMax,double& phiMin,double& phiMax)
302
303// Return values of theta,phi which limit the pixel with index k
304//--
305 {
306 int j;
307 double dphi;
308 bool fgzn= false;
309
310 if((k < 0) || (k >= NPix_)) {
311 tetMin= -99999.;
312 phiMin= -99999.;
313 tetMax= -99999.;
314 phiMax= -99999.;
315 return;
316 }
317
318 // si on se trouve dans l'hémisphère Sud
319 if(k >= NPix_/2) {
320 fgzn= true;
321 k= NPix_-1-k;
322 }
323
324 // on recupere l'indice i de la tranche qui contient le pixel k
325 int i;
326 for( i=0; i< NTheta_; i++ )
327 if(k < TNphi_(i+1)) break;
328
329 // valeurs limites de theta dans l'hemisphere Nord
330 tetMin= Theta_(i);
331 tetMax= Theta_(i+1);
332 // valeurs limites de theta dans l'hemisphere Sud
333 if (fgzn) {
334 tetMin= Pi - Theta_(i+1);
335 tetMax= Pi - Theta_(i);
336 }
337
338 // pixel correspondant dans l'hemisphere Nord
339 if (fgzn) k= TNphi_(i+1)-k+TNphi_(i)-1;
340
341 // indice j de discretisation ( phi= j*dphi )
342 j= k-TNphi_(i);
343 dphi= DeuxPi/(double)NPhi_(i);
344
345 // valeurs limites de phi
346 phiMin= dphi*(double)(j);
347 phiMax= dphi*(double)(j+1);
348 return;
349}
350
351/* --Methode-- */
352//++
353template <class T>
354uint_4 SphereThetaPhi<T>::NbThetaSlices() const
355
356// Return number of theta-slices on the sphere
357//--
358{
359 if (NTheta_<=0)
360 {
361 throw PException(" sphere not pixelized, NbSlice=0 ");
362 }
363 return( 2*NTheta_);
364}
365
366/* --Methode-- */
367//++
368template <class T>
369int_4 SphereThetaPhi<T>::NPhi(int_4 kt) const
370
371// Return number of pixels in phi-direction of the kt-th slice
372//--
373{
374 int nbpix;
375 // verification
376 if((kt < 0) || (kt >= 2*NTheta_)) return(-1);
377
378 // si on se trouve dans l'hemisphere Sud
379 if(kt >= NTheta_) {
380 kt= 2*NTheta_-1-kt;
381 }
382
383 // nombre de pixels
384 nbpix= NPhi_(kt);
385 return(nbpix);
386}
387
388
389/* --Methode-- */
390//++
391template <class T>
392void SphereThetaPhi<T>::Theta(int_4 kt,double& tetMin,double& tetMax)
393
394// Return theta values which limit the slice kt
395//--
396{
397 bool fgzn= false;
398 // verification
399 if( (kt< 0) || (kt>= 2*NTheta_) ) {
400 tetMin= -99999.;
401 tetMax= -99999.;
402 return;
403 }
404
405 // si on se trouve dans l'hemisphere Sud
406 if( kt >= NTheta_ ) {
407 fgzn= true;
408 kt= 2*NTheta_-1-kt;
409 }
410
411 // valeurs limites de theta dans l'hemisphere Nord
412 tetMin= Theta_(kt);
413 tetMax= Theta_(kt+1);
414 // valeurs limites de theta dans l'hemisphere Sud
415 if (fgzn) {
416 tetMin= Pi - Theta_(kt+1);
417 tetMax= Pi - Theta_(kt);
418 }
419}
420
421/* --Methode-- */
422//++
423template <class T>
424void SphereThetaPhi<T>::Phi(int_4 kt,int_4 jp,double& phiMin,double& phiMax)
425
426// Return values of phi which limit the jp-th pixel of the kt-th slice
427//--
428{
429 // verification
430 if((kt < 0) || (kt >= 2*NTheta_)) {
431 phiMin= -99999.;
432 phiMax= -99999.;
433 return;
434 }
435
436 // si on se trouve dans l'hemisphere Sud
437 if(kt >= NTheta_) kt= 2*NTheta_-1-kt;
438
439 // verifie si la tranche kt contient au moins jp pixels
440 if( (jp< 0) || (jp >= NPhi_(kt)) ) {
441 phiMin= -88888.;
442 phiMax= -88888.;
443 return;
444 }
445
446 double dphi= DeuxPi/(double)NPhi_(kt);
447 phiMin= dphi*(double)(jp);
448 phiMax= dphi*(double)(jp+1);
449 return;
450}
451
452/* --Methode-- */
453//++
454template <class T>
455int_4 SphereThetaPhi<T>::Index(int_4 kt,int_4 jp) const
456
457// Return pixel index with sequence index jp in the slice kt
458//--
459{
460 int k;
461 bool fgzn= false;
462
463 // si on se trouve dans l'hemisphere Sud
464 if(kt >= NTheta_) {
465 fgzn= true;
466 kt= 2*NTheta_-1-kt;
467 }
468
469 // si la tranche kt contient au moins i pixels
470 if( (jp>=0) && (jp<NPhi_(kt)) )
471 {
472 // dans l'hemisphere Sud
473 if (fgzn) k= NPix_-TNphi_(kt+1)+jp;
474 // dans l'hemisphere Nord
475 else k= TNphi_(kt)+jp;
476 }
477 else
478 {
479 k= 9999;
480 printf("\n la tranche %d ne contient pas un pixel de rang %d",kt,jp);
481 }
482 return(k);
483}
484
485/* --Methode-- */
486//++
487template <class T>
488void SphereThetaPhi<T>::ThetaPhiIndex(int_4 k,int_4& kt,int_4& jp)
489
490// Return indices kt (theta) and jp (phi) of pixel with index k
491//--
492{
493 bool fgzn= false;
494 // si on se trouve dans l'hemisphere Sud
495 if(k >= NPix_/2)
496 {
497 fgzn= true;
498 k= NPix_-1-k;
499 }
500
501 // on recupere l'indice kt de la tranche qui contient le pixel k
502 int i;
503 for(i = 0; i < NTheta_; i++)
504 if(k < TNphi_(i+1)) break;
505
506 // indice kt de tranche
507 if (fgzn) kt= 2*NTheta_-1-i;
508 else kt= i;
509
510 // indice jp de pixel
511 if (fgzn) jp= TNphi_(i+1)-k-1;
512 else jp= k-TNphi_(i);
513}
514//++
515template <class T>
516void SphereThetaPhi<T>::Pixelize(int_4 m)
517
518// achieve the splitting into pixels (m has the same signification
519// as for the constructor)
520//
521// Each theta-slice of the north hemisphere will be spitted starting f
522// from phi=0 ...
523//
524// South hemisphere is scanned in the same direction according to phi
525// and from equator to the pole (the pixel following the last one of
526// the slice closest to the equator with z>0, is the pixel with lowest
527// phi of the slice closest of the equator with z<0).
528//--
529{
530 int ntotpix,j;
531
532 // Decodage et controle des arguments d'appel :
533 // au moins 2 et au plus 16384 bandes d'un hemisphere en theta
534 if (m < 2) m = 2;
535 if (m > 16384) m = 16384;
536
537 // On memorise les arguments d'appel
538 NTheta_ = m;
539
540 // On commence par decouper l'hemisphere z>0.
541 // Creation des vecteurs contenant :
542 // Les valeurs limites de theta (une valeur de plus que le nombre de bandes...)
543 // Theta_= new double[m+1];
544 Theta_.ReSize(m+1);
545
546 // Le nombre de pixels en phi de chacune des bandes en theta
547 // NPhi_ = new int_4[m];
[980]548 // une taille de m suffit, mais je mets m+1 pour que les 3 tableaux aient
549 // la meme taille pour une manipulation plus faciles par la librairie
550 // cfitsio -- GLM (13-04-00)
551 NPhi_.ReSize(m+1);
[764]552
553 // Le nombre/Deuxpi total des pixels contenus dans les bandes de z superieur a une
554 // bande donnee (mTPphi[m] contient le nombre de pixels total de l'hemisphere)
555 // TNphi_= new int_4[m+1];
556 TNphi_.ReSize(m+1);
557
558 // Calcul du nombre total de pixels dans chaque bande pour optimiser
559 // le rapport largeur/hauteur des pixels
560
561 //calotte polaire
562 TNphi_(0)= 0;
563 NPhi_(0) = 1;
564
565 //bandes jusqu'a l'equateur
566 for(j = 1; j < m; j++)
567 {
568 TNphi_(j)= TNphi_(j-1)+NPhi_(j-1);
569 NPhi_(j) = (int_4)(.5+4.*(double)(m-.5)*sin(Pi*(double)j/(double)(2.*m-1.))) ;
570 }
571
572 // Nombre total de pixels sur l'hemisphere
573 ntotpix = TNphi_(m-1)+NPhi_(m-1);
574 TNphi_(m)= ntotpix;
575 // et sur la sphere entiere
576 NPix_= 2*ntotpix;
577
578 // Creation et initialisation du vecteur des contenus des pixels
579 pixels_.ReSize(NPix_);
580 pixels_.Reset();
581
582 // Determination des limites des bandes en theta :
583 // omeg est l'angle solide couvert par chaque pixel,
584 // une bande donnee kt couvre un angle solide NPhi_[kt]*omeg
585 // egal a 2* Pi*(cos Theta_[kt]-cos Theta_[kt+1]). De meme, l'angle solide
586 //de la
587 // calotte allant du pole a la limite haute de la bande kt vaut
588 // 2* Pi*(1.-cos Theta_[kt+1])= TNphi_[kt]*omeg...
589
590 double omeg2pi= 1./(double)ntotpix;
591 Omega_ = omeg2pi*DeuxPi;
592
593 for(j=0; j <= m; j++)
594 {
595 Theta_(j)= acos(1.-(double)TNphi_(j)*omeg2pi);
596 }
597}
598
599//++
600template <class T>
601void SphereThetaPhi<T>::GetThetaSlice(int_4 index,r_8& theta, TVector<r_8>& phi, TVector<T>& value) const
602
603// For a theta-slice with index 'index', return :
604// the corresponding "theta"
605// a vector containing the phi's of the pixels of the slice
606// a vector containing the corresponding values of pixels
607//--
608
609{
610
611 if(index < 0 || index >= NbThetaSlices())
612 {
613 throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range");
614 }
615
616 int iring= Index(index,0);
617 int lring = NPhi(index);
618
619 phi.ReSize(lring);
620 value.ReSize(lring);
621 double Te= 0.;
622 double Fi= 0.;
623 for(int kk = 0; kk < lring; kk++)
624 {
625 PixThetaPhi(kk+iring,Te,Fi);
626 phi(kk)= Fi;
627 value(kk)= PixVal(kk+iring);
628 }
629 theta= Te;
630}
631
632//++
633template <class T>
634void SphereThetaPhi<T>::GetThetaSlice(int_4 index,r_8& theta, r_8& phi0,TVector<int_4>& pixelIndices, TVector<T>& value) const
635
636// For a theta-slice with index 'index', return :
637// the corresponding "theta"
638// the corresponding "phi" for first pixel of the slice
639// a vector containing the indices of the pixels of the slice
640// (equally distributed in phi)
641// a vector containing the corresponding values of pixels
642//--
643
644{
645
646 if(index < 0 || index >= NbThetaSlices())
647 {
648 throw RangeCheckError("SphereThetaPhi::PIxVal Pixel index out of range");
649
650 }
651
652 int iring= Index(index,0);
653 int lring = NPhi(index);
654
655 pixelIndices.ReSize(lring);
656 value.ReSize(lring);
657 double Te= 0.;
658 double Fi= 0.;
659 for(int kk = 0; kk < lring; kk++)
660 {
661 pixelIndices(kk)=kk+iring ;
662 value(kk)= PixVal(kk+iring);
663 }
664 PixThetaPhi(iring,theta,phi0);
665}
666
667
668
669
670template <class T>
671void SphereThetaPhi<T>::print(ostream& os) const
672{
673 if(mInfo_) os << " DVList Info= " << *mInfo_ << endl;
674 //
675 os << " NTheta_= " << NTheta_ << endl;
676 os << " NPix_ = " << NPix_ << endl;
677 os << " Omega_ = " << Omega_ << endl;
678
679 os << " contenu de NPhi_ : ";
680 int i;
681 for(i=0; i < NTheta_; i++)
682 {
683 if(i%5 == 0) os << endl;
684 os << NPhi_(i) <<", ";
685 }
686 os << endl;
687
688 os << " contenu de Theta_ : ";
689 for(i=0; i < NTheta_+1; i++)
690 {
691 if(i%5 == 0) os << endl;
692 os << Theta_(i) <<", ";
693 }
694 os << endl;
695
696 os << " contenu de TNphi_ : ";
697 for(i=0; i < NTheta_+1; i++)
698 {
699 if(i%5 == 0) os << endl;
700 os << TNphi_(i) <<", ";
701 }
702 os << endl;
703
704 os << " contenu de pixels : ";
705 for(i=0; i < NPix_; i++)
706 {
707 if(i%5 == 0) os << endl;
708 os << pixels_(i) <<", ";
709 }
710 os << endl;
711}
712
713
714#ifdef __CXX_PRAGMA_TEMPLATES__
715#pragma define_template SphereThetaPhi<r_8>
716#pragma define_template SphereThetaPhi<r_4>
717#pragma define_template SphereThetaPhi< complex<r_4> >
718#pragma define_template SphereThetaPhi< complex<r_8> >
719#endif
720#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
721template class SphereThetaPhi<r_8>;
722template class SphereThetaPhi<r_4>;
723template class SphereThetaPhi< complex<r_4> >;
724template class SphereThetaPhi< complex<r_8> >;
725#endif
Note: See TracBrowser for help on using the repository browser.