source: Sophya/trunk/SophyaLib/SkyMap/spherehealpix.cc@ 1431

Last change on this file since 1431 was 1419, checked in by lemeur, 25 years ago

surcharge d'operateurs =, +=, *= etc...

File size: 17.3 KB
Line 
1#include "machdefs.h"
2#include <math.h>
3#include <complex>
4
5#include "pexceptions.h"
6#include "fiondblock.h"
7#include "spherehealpix.h"
8#include "strutil.h"
9
10extern "C"
11{
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15}
16
17using namespace SOPHYA;
18
19/*!
20 \class SOPHYA::SphereHEALPix
21
22*******************************************************************
23 Pixelisation Gorski
24
25\verbatim
26
27 -----------------------------------------------------------------------
28 version 0.8.2 Aug97 TAC Eric Hivon, Kris Gorski
29 -----------------------------------------------------------------------
30
31 the sphere is split in 12 diamond-faces containing nside**2 pixels each
32 the numbering of the pixels (in the nested scheme) is similar to
33 quad-cube
34 In each face the first pixel is in the lowest corner of the diamond
35 the faces are (x,y) coordinate on each face
36
37 . . . . <--- North Pole
38 / \ / \ / \ / \ ^ ^
39 . 0 . 1 . 2 . 3 . <--- z = 2/3 \ /
40 \ / \ / \ / \ / y \ / x
41 4 . 5 . 6 . 7 . 4 <--- equator \ /
42 / \ / \ / \ / \ \/
43 . 8 . 9 .10 .11 . <--- z = -2/3 (0,0) : lowest corner
44 \ / \ / \ / \ /
45 . . . . <--- South Pole
46\endverbatim
47 phi:0 2Pi
48
49 in the ring scheme pixels are numbered along the parallels
50 the first parallel is the one closest to the north pole and so on
51 on each parallel, pixels are numbered starting from the one closest
52 to phi = 0
53
54 nside MUST be a power of 2 (<= 8192)
55
56*/
57
58/* --Methode-- */
59
60template<class T>
61SphereHEALPix<T>::SphereHEALPix() : pixels_(), sliceBeginIndex_(),
62 sliceLenght_()
63
64
65{
66 InitNul();
67}
68
69/*! \fn SOPHYA::SphereHEALPix::SphereHEALPix(int_4 m)
70
71 \param <m> : "nside" of the Healpix algorithm
72
73 The total number of pixels will be Npix = 12*nside**2
74
75 nside MUST be a power of 2 (<= 8192)
76*/
77
78template<class T>
79SphereHEALPix<T>::SphereHEALPix(int_4 m)
80
81{
82
83 if(m <= 0 || m > 8192)
84 {
85 cout << "SphereHEALPix : m hors bornes [0,8192], m= " << m << endl;
86 throw RangeCheckError("SphereHEALPix<T>::SphereHEALPix() - Out of bound nside (< 8192)!");
87 }
88 // verifier que m est une puissance de deux
89 int x= m;
90 while(x%2 == 0) x/=2;
91 if(x != 1)
92 {
93 cout<<"SphereHEALPix: m doit etre une puissance de deux, m= "<<m<<endl;
94 throw ParmError("SphereHEALPix<T>::SphereHEALPix() - nside != 2^n !");
95 }
96 InitNul();
97 // SetTemp(false);
98 Pixelize(m);
99 SetThetaSlices();
100}
101//++
102template<class T>
103SphereHEALPix<T>::SphereHEALPix(const SphereHEALPix<T>& s, bool share)
104 : pixels_(s.pixels_, share), sliceBeginIndex_(s.sliceBeginIndex_, share),
105 sliceLenght_(s.sliceLenght_, share)
106// copy constructor
107//--
108{
109 nSide_= s.nSide_;
110 nPix_ = s.nPix_;
111 omeg_ = s.omeg_;
112 if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
113}
114//++
115template<class T>
116SphereHEALPix<T>::SphereHEALPix(const SphereHEALPix<T>& s)
117 : pixels_(s.pixels_), sliceBeginIndex_(s.sliceBeginIndex_),
118 sliceLenght_(s.sliceLenght_)
119// copy constructor
120//--
121{
122 nSide_= s.nSide_;
123 nPix_ = s.nPix_;
124 omeg_ = s.omeg_;
125 if(s.mInfo_) mInfo_= new DVList(*s.mInfo_);
126 // CloneOrShare(s);
127}
128
129//! Clone if \b a is not temporary, share if temporary
130/*! \sa NDataBlock::CloneOrShare(const NDataBlock<T>&) */
131template<class T>
132void SphereHEALPix<T>::CloneOrShare(const SphereHEALPix<T>& a)
133{
134 nSide_= a.nSide_;
135 nPix_ = a.nPix_;
136 omeg_ = a.omeg_;
137 pixels_.CloneOrShare(a.pixels_);
138 sliceBeginIndex_.CloneOrShare(a.sliceBeginIndex_);
139 sliceLenght_.CloneOrShare(a.sliceLenght_);
140 if (mInfo_) {delete mInfo_; mInfo_ = NULL;}
141 if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_));
142}
143
144//! Share data with a
145template<class T>
146void SphereHEALPix<T>::Share(const SphereHEALPix<T>& a)
147{
148 nSide_= a.nSide_;
149 nPix_ = a.nPix_;
150 omeg_ = a.omeg_;
151 pixels_.Share(a.pixels_);
152 sliceBeginIndex_.Share(a.sliceBeginIndex_);
153 sliceLenght_.Share(a.sliceLenght_);
154 if (mInfo_) {delete mInfo_; mInfo_ = NULL;}
155 if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_));
156}
157
158////////////////////////// methodes de copie/share
159template<class T>
160SphereHEALPix<T>& SphereHEALPix<T>::Set(const SphereHEALPix<T>& a)
161{
162 if (this != &a)
163 {
164
165 if (a.NbPixels() < 1)
166 throw RangeCheckError("SphereHEALPix<T>::Set(a ) - SphereHEALPix a not allocated ! ");
167 if (NbPixels() < 1) CloneOrShare(a);
168 else CopyElt(a);
169
170
171 if (mInfo_) delete mInfo_;
172 mInfo_ = NULL;
173 if (a.mInfo_) mInfo_ = new DVList(*(a.mInfo_));
174 }
175 return(*this);
176}
177
178template<class T>
179SphereHEALPix<T>& SphereHEALPix<T>::CopyElt(const SphereHEALPix<T>& a)
180{
181 if (NbPixels() < 1)
182 throw RangeCheckError("SphereHEALPix<T>::CopyElt(const SphereHEALPix<T>& ) - Not Allocated SphereHEALPix ! ");
183 if (NbPixels() != a.NbPixels())
184 throw(SzMismatchError("SphereHEALPix<T>::CopyElt(const SphereHEALPix<T>&) SizeMismatch")) ;
185 nSide_= a.nSide_;
186 nPix_ = a.nPix_;
187 omeg_ = a.omeg_;
188 int k;
189 for (k=0; k< nPix_; k++) pixels_(k) = a.pixels_(k);
190 for (k=0; k< a.sliceBeginIndex_.Size(); k++) sliceBeginIndex_(k) = a.sliceBeginIndex_(k);
191 for (k=0; k< a.sliceLenght_.Size(); k++) sliceLenght_(k) = a.sliceLenght_(k);
192 return(*this);
193}
194
195
196
197//++
198// Titre Destructor
199//--
200//++
201template<class T>
202SphereHEALPix<T>::~SphereHEALPix()
203
204//--
205{
206}
207
208//++
209// Titre Public Methods
210//--
211
212/*! \fn void SOPHYA::SphereHEALPix::Resize(int_4 m)
213 \param <m> "nside" of the Gorski algorithm
214
215 The total number of pixels will be Npix = 12*nside**2
216
217 nside MUST be a power of 2 (<= 8192)
218*/
219template<class T>
220void SphereHEALPix<T>::Resize(int_4 m)
221
222
223{
224 if (m<=0 || m> 8192) {
225 cout << "SphereHEALPix : m hors bornes [0,8192], m= " << m << endl;
226 exit(1);
227 }
228 // verifier que m est une puissance de deux
229 int x= m;
230 while (x%2==0) x/=2;
231 if(x != 1)
232 {
233 cout<<"SphereHEALPix: m doit etre une puissance de deux, m= "<<m<<endl;
234 exit(1);
235 }
236 InitNul();
237 Pixelize(m);
238 SetThetaSlices();
239}
240
241template<class T>
242void SphereHEALPix<T>::Pixelize( int_4 m)
243
244// prépare la pixelisation Gorski (m a la même signification
245// que pour le constructeur)
246//
247//
248{
249 // On memorise les arguments d'appel
250 nSide_= m;
251
252 // Nombre total de pixels sur la sphere entiere
253 nPix_= 12*nSide_*nSide_;
254
255 // pour le moment les tableaux qui suivent seront ranges dans l'ordre
256 // de l'indexation GORSKY "RING"
257 // on pourra ulterieurement changer de strategie et tirer profit
258 // de la dualite d'indexation GORSKY (RING et NEST) : tout dependra
259 // de pourquoi c'est faire
260
261 // Creation et initialisation du vecteur des contenus des pixels
262 pixels_.ReSize(nPix_);
263 pixels_.Reset();
264
265 // solid angle per pixel
266 omeg_= 4.0*Pi/nPix_;
267}
268
269template<class T>
270void SphereHEALPix<T>::InitNul()
271//
272// initialise à zéro les variables de classe
273{
274 nSide_= 0;
275 nPix_ = 0;
276 omeg_ = 0.;
277// pixels_.Reset(); - Il ne faut pas mettre les pixels a zero si share !
278}
279
280/* --Methode-- */
281/* Nombre de pixels du decoupage */
282/*! \fn int_4 SOPHYA::SphereHEALPix::NbPixels() const
283
284 Return number of pixels of the splitting
285*/
286template<class T>
287int_4 SphereHEALPix<T>::NbPixels() const
288{
289 return(nPix_);
290}
291
292
293/*! \fn uint_4 SOPHYA::SphereHEALPix::NbThetaSlices() const
294
295 \return number of slices in theta direction on the sphere
296*/
297template<class T>
298uint_4 SphereHEALPix<T>::NbThetaSlices() const
299{
300 uint_4 nbslices = uint_4(4*nSide_-1);
301 if (nSide_<=0)
302 {
303 nbslices = 0;
304 throw PException(" sphere not pixelized, NbSlice=0 ");
305 }
306 return nbslices;
307}
308
309/*! \fn void SOPHYA::SphereHEALPix::GetThetaSlice(int_4 index,r_8& theta,TVector<r_8>& phi,TVector<T>& value) const
310
311 For a theta-slice with index 'index', return :
312
313 the corresponding "theta"
314
315 a vector containing the phi's of the pixels of the slice
316
317 a vector containing the corresponding values of pixels
318*/
319template<class T>
320void SphereHEALPix<T>::GetThetaSlice(int_4 index,r_8& theta,TVector<r_8>& phi,TVector<T>& value) const
321
322{
323
324 if (index<0 || index >= NbThetaSlices())
325 {
326 cout << " SphereHEALPix::GetThetaSlice : Pixel index out of range" <<endl;
327 throw RangeCheckError(" SphereHEALPix::GetThetaSlice : Pixel index out of range");
328 }
329
330
331 int_4 iring= sliceBeginIndex_(index);
332 int_4 lring = sliceLenght_(index);
333
334 phi.ReSize(lring);
335 value.ReSize(lring);
336
337 double TH= 0.;
338 double FI= 0.;
339 for(int_4 kk = 0; kk < lring;kk++)
340 {
341 PixThetaPhi(kk+iring,TH,FI);
342 phi(kk)= FI;
343 value(kk)= PixVal(kk+iring);
344 }
345 theta= TH;
346}
347/*! \fn void SOPHYA::SphereHEALPix::GetThetaSlice(int_4 sliceIndex,r_8& theta, r_8& phi0, TVector<int_4>& pixelIndices,TVector<T>& value) const
348
349 For a theta-slice with index 'index', return :
350
351 the corresponding "theta"
352
353 the corresponding "phi" for first pixel of the slice
354
355 a vector containing indices of the pixels of the slice
356
357 (equally distributed in phi)
358
359 a vector containing the corresponding values of pixels
360*/
361
362template<class T>
363void SphereHEALPix<T>::GetThetaSlice(int_4 sliceIndex,r_8& theta, r_8& phi0, TVector<int_4>& pixelIndices,TVector<T>& value) const
364
365{
366
367 if (sliceIndex<0 || sliceIndex >= NbThetaSlices())
368 {
369 cout << " SphereHEALPix::GetThetaSlice : Pixel index out of range" <<endl;
370 throw RangeCheckError(" SphereHEALPix::GetThetaSlice : Pixel index out of range");
371 }
372 int_4 iring= sliceBeginIndex_(sliceIndex);
373 int_4 lring = sliceLenght_(sliceIndex);
374 pixelIndices.ReSize(lring);
375 value.ReSize(lring);
376
377 for(int_4 kk = 0; kk < lring;kk++)
378 {
379 pixelIndices(kk)= kk+iring;
380 value(kk)= PixVal(kk+iring);
381 }
382 PixThetaPhi(iring, theta, phi0);
383}
384
385template<class T>
386void SphereHEALPix<T>::SetThetaSlices()
387{
388 sliceBeginIndex_.ReSize(4*nSide_-1);
389 sliceLenght_.ReSize(4*nSide_-1);
390 int sliceIndex;
391 for (sliceIndex=0; sliceIndex< nSide_-1; sliceIndex++)
392 {
393 sliceBeginIndex_(sliceIndex) = 2*sliceIndex*(sliceIndex+1);
394 sliceLenght_(sliceIndex) = 4*(sliceIndex+1);
395 }
396 for (sliceIndex= nSide_-1; sliceIndex< 3*nSide_; sliceIndex++)
397 {
398 sliceBeginIndex_(sliceIndex) = 2*nSide_*(2*sliceIndex-nSide_+1);
399 sliceLenght_(sliceIndex) = 4*nSide_;
400 }
401 for (sliceIndex= 3*nSide_; sliceIndex< 4*nSide_-1; sliceIndex++)
402 {
403 int_4 nc= 4*nSide_-1-sliceIndex;
404 sliceBeginIndex_(sliceIndex) = nPix_-2*nc*(nc+1);
405 sliceLenght_(sliceIndex) = 4*nc;
406 }
407}
408
409
410/*! \fn T& SOPHYA::SphereHEALPix::PixVal(int_4 k)
411
412 \return value of pixel with "RING" index k
413*/
414template<class T>
415T& SphereHEALPix<T>::PixVal(int_4 k)
416
417{
418 if((k < 0) || (k >= nPix_))
419 {
420 throw RangeCheckError("SphereHEALPix::PIxVal Pixel index out of range");
421 }
422 return pixels_(k);
423}
424
425/*! \fn T const& SOPHYA::SphereHEALPix::PixVal(int_4 k) const
426
427 \return value of pixel with "RING" index k
428*/
429template<class T>
430T const& SphereHEALPix<T>::PixVal(int_4 k) const
431
432{
433 if((k < 0) || (k >= nPix_))
434 {
435 throw RangeCheckError("SphereHEALPix::PIxVal Pixel index out of range");
436 }
437 return *(pixels_.Data()+k);
438}
439
440/*! \fn T& SOPHYA::SphereHEALPix::PixValNest(int_4 k)
441
442 \return value of pixel with "NESTED" index k
443*/
444template<class T>
445T& SphereHEALPix<T>::PixValNest(int_4 k)
446
447//--
448{
449 if((k < 0) || (k >= nPix_))
450 {
451 throw RangeCheckError("SphereHEALPix::PIxValNest Pixel index out of range");
452 }
453 return pixels_(nest2ring(nSide_,k));
454}
455
456/*! \fn T const& SOPHYA::SphereHEALPix::PixValNest(int_4 k) const
457
458 \return value of pixel with "NESTED" index k
459*/
460
461template<class T>
462T const& SphereHEALPix<T>::PixValNest(int_4 k) const
463
464{
465 if((k < 0) || (k >= nPix_))
466 {
467 throw RangeCheckError("SphereHEALPix::PIxValNest Pixel index out of range");
468 }
469 int_4 pix= nest2ring(nSide_,k);
470 return *(pixels_.Data()+pix);
471}
472
473/*! \fn bool SOPHYA::SphereHEALPix::ContainsSph(double theta, double phi) const
474
475\return true if teta,phi in map
476*/
477template<class T>
478bool SphereHEALPix<T>::ContainsSph(double theta, double phi) const
479{
480return(true);
481}
482
483/*! \fn int_4 SOPHYA::SphereHEALPix::PixIndexSph(double theta,double phi) const
484
485 \return "RING" index of the pixel corresponding to direction (theta, phi).
486 */
487template<class T>
488int_4 SphereHEALPix<T>::PixIndexSph(double theta,double phi) const
489
490{
491 return ang2pix_ring(nSide_,theta,phi);
492}
493
494/*! \fn int_4 SOPHYA::SphereHEALPix::PixIndexSphNest(double theta,double phi) const
495
496 \return "NESTED" index of the pixel corresponding to direction (theta, phi).
497 */
498template<class T>
499int_4 SphereHEALPix<T>::PixIndexSphNest(double theta,double phi) const
500
501{
502 return ang2pix_nest(nSide_,theta,phi);
503}
504
505
506/* --Methode-- */
507/*! \fn void SOPHYA::SphereHEALPix::PixThetaPhi(int_4 k,double& theta,double& phi) const
508 \return (theta,phi) coordinates of middle of pixel with "RING" index k
509 */
510template<class T>
511void SphereHEALPix<T>::PixThetaPhi(int_4 k,double& theta,double& phi) const
512{
513 pix2ang_ring(nSide_,k,theta,phi);
514}
515
516/*! \fn T SOPHYA::SphereHEALPix::SetPixels(T v)
517
518Set all pixels to value v
519*/
520template <class T>
521T SphereHEALPix<T>::SetPixels(T v)
522{
523pixels_.Reset(v);
524return(v);
525}
526
527
528
529/*! \fn void SOPHYA::SphereHEALPix::PixThetaPhiNest(int_4 k,double& theta,double& phi) const
530
531 \return (theta,phi) coordinates of middle of pixel with "NESTED" index k
532 */
533template<class T>
534void SphereHEALPix<T>::PixThetaPhiNest(int_4 k,double& theta,double& phi) const
535
536{
537 pix2ang_nest(nSide_,k,theta,phi);
538}
539
540
541/*! \fn int_4 SOPHYA::SphereHEALPix::NestToRing(int_4 k) const
542
543 translation from NESTED index into RING index
544*/
545template<class T>
546int_4 SphereHEALPix<T>::NestToRing(int_4 k) const
547
548{
549 return nest2ring(nSide_,k);
550}
551
552
553/*! \fn int_4 SOPHYA::SphereHEALPix::RingToNest(int_4 k) const
554
555 translation from RING index into NESTED index
556*/
557template<class T>
558int_4 SphereHEALPix<T>::RingToNest(int_4 k) const
559{
560 return ring2nest(nSide_,k);
561}
562
563// ...... Operations de calcul ......
564
565//! Fill a SphereHEALPix with a constant value \b a
566template <class T>
567SphereHEALPix<T>& SphereHEALPix<T>::SetT(T a)
568{
569 if (NbPixels() < 1)
570 throw RangeCheckError("SphereHEALPix<T>::SetT(T ) - SphereHEALPix not dimensionned ! ");
571 pixels_ = a;
572 return (*this);
573}
574
575/*! Add a constant value \b x to a SphereHEALPix */
576template <class T>
577SphereHEALPix<T>& SphereHEALPix<T>::Add(T a)
578 {
579 if (NbPixels() < 1)
580 throw RangeCheckError("SphereHEALPix<T>::Add(T ) - SphereHEALPix not dimensionned ! ");
581 pixels_ += a;
582 return (*this);
583}
584
585/*! Substract a constant value \b a to a SphereHEALPix */
586template <class T>
587SphereHEALPix<T>& SphereHEALPix<T>::Sub(T a)
588{
589 if (NbPixels() < 1)
590 throw RangeCheckError("SphereHEALPix<T>::Sub(T ) - SphereHEALPix not dimensionned ! ");
591 pixels_ -= a;
592 return (*this);
593}
594
595/*! multiply a SphereHEALPix by a constant value \b a */
596template <class T>
597SphereHEALPix<T>& SphereHEALPix<T>::Mul(T a)
598{
599 if (NbPixels() < 1)
600 throw RangeCheckError("SphereHEALPix<T>::Mul(T ) - SphereHEALPix not dimensionned ! ");
601 pixels_ *= a;
602 return (*this);
603}
604
605/*! divide a SphereHEALPix by a constant value \b a */
606template <class T>
607SphereHEALPix<T>& SphereHEALPix<T>::Div(T a)
608{
609 if (NbPixels() < 1)
610 throw RangeCheckError("SphereHEALPix<T>::Div(T ) - SphereHEALPix not dimensionned ! ");
611 pixels_ /= a;
612 return (*this);
613}
614
615// >>>> Operations avec 2nd membre de type SphereHEALPix
616//! Add two SphereHEALPix
617
618template <class T>
619SphereHEALPix<T>& SphereHEALPix<T>::AddElt(const SphereHEALPix<T>& a)
620{
621 if (NbPixels() != a.NbPixels() )
622 {
623 throw(SzMismatchError("SphereHEALPix<T>::AddElt(const SphereHEALPix<T>&) SizeMismatch")) ;
624 }
625 pixels_ += a.pixels_;
626 return (*this);
627}
628
629//! Substract two SphereHEALPix
630template <class T>
631SphereHEALPix<T>& SphereHEALPix<T>::SubElt(const SphereHEALPix<T>& a)
632{
633 if (NbPixels() != a.NbPixels() )
634 {
635 throw(SzMismatchError("SphereHEALPix<T>::SubElt(const SphereHEALPix<T>&) SizeMismatch")) ;
636 }
637 pixels_ -= a.pixels_;
638 return (*this);
639}
640
641//! Multiply two SphereHEALPix (elements by elements)
642template <class T>
643SphereHEALPix<T>& SphereHEALPix<T>::MulElt(const SphereHEALPix<T>& a)
644{
645 if (NbPixels() != a.NbPixels() )
646 {
647 throw(SzMismatchError("SphereHEALPix<T>::SubElt(const SphereHEALPix<T>&) SizeMismatch")) ;
648 }
649 pixels_ *= a.pixels_;
650 return (*this);
651}
652
653
654
655
656template <class T>
657void SphereHEALPix<T>::print(ostream& os) const
658{
659 if(mInfo_) os << " DVList Info= " << *mInfo_ << endl;
660 //
661 os << " nSide_ = " << nSide_ << endl;
662 os << " nPix_ = " << nPix_ << endl;
663 os << " omeg_ = " << omeg_ << endl;
664
665 os << " content of pixels : ";
666 for(int i=0; i < nPix_; i++)
667 {
668 if(i%5 == 0) os << endl;
669 os << pixels_(i) <<", ";
670 }
671 os << endl;
672
673
674}
675
676
677
678//*******************************************************************
679
680#ifdef __CXX_PRAGMA_TEMPLATES__
681#pragma define_template SphereHEALPix<uint_2>
682#pragma define_template SphereHEALPix<int_4>
683#pragma define_template SphereHEALPix<r_8>
684#pragma define_template SphereHEALPix<r_4>
685#pragma define_template SphereHEALPix< complex<r_4> >
686#pragma define_template SphereHEALPix< complex<r_8> >
687#endif
688#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
689template class SphereHEALPix<uint_2>;
690template class SphereHEALPix<int_4>;
691template class SphereHEALPix<r_8>;
692template class SphereHEALPix<r_4>;
693template class SphereHEALPix< complex<r_4> >;
694template class SphereHEALPix< complex<r_8> >;
695#endif
696
Note: See TracBrowser for help on using the repository browser.