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

Last change on this file since 2327 was 2303, checked in by ansari, 23 years ago

MAJ pour documentation V1.5 , Reza 2/3/2003

File size: 17.7 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 \ingroup SkyMap
22 Class implementing spherical maps, in the HEALPix pixelisation scheme,
23 with template data types (double, float, complex, ...)
24
25
26\verbatim
27
28 -----------------------------------------------------------------------
29 version 0.8.2 Aug97 TAC Eric Hivon, Kris Gorski
30 -----------------------------------------------------------------------
31
32 the sphere is split in 12 diamond-faces containing nside**2 pixels each
33 the numbering of the pixels (in the nested scheme) is similar to
34 quad-cube
35 In each face the first pixel is in the lowest corner of the diamond
36 the faces are (x,y) coordinate on each face
37
38 . . . . <--- North Pole
39 / \ / \ / \ / \ ^ ^
40 . 0 . 1 . 2 . 3 . <--- z = 2/3 \ /
41 \ / \ / \ / \ / y \ / x
42 4 . 5 . 6 . 7 . 4 <--- equator \ /
43 / \ / \ / \ / \ \/
44 . 8 . 9 .10 .11 . <--- z = -2/3 (0,0) : lowest corner
45 \ / \ / \ / \ /
46 . . . . <--- South Pole
47\endverbatim
48 phi:0 2Pi
49
50 in the ring scheme pixels are numbered along the parallels
51 the first parallel is the one closest to the north pole and so on
52 on each parallel, pixels are numbered starting from the one closest
53 to phi = 0
54
55 nside MUST be a power of 2 (<= 8192)
56
57*/
58
59/* --Methode-- */
60
61template<class T>
62SphereHEALPix<T>::SphereHEALPix() : pixels_(), sliceBeginIndex_(),
63 sliceLenght_()
64
65
66{
67 InitNul();
68}
69
70/*! \fn SOPHYA::SphereHEALPix::SphereHEALPix(int_4 m)
71
72 \param <m> : "nside" of the Healpix algorithm
73
74 The total number of pixels will be Npix = 12*nside**2
75
76 nside MUST be a power of 2 (<= 8192)
77*/
78
79template<class T>
80SphereHEALPix<T>::SphereHEALPix(int_4 m)
81
82{
83
84 if(m <= 0 || m > 8192)
85 {
86 cout << "SphereHEALPix : m hors bornes [0,8192], m= " << m << endl;
87 throw RangeCheckError("SphereHEALPix<T>::SphereHEALPix() - Out of bound nside (< 8192)!");
88 }
89 // verifier que m est une puissance de deux
90 int x= m;
91 while(x%2 == 0) x/=2;
92 if(x != 1)
93 {
94 cout<<"SphereHEALPix: m doit etre une puissance de deux, m= "<<m<<endl;
95 throw ParmError("SphereHEALPix<T>::SphereHEALPix() - nside != 2^n !");
96 }
97 InitNul();
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 cout << " c'est mon Add " << endl;
580 if (NbPixels() < 1)
581 throw RangeCheckError("SphereHEALPix<T>::Add(T ) - SphereHEALPix not dimensionned ! ");
582 // pixels_ += a;
583 pixels_.Add(a);
584 return (*this);
585}
586
587/*! Substract a constant value \b a to a SphereHEALPix */
588template <class T>
589SphereHEALPix<T>& SphereHEALPix<T>::Sub(T a,bool fginv)
590{
591 if (NbPixels() < 1)
592 throw RangeCheckError("SphereHEALPix<T>::Sub(T ) - SphereHEALPix not dimensionned ! ");
593 pixels_.Sub(a,fginv);
594 return (*this);
595}
596
597/*! multiply a SphereHEALPix by a constant value \b a */
598template <class T>
599SphereHEALPix<T>& SphereHEALPix<T>::Mul(T a)
600{
601 if (NbPixels() < 1)
602 throw RangeCheckError("SphereHEALPix<T>::Mul(T ) - SphereHEALPix not dimensionned ! ");
603 pixels_ *= a;
604 return (*this);
605}
606
607/*! divide a SphereHEALPix by a constant value \b a */
608template <class T>
609SphereHEALPix<T>& SphereHEALPix<T>::Div(T a)
610{
611 if (NbPixels() < 1)
612 throw RangeCheckError("SphereHEALPix<T>::Div(T ) - SphereHEALPix not dimensionned ! ");
613 pixels_ /= a;
614 return (*this);
615}
616
617// >>>> Operations avec 2nd membre de type SphereHEALPix
618//! Add two SphereHEALPix
619
620template <class T>
621SphereHEALPix<T>& SphereHEALPix<T>::AddElt(const SphereHEALPix<T>& a)
622{
623 if (NbPixels() != a.NbPixels() )
624 {
625 throw(SzMismatchError("SphereHEALPix<T>::AddElt(const SphereHEALPix<T>&) SizeMismatch")) ;
626 }
627 pixels_ += a.pixels_;
628 return (*this);
629}
630
631//! Substract two SphereHEALPix
632template <class T>
633SphereHEALPix<T>& SphereHEALPix<T>::SubElt(const SphereHEALPix<T>& a)
634{
635 if (NbPixels() != a.NbPixels() )
636 {
637 throw(SzMismatchError("SphereHEALPix<T>::SubElt(const SphereHEALPix<T>&) SizeMismatch")) ;
638 }
639 pixels_ -= a.pixels_;
640 return (*this);
641}
642
643//! Multiply two SphereHEALPix (elements by elements)
644template <class T>
645SphereHEALPix<T>& SphereHEALPix<T>::MulElt(const SphereHEALPix<T>& a)
646{
647 if (NbPixels() != a.NbPixels() )
648 {
649 throw(SzMismatchError("SphereHEALPix<T>::MulElt(const SphereHEALPix<T>&) SizeMismatch")) ;
650 }
651 pixels_ *= a.pixels_;
652 return (*this);
653}
654
655//! Divide two SphereHEALPix (elements by elements) - No protection for divide by 0
656template <class T>
657SphereHEALPix<T>& SphereHEALPix<T>::DivElt(const SphereHEALPix<T>& a)
658{
659 if (NbPixels() != a.NbPixels() )
660 {
661 throw(SzMismatchError("SphereHEALPix<T>::DivElt(const SphereHEALPix<T>&) SizeMismatch")) ;
662 }
663 pixels_ /= a.pixels_;
664 return (*this);
665}
666
667
668
669
670template <class T>
671void SphereHEALPix<T>::print(ostream& os) const
672{
673 if(mInfo_) os << " DVList Info= " << *mInfo_ << endl;
674 //
675 os << " nSide_ = " << nSide_ << endl;
676 os << " nPix_ = " << nPix_ << endl;
677 os << " omeg_ = " << omeg_ << endl;
678
679 os << " content of pixels : ";
680 for(int i=0; i < nPix_; i++)
681 {
682 if(i%5 == 0) os << endl;
683 os << pixels_(i) <<", ";
684 }
685 os << endl;
686
687
688}
689
690
691
692//*******************************************************************
693
694#ifdef __CXX_PRAGMA_TEMPLATES__
695#pragma define_template SphereHEALPix<uint_2>
696#pragma define_template SphereHEALPix<int_4>
697#pragma define_template SphereHEALPix<r_8>
698#pragma define_template SphereHEALPix<r_4>
699#pragma define_template SphereHEALPix< complex<r_4> >
700#pragma define_template SphereHEALPix< complex<r_8> >
701#endif
702#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
703template class SphereHEALPix<uint_2>;
704template class SphereHEALPix<int_4>;
705template class SphereHEALPix<r_8>;
706template class SphereHEALPix<r_4>;
707template class SphereHEALPix< complex<r_4> >;
708template class SphereHEALPix< complex<r_8> >;
709#endif
710
Note: See TracBrowser for help on using the repository browser.