source: Sophya/trunk/SophyaLib/Samba/spheregorski.cc@ 228

Last change on this file since 228 was 228, checked in by ansari, 26 years ago

Creation du module DPC/Samba Reza 13/04/99

File size: 38.5 KB
RevLine 
[228]1//
2#include "spheregorski.h"
3#include "strutil.h"
4extern "C" {
5#include <stdio.h>
6#include <stdlib.h>
7#include <unistd.h>
8}
9
10extern "C" {
11 //void ang2pix_ring_(int&,double&,double&,int&);
12 //void pix2ang_ring_(int&, int&, double&, double&);
13//void ang2pix_nest_(int&,double&,double&,int&);
14 //void pix2ang_nest_(int&, int&, double&, double&);
15//void nest2ring_(int&, int&, int&);
16//void ring2nest_(int&, int&, int&);
17void anafast_(int&, int&, int&,double&,float*,float*,float*,float*,
18 float*,float*,float*);
19void synfast_(int&, int&, int&,int&, float&,float*,float*,float*,
20 double*, double*,double*,double*,double*,float*);
21void input_map_(char*,float*,int&);
22void ecrire_fits_(int&,int&,int&,float*,char*,char*,int&,float&,float&);
23
24}
25//*******************************************************************
26//++
27// Class SphereGorski
28//
29// include spheregorski.h strutil.h
30//
31// Pixelisation Gorski
32//
33//
34//| -----------------------------------------------------------------------
35//| version 0.8.2 Aug97 TAC Eric Hivon, Kris Gorski
36//| -----------------------------------------------------------------------
37//
38// the sphere is split in 12 diamond-faces containing nside**2 pixels each
39//
40// the numbering of the pixels (in the nested scheme) is similar to
41// quad-cube
42// In each face the first pixel is in the lowest corner of the diamond
43//
44// the faces are (x,y) coordinate on each face
45//| . . . . <--- North Pole
46//| / \ / \ / \ / \ ^ ^
47//| . 0 . 1 . 2 . 3 . <--- z = 2/3 \ /
48//| \ / \ / \ / \ / y \ / x
49//| 4 . 5 . 6 . 7 . 4 <--- equator \ /
50//| / \ / \ / \ / \ \/
51//| . 8 . 9 .10 .11 . <--- z = -2/3 (0,0) : lowest corner
52//| \ / \ / \ / \ /
53//| . . . . <--- South Pole
54//|
55// phi:0 2Pi
56//
57// in the ring scheme pixels are numbered along the parallels
58// the first parallel is the one closest to the north pole and so on
59// on each parallel, pixels are numbered starting from the one closest
60// to phi = 0
61//
62// nside DOIT OBLIGATOIREMENT ETRE UNE PUISSANCE DE 2 (<= 8192)
63//--
64//++
65//
66// Links Parents
67//
68// SphericalMap
69//--
70//++
71//
72// Links Descendants
73//
74//
75//--
76
77/* --Methode-- */
78//++
79// Titre Constructeurs
80//--
81//++
82
83SphereGorski::SphereGorski()
84
85//--
86{
87 InitNul();
88}
89
90/* --Methode-- */
91//++
92SphereGorski::SphereGorski(char* flnm)
93
94// Constructeur : charge une image à partir d'un fichier
95//--
96{
97 InitNul();
98 PInPersist s(flnm);
99 Read(s);
100}
101
102//++
103SphereGorski::SphereGorski(int_4 m)
104
105// Constructeur : m est la variable nside de l'algorithme de Gorski
106// le nombre total de pixels sera Npix = 12*nside**2
107// m DOIT OBLIGATOIREMENT ETRE UNE PUISSANCE DE 2 (<= 8192)
108//--
109{
110 //printf(" initialisation par defaut SphereGorski \n");
111 if (m<=0 || m> 8192) {
112 cout << "SphereGorski : m hors bornes [0,8192], m= " << m << endl;
113 exit(1);
114 }
115// verifier que m est une puissance de deux
116 int_4 x=m;
117 while (x%2==0) x/=2;
118 if (x!=1) {
119 cout << "SphereGorski : m doit etre une puissance de deux, m= " << m << endl;
120 exit(1);
121 }
122
123 InitNul();
124 Pixelize(m);
125 if (pix2x_==NULL) {
126 pix2x_=new int[1024];
127 pix2y_=new int[1024];
128 mk_pix2xy(pix2x_,pix2y_);
129 }
130 if (x2pix_==NULL) {
131 x2pix_=new int[128];
132 y2pix_=new int[128];
133 mk_xy2pix(x2pix_,y2pix_);
134 }
135}
136
137
138
139
140
141
142//++
143// Titre Destructeur
144//--
145//++
146SphereGorski::~SphereGorski()
147
148//--
149{
150 Clear();
151}
152
153//++
154// Titre Méthodes
155//--
156
157
158
159
160void SphereGorski::Pixelize( int_4 m)
161
162// prépare la pixelisation Gorski (m a la même signification
163// que pour le constructeur)
164//
165//
166//--
167{
168
169 // On memorise les arguments d'appel
170 nSide_ = m;
171
172
173 // Nombre total de pixels sur la sphere entiere
174 nPix_=12*nSide_*nSide_;
175
176// pour le moment les tableaux qui suivent seront ranges dans l'ordre
177// de l'indexation GORSKY "RING"
178// on pourra ulterieurement changer de strategie et tirer profit
179// de la dualite d'indexation GORSKY (RING er NEST) : tout dependra
180// de pourquoi c'est faire
181
182 // Creation et initialisation du vecteur des contenus des pixels
183 mPix_ = new r_8[nPix_];
184 for(int i=0; i<nPix_; i++) mPix_[i] = 0.;
185
186 // solid angle per pixel
187 omeg_=4*Pi/nPix_;
188}
189
190void SphereGorski::InitNul()
191//
192// initialise à zéro les variables de classe
193{
194 nlmax_=0;
195 nmmax_=0;
196 iseed_=0;
197 fwhm_=0.;
198 quadrupole_=0.;
199 sym_cut_deg_=0.;
200 for (int k=0; k<128;k++) powFile_[k]=' ';
201 nSide_=0;
202 nPix_ =0;
203 mPix_ = NULL;
204 pix2x_=NULL;
205 pix2y_=NULL;
206 x2pix_=NULL;
207 y2pix_=NULL;
208 pix2xy_=NULL;
209}
210/* --Methode-- */
211void SphereGorski::Clear()
212
213{
214 if (mPix_) delete[] mPix_;
215 if (pix2x_) delete[] pix2x_;
216 if (pix2y_) delete[] pix2y_;
217 if (x2pix_) delete[] x2pix_;
218 if (y2pix_) delete[] y2pix_;
219 if (pix2xy_) delete pix2xy_;
220}
221//++
222void SphereGorski::WriteSelf(POutPersist& s) const
223
224// créer un fichier image
225//--
226{
227 char strg[256];
228 if (mInfo_) sprintf(strg, "SphereGorski: NSlices=%6d NPix=%9d HasInfo",
229 (int_4)nSide_, (int_4)nPix_);
230 else
231 sprintf(strg, "SphereGorski: nSide=%6d nPix=%9d ",
232 (int_4)nSide_, (int_4)nPix_);
233 s.PutLine(strg);
234 if (mInfo_) mInfo_->Write(s);
235 s.PutI4(nlmax_);
236 s.PutI4(nmmax_);
237 s.PutI4(iseed_);
238 s.PutI4(nSide_);
239 s.PutI4(nPix_);
240 s.PutR4(fwhm_);
241 s.PutR4(quadrupole_);
242 s.PutR4(sym_cut_deg_);
243 s.PutR8(omeg_);
244 s.PutR8s(mPix_, nPix_);
245 s.PutLine(powFile_);
246 return;
247}
248
249/* --Methode-- */
250//++
251void SphereGorski::ReadSelf(PInPersist& s)
252
253// relit un fichier d'image
254//--
255{
256 Clear();
257 char strg[256];
258 s.GetLine(strg, 255);
259// Pour savoir s'il y avait un DVList Info associe
260 bool hadinfo = false;
261 if (strncmp(strg+strlen(strg)-7, "HasInfo", 7) == 0) hadinfo = true;
262 if (hadinfo) { // Lecture eventuelle du DVList Info
263 if (mInfo_ == NULL) mInfo_ = new DVList;
264 mInfo_->Read(s);
265 }
266 s.GetI4(nlmax_);
267 s.GetI4(nmmax_);
268 s.GetI4(iseed_);
269 s.GetI4(nSide_);
270 s.GetI4(nPix_);
271 s.GetR4(fwhm_);
272 s.GetR4(quadrupole_);
273 s.GetR4(sym_cut_deg_);
274 mPix_=new r_8[nPix_];
275 s.GetR8(omeg_);
276 s.GetR8s(mPix_, nPix_);
277 s.GetLine(powFile_, 127);
278
279 return;
280}
281
282
283/* --Methode-- */
284//++
285void SphereGorski::ReadFits(char flnm[])
286
287// remplit la sphere a partir d'un fichier FITS
288//--
289{
290 strip(flnm,'B',' ');
291 if (access(flnm,F_OK) != 0) {perror(flnm); exit(1);}
292 if(!nPix_) {
293 cout << " ReadFits : SphereGorski non pixelisee " << endl;
294 exit(1);
295 }
296 int npixtot=nPix_;
297
298// quand map et mPix_ auront le meme type, map ne sera plus necessaire
299
300 float* map=new float[12*nSide_*nSide_];
301 input_map_(flnm,map,npixtot);
302 // Remplissage de la sphère
303
304 for(int j=0; j<nPix_; j++ ) mPix_[j]=(r_8)map[j];
305 delete [] map;
306
307
308}
309
310/* --Methode-- */
311//++
312void SphereGorski::WriteFits(char flnm[])
313
314// ecrit la sphere sur un fichier FITS
315
316//--
317{
318 strip(flnm,'B',' ');
319 if (access(flnm,F_OK) == 0) {
320 cout << " SphereGorski::WriteFits : le fichier existe deja" << endl;
321 exit(1);
322 }
323 //else cout << "un fichier sera cree " << endl;
324 if(!nPix_) {
325 cout << " WriteFits : SphereGorski non pixelisee " << endl;
326 exit(1);
327 }
328
329
330 char infile[128];
331 for (int k=0; k< 128; k++) infile[k]=powFile_[k];
332
333// quand map et mPix_ auront le meme type, map ne sera plus necessaire
334
335 float* map=new float[12*nSide_*nSide_];
336
337 for(int j=0; j<nPix_; j++ ) map[j]=(float)mPix_[j];
338 int nlmax=nlmax_;
339 int nsmax=nSide_;
340 int nmmax=nmmax_;
341 int iseed=iseed_;
342 float fwhm=fwhm_;
343 float quadrupole=quadrupole_;
344 ecrire_fits_(nlmax,nsmax,nmmax,map,infile,flnm,iseed,fwhm,quadrupole);
345 delete [] map;
346
347}
348
349/* --Methode-- */
350//++
351int_4 SphereGorski::NbPixels() const
352
353// Retourne le nombre de pixels du découpage
354//--
355{
356 return(nPix_);
357}
358
359//++
360int_4 SphereGorski::NbThetaSlices() const
361
362// Retourne le nombre de tranches en theta sur la sphere
363//--
364{return int_4(4*nSide_-1);}
365
366
367//++
368void SphereGorski::GetThetaSlice(int_4 index, r_4& theta, Vector& phi, Vector& value) const
369
370// Retourne, pour la tranche en theta d'indice 'index' le theta
371// correspondant, un vecteur (Peida) contenant les phi des pixels de
372// la tranche, un vecteur (Peida) contenant les valeurs de pixel
373// correspondantes
374//--
375{
376
377cout << "entree GetThetaSlice, couche no " << index << endl;
378 if (index<0 || index > NbThetaSlices()) {
379 // THROW(out_of_range("SphereGorski::PIxVal Pixel index out of range"));
380 cout << " SphereGorski::GetThetaSlice : exceptions a mettre en place" <<endl;
381 THROW(rangeCheckErr);
382 }
383 int_4 iring=0;
384 int lring=0;
385 if (index<nSide_-1) {
386 iring=2*index*(index+1);
387 lring=4*(index+1);
388 }else
389 if (index<3*nSide_) {
390 iring=2*nSide_*(2*index-nSide_+1);
391 lring=4*nSide_;
392 }else
393 {
394 int nc=4*nSide_-1-index;
395 iring=nPix_-2*nc*(nc+1);
396 lring=4*nc;
397 }
398 phi.Realloc(lring);
399 value.Realloc(lring);
400 float T=0.;
401 float F=0.;
402 for (int kk=0; kk<lring;kk++) {
403 PixThetaPhi(kk+iring,T,F);
404 phi(kk)=F;
405 value(kk)=PixVal(kk+iring);
406 }
407 theta=T;
408
409}
410
411
412
413/* --Methode-- */
414//++
415r_8& SphereGorski::PixVal(int_4 k)
416
417// Retourne la valeur du contenu du pixel d'indice "RING" k
418//--
419{
420 if ( (k<0) || (k >= nPix_) ) {
421 // THROW(out_of_range("SphereGorski::PIxVal Pixel index out of range"));
422 cout << " SphereGorski::PIxVal : exceptions a mettre en place" <<endl;
423 THROW(rangeCheckErr);
424 }
425 return(mPix_[k]);
426}
427
428/* --Methode-- */
429//++
430r_8 const& SphereGorski::PixVal(int_4 k) const
431
432// Retourne la valeur du contenu du pixel d'indice "RING" k
433//--
434{
435 if ( (k<0) || (k >= nPix_) ) {
436 //THROW(out_of_range("SphereGorski::PIxVal Pixel index out of range"));
437 cout << " SphereGorski::PIxVal : exceptions a mettre en place" <<endl;
438 THROW(rangeCheckErr);
439 }
440 return(mPix_[k]);
441}
442
443
444//++
445r_8& SphereGorski::PixValNest(int_4 k)
446
447// Retourne la valeur du contenu du pixel d'indice "NESTED" k
448//--
449{
450 if ( (k<0) || (k >= nPix_) ) {
451 //THROW(out_of_range("SphereGorski::PIxValNest Pixel index out of range"));
452 cout << " SphereGorski::PIxValNest : exceptions a mettre en place" <<endl;
453 THROW(rangeCheckErr);
454 }
455 return mPix_[nest2ring(nSide_,k)];
456}
457//++
458
459r_8 const& SphereGorski::PixValNest(int_4 k) const
460
461// Retourne la valeur du contenu du pixel d'indice "NESTED" k
462//--
463{
464 if ( (k<0) || (k >= nPix_) ) {
465 //THROW(out_of_range("SphereGorski::PIxValNest Pixel index out of range"));
466 cout << " SphereGorski::PIxValNest : exceptions a mettre en place" <<endl;
467 THROW(rangeCheckErr);
468 }
469 int_4 pix=nest2ring(nSide_,k);
470 return mPix_[pix];
471}
472
473
474
475/* --Methode-- */
476//++
477int_4 SphereGorski::PixIndexSph(r_4 theta, r_4 phi) const
478
479// Retourne l'indice "RING" du pixel vers lequel pointe une direction
480// définie par ses coordonnées sphériques
481//--
482{
483 return ang2pix_ring(nSide_, double(theta), double(phi));
484}
485
486//++
487int_4 SphereGorski::PixIndexSphNest(r_4 theta, r_4 phi) const
488
489// Retourne l'indice NESTED" du pixel vers lequel pointe une direction
490// définie par ses coordonnées sphériques
491//--
492{
493 return ang2pix_nest(nSide_, double(theta), double(phi));
494}
495
496
497/* --Methode-- */
498//++
499void SphereGorski::PixThetaPhi(int_4 k, r_4& teta, r_4& phi) const
500
501// Retourne les coordonnées (teta,phi) du milieu du pixel d'indice "RING" k
502//--
503{
504 double t;
505 double p;
506 pix2ang_ring(nSide_,k, t, p);
507 teta=(r_4)t;
508 phi=(r_4)p;
509}
510
511//++
512r_8 SphereGorski::PixSolAngle(int_4 dummy) const
513// Pixel Solid angle (steradians)
514// All the pixels have the same solid angle. The dummy argument is
515// for compatibility with eventual pixelizations which would not
516// fulfil this requirement.
517//--
518{
519 return omeg_;
520}
521
522
523//++
524void SphereGorski::PixThetaPhiNest(int_4 k, float& teta, float& phi) const
525
526// Retourne les coordonnées (teta,phi) du milieu du pixel d'indice
527// NESTED k
528//--
529{
530 double t;
531 double p;
532 pix2ang_nest(nSide_, k, t, p);
533 teta=(r_4)t;
534 phi=(r_4)p;
535}
536
537//++
538int_4 SphereGorski::NestToRing(int_4 k)
539
540// conversion d'index NESTD en un index RING
541//
542//--
543{
544 return nest2ring(nSide_,k);
545}
546//++
547int_4 SphereGorski::RingToNest(int_4 k)
548//
549// conversion d'index RING en un index NESTED
550//
551//--
552{
553 return ring2nest(nSide_,k);
554}
555//++
556void SphereGorski::anharm(int nlmax, float sym_c,float* powspec)
557//
558// analyse en harmoniques spheriques des valeurs des pixels de la
559// sphere : appel du module anafast (Gorski-Hivon)
560//
561// "nlmax" : multipole maximum, nlmax <= 2*nsmax (cf. Nyquist)
562//
563// "sym c" : coupure symetrique autour de l'equateur (degres)
564//
565// "powspec" : tableau resultat (a reserver avant l'appel) de C(l)
566// (spectre de puissance)
567//
568//--
569//
570// Pb a resoudre : dans cette classe les valeurs de pixel sont "double"
571// dans anafast le tableau correspondant est "float"
572// pour l'instant on duplique les tableaux, il faudra decider quelque chose
573//
574{
575 if (nlmax > 2*nSide_) {
576 cout << " anharm : nlmax= " << nlmax <<
577 " doit etre <= 2*nsmax (cf. Nyquist), soit :" << 2*nSide_ << endl;
578 exit(1);
579 }
580 else {
581 nlmax_=nlmax;
582 nmmax_=nlmax_;
583 }
584 sym_cut_deg_=sym_c;
585 float* map=new float[nPix_];
586 for (int k=0; k<nPix_; k++) map[k]=(float)mPix_[k];
587 int nsmax=nSide_;
588 int nmmax=nmmax_;
589 double sc=(double)sym_cut_deg_;
590 float* alm_T=new float[2*(nlmax+1)*(nmmax+1)];
591 if (powspec==NULL) {
592
593 cout <<
594 " anharm : un tableau de C_l doit etre alloue avant appel " << endl;
595 exit(1);
596 }
597 float* phas_n=new float[2*(nmmax+1)];
598 float* phas_s=new float[2*(nmmax+1)];
599 float* dataw =new float[16*nsmax];
600 float* work =new float[16*nsmax];
601
602 anafast_(nsmax,nlmax,nmmax,sc,map,alm_T, powspec,phas_n,phas_s,dataw,work);
603 quadrupole_=powspec[2];
604 delete [] map;
605 delete [] alm_T;
606 delete [] phas_n;
607 delete [] phas_s;
608 delete [] dataw;
609 delete [] work;
610
611}
612
613
614//++
615void SphereGorski::synharm(int nlmax, int iseed,float fwhm, float* powspec)
616//
617// synthese des valeurs des pixels de la sphere par l'intermediaire
618// des coefficients en harmoniques spheriques reconstitues apartir d'un
619// spectre en puissance : appel du module synfast (Gorski-Hivon)
620//
621// powspec est un tableau (a fournir) de C(l) (spectre de puissance)
622// Ce tableau doit contenir les valeur de C(l) par ordre
623// SEQUENTIEL de l (de l=0 a l=nlmax). IL SERA MODIFIE PAR L'ALGORITHME
624//
625// nlmax : multipole maximum (nlmax <= 2*nsmax (cf. Nyquist)
626// iseed : initialisation generation aleatoire (negatif, suggere : -1)
627// fwhm : largeur totale a mi-hauteur (minutes d'arc, >=0, ex: 5)
628//--
629// Pb a resoudre : dans cette classe les valeurs de pixel sont "double"
630// dans anafast le tableau correspondant est "float"
631// pour l'instant on duplique les tableaux, il faudra decider quelque chose
632
633{
634 if (nlmax > 2*nSide_) {
635 cout << " sphereGorski::synharm: nlmax= " << nlmax <<
636 " doit etre <= 2*nsmax (cf. Nyquist), soit : " << 2*nSide_ << endl;
637 exit(1);
638 }
639 else {
640 nlmax_=nlmax;
641 nmmax_=nlmax_;
642 quadrupole_=powspec[2];
643 }
644 if (powspec==NULL) {
645
646 cout <<
647 "sphereGorski::synharm : un tableau de C_l doit etre alloue avant appel"
648 << endl;
649 exit(1);
650 }
651 iseed_=iseed;
652 fwhm_ =fwhm;
653 float* map=new float[nPix_];
654 int nsmax=nSide_;
655 int nmmax=nmmax_;
656 float* alm_T=new float[2*(nlmax+1)*(nmmax+1)];
657
658
659// tableaux de travail
660 double* b_north=new double[2*(2*nmmax+1)];
661 double* b_south=new double[2*(2*nmmax+1)];
662 double* bw=new double[2*4*nsmax];
663 double* data=new double[2*4*nsmax];
664 double* work=new double[2*4*nsmax];
665 float* lread=new float[nlmax+1];
666 synfast_(nsmax,nlmax,nmmax,iseed,fwhm, map,alm_T, powspec,
667 b_north,b_south,bw,data,work,lread);
668 for (int k=0; k<nPix_; k++) mPix_[k]=(double)map[k];
669 delete [] map;
670 delete [] alm_T;
671 delete [] b_north;
672 delete [] b_south;
673 delete [] bw;
674 delete [] data;
675 delete [] work;
676 delete [] lread;
677
678}
679
680int SphereGorski::nest2ring(int nside, int ipnest) const {
681 /*
682 c=======================================================================
683 subroutine nest2ring(nside, ipnest, ipring)
684 c=======================================================================
685 c conversion from NESTED to RING pixel number
686 c=======================================================================
687 */
688 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
689 // (16/12/98)
690
691 int npix, npface, face_num, ncap, n_before;
692 int ipf, ip_low, ip_trunc, ip_med, ip_hi;
693 int ix, iy, jrt, jr, nr, jpt, jp, kshift, nl4;
694 int ns_max=8192;
695 int jrll[12]={2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};
696 int jpll[12]={1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};
697
698 if( nside<1 || nside>ns_max ) {
699 cout << "nside out of range" << endl;
700 exit(0);
701 }
702 npix = 12 * nside* nside;
703 if( ipnest<0 || ipnest>npix-1 ) {
704 cout << "ipnest out of range" << endl;
705 exit(0);
706 }
707
708
709 ncap = 2* nside*( nside-1);// ! number of points in the North Polar cap
710 nl4 = 4* nside;
711
712 //c finds the face, and the number in the face
713 npface = nside* nside;
714 //cccccc ip = ipnest - 1 ! in {0,npix-1}
715
716 face_num = ipnest/npface;// ! face number in {0,11}
717 ipf =ipnest%npface;// ! pixel number in the face {0,npface-1}
718 //c finds the x,y on the face (starting from the lowest corner)
719 //c from the pixel number
720 ip_low=ipf%1024; // ! content of the last 10 bits
721 ip_trunc = ipf/1024; // ! truncation of the last 10 bits
722 ip_med=ip_trunc%1024; // ! content of the next 10 bits
723 ip_hi = ip_trunc/1024;// ! content of the high weight 10 bits
724
725 ix = 1024*pix2x_[ip_hi] + 32*pix2x_[ip_med] + pix2x_[ip_low];
726 iy = 1024*pix2y_[ip_hi] + 32*pix2y_[ip_med] + pix2y_[ip_low];
727
728 //c transforms this in (horizontal, vertical) coordinates
729 jrt = ix + iy;// ! 'vertical' in {0,2*(nside-1)}
730 jpt = ix - iy;// ! 'horizontal' in {-nside+1,nside-1}
731
732 //c computes the z coordinate on the sphere
733 // jr = jrll[face_num+1]*nside - jrt - 1;// ! ring number in {1,4*nside-1}
734 jr = jrll[face_num]*nside - jrt - 1;
735 nr = nside;// ! equatorial region (the most frequent)
736 n_before = ncap + nl4 * (jr - nside);
737 kshift=(jr - nside)%2;
738 if( jr<nside ) {//then ! north pole region
739 nr = jr;
740 n_before = 2 * nr * (nr - 1);
741 kshift = 0;
742 }
743 else if( jr>3*nside ) {//then ! south pole region
744 nr = nl4 - jr;
745 n_before = npix - 2 * (nr + 1) * nr;
746 kshift = 0;
747 }
748
749 //c computes the phi coordinate on the sphere, in [0,2Pi]
750 jp = (jpll[face_num]*nr + jpt + 1 + kshift)/2;// ! 'phi' number in the ring in {1,4*nr}
751
752 if( jp>nl4 ) jp = jp - nl4;
753 if( jp<1 ) jp = jp + nl4;
754
755 int aux=n_before + jp - 1;
756 return (n_before + jp - 1);// ! in {0, npix-1}
757
758}
759
760void SphereGorski::mk_pix2xy(int *pix2x,int *pix2y) {
761 /*
762 c=======================================================================
763 subroutine mk_pix2xy
764 c=======================================================================
765 c constructs the array giving x and y in the face from pixel number
766 c for the nested (quad-cube like) ordering of pixels
767 c
768 c the bits corresponding to x and y are interleaved in the pixel number
769 c one breaks up the pixel number by even and odd bits
770 c=======================================================================
771 */
772 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
773 // (16/12/98)
774
775 int kpix, jpix, IX, IY, IP, ID;
776 for (int i=0;i<1023;i++ ) pix2x[i]=0;
777
778 for( kpix=0;kpix<1024;kpix++ ) {
779 jpix = kpix;
780 IX = 0;
781 IY = 0;
782 IP = 1 ;// ! bit position (in x and y)
783 while( jpix!=0 ){// ! go through all the bits
784 ID=jpix%2;// ! bit value (in kpix), goes in ix
785 jpix = jpix/2;
786 IX = ID*IP+IX;
787
788 ID=jpix%2;// ! bit value (in kpix), goes in iy
789 jpix = jpix/2;
790 IY = ID*IP+IY;
791
792 IP = 2*IP;// ! next bit (in x and y)
793 }
794
795 pix2x[kpix] = IX;// ! in 0,31
796 pix2y[kpix] = IY;// ! in 0,31
797 }
798}
799
800int SphereGorski::ring2nest(int nside, int ipring) const {
801 /*
802 c=======================================================================
803 subroutine ring2nest(nside, ipring, ipnest)
804 c=======================================================================
805 c conversion from RING to NESTED pixel number
806 c=======================================================================
807 */
808 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
809 // (16/12/98)
810
811 double fihip, hip;
812 int npix, nl2, nl4, ncap, ip, iphi, ipt, ipring1;
813 int kshift, face_num, nr;
814 int irn, ire, irm, irs, irt, ifm , ifp;
815 int ix, iy, ix_low, ix_hi, iy_low, iy_hi, ipf;
816 int ns_max(8192);
817
818 // coordinate of the lowest corner of each face
819 int jrll[12]={2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};// ! in unit of nside
820 int jpll[12]={1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};//! in unit of nside/2
821
822 if( nside<1 || nside>ns_max ) {
823 cout << "nside out of range" << endl;
824 exit(0);
825 }
826 npix = 12 * nside*nside;
827 if( ipring<0 || ipring>npix-1 ) {
828 cout << "ipring out of range" << endl;
829 exit(0);
830 }
831
832 nl2 = 2*nside;
833 nl4 = 4*nside;
834 npix = 12*nside*nside;// ! total number of points
835 ncap = 2*nside*(nside-1);// ! points in each polar cap, =0 for nside =1
836 ipring1 = ipring + 1;
837
838 //c finds the ring number, the position of the ring and the face number
839 if( ipring1<=ncap ) {//then
840
841 hip = ipring1/2.;
842 fihip = (int)floor ( hip );
843 irn = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;// ! counted from North pole
844 iphi = ipring1 - 2*irn*(irn - 1);
845
846 kshift = 0;
847 nr = irn ;// ! 1/4 of the number of points on the current ring
848 face_num = (iphi-1) / irn;// ! in {0,3}
849 }
850 else if( ipring1<=nl2*(5*nside+1) ) {//then
851
852 ip = ipring1 - ncap - 1;
853 irn = (int)floor( ip / nl4 ) + nside;// ! counted from North pole
854 iphi = (int)fmod(ip,nl4) + 1;
855
856 kshift = (int)fmod(irn+nside,2);// ! 1 if irn+nside is odd, 0 otherwise
857 nr = nside;
858 ire = irn - nside + 1;// ! in {1, 2*nside +1}
859 irm = nl2 + 2 - ire;
860 ifm = (iphi - ire/2 + nside -1) / nside;// ! face boundary
861 ifp = (iphi - irm/2 + nside -1) / nside;
862 if( ifp==ifm ) {//then ! faces 4 to 7
863 face_num = (int)fmod(ifp,4) + 4;
864 }
865 else if( ifp + 1==ifm ) {//then ! (half-)faces 0 to 3
866 face_num = ifp;
867 }
868 else if( ifp - 1==ifm ) {//then ! (half-)faces 8 to 11
869 face_num = ifp + 7;
870 }
871 }
872 else {
873
874 ip = npix - ipring1 + 1;
875 hip = ip/2.;
876 fihip = floor ( hip );
877 irs = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;// ! counted from South pole
878 iphi = 4*irs + 1 - (ip - 2*irs*(irs-1));
879
880 kshift = 0;
881 nr = irs;
882 irn = nl4 - irs;
883 face_num = (iphi-1) / irs + 8;// ! in {8,11}
884 }
885
886 //c finds the (x,y) on the face
887 irt = irn - jrll[face_num]*nside + 1;// ! in {-nside+1,0}
888 ipt = 2*iphi - jpll[face_num]*nr - kshift - 1;// ! in {-nside+1,nside-1}
889
890
891 if( ipt>=nl2 ) ipt = ipt - 8*nside;// ! for the face #4
892
893 ix = (ipt - irt ) / 2;
894 iy = -(ipt + irt ) / 2;
895
896 ix_low = (int)fmod(ix,128);
897 ix_hi = ix/128;
898 iy_low = (int)fmod(iy,128);
899 iy_hi = iy/128;
900 ipf = (x2pix_[ix_hi]+y2pix_[iy_hi]) * (128 * 128)
901 + (x2pix_[ix_low]+y2pix_[iy_low]);
902
903 return (ipf + face_num* nside *nside);// ! in {0, 12*nside**2 - 1}
904}
905
906void SphereGorski::mk_xy2pix(int *x2pix, int *y2pix) {
907 /*
908 c=======================================================================
909 subroutine mk_xy2pix
910 c=======================================================================
911 c sets the array giving the number of the pixel lying in (x,y)
912 c x and y are in {1,128}
913 c the pixel number is in {0,128**2-1}
914 c
915 c if i-1 = sum_p=0 b_p * 2^p
916 c then ix = sum_p=0 b_p * 4^p
917 c iy = 2*ix
918 c ix + iy in {0, 128**2 -1}
919 c=======================================================================
920 */
921 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
922 // (16/12/98)
923
924 int K,IP,I,J,ID;
925
926 for( int i(0);i<127;i++ ) x2pix[i]=0;
927 for( I=1;I<=128;I++ ) {
928 J = I-1;// !pixel numbers
929 K = 0;//
930 IP = 1;//
931 truc : if( J==0 ) {
932 x2pix[I-1] = K;
933 y2pix[I-1] = 2*K;
934 }
935 else {
936 ID = (int)fmod(J,2);
937 J = J/2;
938 K = IP*ID+K;
939 IP = IP*4;
940 goto truc;
941 }
942 }
943 //c endif
944
945}
946
947int SphereGorski::ang2pix_ring(int nside, double theta, double phi) const {
948 /*
949 c=======================================================================
950 c gives the pixel number ipix (RING)
951 c corresponding to angles theta and phi
952 c=======================================================================
953 */
954 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
955 // (16/12/98)
956
957 int nl2, nl4, ncap, npix, jp, jm, ipix1;
958 double z, za, tt, tp, tmp;
959 int ir, ip, kshift;
960
961 double piover2(Pi/2.);
962 double twopi(2.*Pi);
963 double z0(2./3.);
964 int ns_max(8192);
965
966 if( nside<1 || nside>ns_max ) {
967 cout << "nside out of range" << endl;
968 exit(0);
969 }
970
971 if( theta<0. || theta>Pi) {
972 cout << "theta out of range" << endl;
973 exit(0);
974 }
975
976 z = cos(theta);
977 za = fabs(z);
978 if( phi >= twopi) phi = phi - twopi;
979 if (phi < 0.) phi = phi + twopi;
980 tt = phi / piover2;// ! in [0,4)
981
982 nl2 = 2*nside;
983 nl4 = 4*nside;
984 ncap = nl2*(nside-1);// ! number of pixels in the north polar cap
985 npix = 12*nside*nside;
986
987 if( za <= z0 ) {
988
989 jp = (int)floor(nside*(0.5 + tt - z*0.75));// ! index of ascending edge line
990 jm = (int)floor(nside*(0.5 + tt + z*0.75));// ! index of descending edge line
991
992 ir = nside + 1 + jp - jm;// ! in {1,2n+1} (ring number counted from z=2/3)
993 kshift = 0;
994 if (fmod(ir,2)==0.) kshift = 1;// ! kshift=1 if ir even, 0 otherwise
995
996 ip = (int)floor( ( jp+jm - nside + kshift + 1 ) / 2 ) + 1;// ! in {1,4n}
997 if( ip>nl4 ) ip = ip - nl4;
998
999 ipix1 = ncap + nl4*(ir-1) + ip ;
1000 }
1001 else {
1002
1003 tp = tt - floor(tt);// !MOD(tt,1.d0)
1004 tmp = sqrt( 3.*(1. - za) );
1005
1006 jp = (int)floor( nside * tp * tmp );// ! increasing edge line index
1007 jm = (int)floor( nside * (1. - tp) * tmp );// ! decreasing edge line index
1008
1009 ir = jp + jm + 1;// ! ring number counted from the closest pole
1010 ip = (int)floor( tt * ir ) + 1;// ! in {1,4*ir}
1011 if( ip>4*ir ) ip = ip - 4*ir;
1012
1013 ipix1 = 2*ir*(ir-1) + ip;
1014 if( z<=0. ) {
1015 ipix1 = npix - 2*ir*(ir+1) + ip;
1016 }
1017 }
1018 return (ipix1 - 1);// ! in {0, npix-1}
1019
1020}
1021
1022int SphereGorski::ang2pix_nest(int nside, double theta, double phi) const {
1023 /*
1024 c=======================================================================
1025 subroutine ang2pix_nest(nside, theta, phi, ipix)
1026 c=======================================================================
1027 c gives the pixel number ipix (NESTED)
1028 c corresponding to angles theta and phi
1029 c
1030 c the computation is made to the highest resolution available (nside=8192)
1031 c and then degraded to that required (by integer division)
1032 c this doesn't cost more, and it makes sure
1033 c that the treatement of round-off will be consistent
1034 c for every resolution
1035 c=======================================================================
1036 */
1037 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
1038 // (16/12/98)
1039
1040 double z, za, z0, tt, tp, tmp;
1041 int face_num,jp,jm;
1042 int ifp, ifm;
1043 int ix, iy, ix_low, ix_hi, iy_low, iy_hi, ipf, ntt;
1044 double piover2(Pi/2.), twopi(2.*Pi);
1045 int ns_max(8192);
1046
1047 if( nside<1 || nside>ns_max ) {
1048 cout << "nside out of range" << endl;
1049 exit(0);
1050 }
1051 if( theta<0 || theta>Pi ) {
1052 cout << "theta out of range" << endl;
1053 exit(0);
1054 }
1055 z = cos(theta);
1056 za = fabs(z);
1057 z0 = 2./3.;
1058 if( phi>=twopi ) phi = phi - twopi;
1059 if( phi<0. ) phi = phi + twopi;
1060 tt = phi / piover2;// ! in [0,4[
1061 if( za<=z0 ) { // then ! equatorial region
1062
1063 //(the index of edge lines increase when the longitude=phi goes up)
1064 jp = (int)floor(ns_max*(0.5 + tt - z*0.75));// ! ascending edge line index
1065 jm = (int)floor(ns_max*(0.5 + tt + z*0.75));// ! descending edge line index
1066
1067 //c finds the face
1068 ifp = jp / ns_max;// ! in {0,4}
1069 ifm = jm / ns_max;
1070 if( ifp==ifm ) face_num = (int)fmod(ifp,4) + 4; //then ! faces 4 to 7
1071 else if( ifp<ifm ) face_num = (int)fmod(ifp,4); // (half-)faces 0 to 3
1072 else face_num = (int)fmod(ifm,4) + 8;//! (half-)faces 8 to 11
1073
1074 ix = (int)fmod(jm, ns_max);
1075 iy = ns_max - (int)fmod(jp, ns_max) - 1;
1076 }
1077 else { //! polar region, za > 2/3
1078
1079 ntt = (int)floor(tt);
1080 if( ntt>=4 ) ntt = 3;
1081 tp = tt - ntt;
1082 tmp = sqrt( 3.*(1. - za) );// ! in ]0,1]
1083
1084 //(the index of edge lines increase when distance from the closest pole goes up)
1085 jp = (int)floor( ns_max * tp * tmp );// ! line going toward the pole as phi increases
1086 jm = (int)floor( ns_max * (1. - tp) * tmp );// ! that one goes away of the closest pole
1087 jp = (int)min(ns_max-1, jp);// ! for points too close to the boundary
1088 jm = (int)min(ns_max-1, jm);
1089
1090 // finds the face and pixel's (x,y)
1091 if( z>=0 ) {
1092 face_num = ntt;// ! in {0,3}
1093 ix = ns_max - jm - 1;
1094 iy = ns_max - jp - 1;
1095 }
1096 else {
1097 face_num = ntt + 8;// ! in {8,11}
1098 ix = jp;
1099 iy = jm;
1100 }
1101 }
1102
1103 ix_low = (int)fmod(ix,128);
1104 ix_hi = ix/128;
1105 iy_low = (int)fmod(iy,128);
1106 iy_hi = iy/128;
1107 ipf = (x2pix_[ix_hi]+y2pix_[iy_hi]) * (128 * 128)+ (x2pix_[ix_low]+y2pix_[iy_low]);
1108 ipf = ipf / pow(ns_max/nside,2);// ! in {0, nside**2 - 1}
1109 return ( ipf + face_num*pow(nside,2));// ! in {0, 12*nside**2 - 1}
1110}
1111
1112
1113void SphereGorski::pix2ang_ring(int nside, int ipix, double& theta, double& phi) const {
1114 /*
1115 c=======================================================================
1116 c gives theta and phi corresponding to pixel ipix (RING)
1117 c for a parameter nside
1118 c=======================================================================
1119 */
1120 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
1121 // (16/12/98)
1122
1123 int nl2, nl4, npix, ncap, iring, iphi, ip, ipix1;
1124 double fact1, fact2, fodd, hip, fihip;
1125
1126 int ns_max(8192);
1127
1128 if( nside<1 || nside>ns_max ) {
1129 cout << "nside out of range" << endl;
1130 exit(0);
1131 }
1132 npix = 12*nside*nside; // ! total number of points
1133 if( ipix<0 || ipix>npix-1 ) {
1134 cout << "ipix out of range" << endl;
1135 exit(0);
1136 }
1137
1138 ipix1 = ipix + 1; // in {1, npix}
1139 nl2 = 2*nside;
1140 nl4 = 4*nside;
1141 ncap = 2*nside*(nside-1);// ! points in each polar cap, =0 for nside =1
1142 fact1 = 1.5*nside;
1143 fact2 = 3.0*nside*nside;
1144
1145 if( ipix1 <= ncap ) { //! North Polar cap -------------
1146
1147 hip = ipix1/2.;
1148 fihip = floor(hip);
1149 iring = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;// ! counted from North pole
1150 iphi = ipix1 - 2*iring*(iring - 1);
1151
1152 theta = acos( 1. - iring*iring / fact2 );
1153 phi = (1.*iphi - 0.5) * Pi/(2.*iring);
1154 // cout << theta << " " << phi << endl;
1155 }
1156 else if( ipix1 <= nl2*(5*nside+1) ) {//then ! Equatorial region ------
1157
1158 ip = ipix1 - ncap - 1;
1159 iring = (int)floor( ip / nl4 ) + nside;// ! counted from North pole
1160 iphi = (int)fmod(ip,nl4) + 1;
1161
1162 fodd = 0.5 * (1 + fmod((double)(iring+nside),2));// ! 1 if iring+nside is odd, 1/2 otherwise
1163 theta = acos( (nl2 - iring) / fact1 );
1164 phi = (1.*iphi - fodd) * Pi /(2.*nside);
1165 }
1166 else {//! South Polar cap -----------------------------------
1167
1168 ip = npix - ipix1 + 1;
1169 hip = ip/2.;
1170 fihip = 1.*hip;
1171 iring = (int)floor( sqrt( hip - sqrt(fihip) ) ) + 1;// ! counted from South pole
1172 iphi = (int)(4.*iring + 1 - (ip - 2.*iring*(iring-1)));
1173
1174 theta = acos( -1. + iring*iring / fact2 );
1175 phi = (1.*iphi - 0.5) * Pi/(2.*iring);
1176 // cout << theta << " " << phi << endl;
1177 }
1178}
1179
1180void SphereGorski::pix2ang_nest(int nside, int ipix, double& theta, double& phi) const {
1181 /*
1182 c=======================================================================
1183 subroutine pix2ang_nest(nside, ipix, theta, phi)
1184 c=======================================================================
1185 c gives theta and phi corresponding to pixel ipix (NESTED)
1186 c for a parameter nside
1187 c=======================================================================
1188 */
1189 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
1190 // (16/12/98)
1191
1192 int npix, npface, face_num;
1193 int ipf, ip_low, ip_trunc, ip_med, ip_hi;
1194 int ix, iy, jrt, jr, nr, jpt, jp, kshift, nl4;
1195 double z, fn, fact1, fact2;
1196 double piover2(Pi/2.);
1197 int ns_max(8192);
1198
1199
1200 // ! coordinate of the lowest corner of each face
1201 int jrll[12]={2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};//! in unit of nside
1202 int jpll[12]={1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};// ! in unit of nside/2
1203
1204 if( nside<1 || nside>ns_max ) {
1205 cout << "nside out of range" << endl;
1206 exit(0);
1207 }
1208 npix = 12 * nside*nside;
1209 if( ipix<0 || ipix>npix-1 ) {
1210 cout << "ipix out of range" << endl;
1211 exit(0);
1212 }
1213
1214 fn = 1.*nside;
1215 fact1 = 1./(3.*fn*fn);
1216 fact2 = 2./(3.*fn);
1217 nl4 = 4*nside;
1218
1219 //c finds the face, and the number in the face
1220 npface = nside*nside;
1221
1222 face_num = ipix/npface;// ! face number in {0,11}
1223 ipf = (int)fmod(ipix,npface);// ! pixel number in the face {0,npface-1}
1224
1225 //c finds the x,y on the face (starting from the lowest corner)
1226 //c from the pixel number
1227 ip_low = (int)fmod(ipf,1024);// ! content of the last 10 bits
1228 ip_trunc = ipf/1024 ;// ! truncation of the last 10 bits
1229 ip_med = (int)fmod(ip_trunc,1024);// ! content of the next 10 bits
1230 ip_hi = ip_trunc/1024 ;//! content of the high weight 10 bits
1231
1232 ix = 1024*pix2x_[ip_hi] + 32*pix2x_[ip_med] + pix2x_[ip_low];
1233 iy = 1024*pix2y_[ip_hi] + 32*pix2y_[ip_med] + pix2y_[ip_low];
1234
1235 //c transforms this in (horizontal, vertical) coordinates
1236 jrt = ix + iy;// ! 'vertical' in {0,2*(nside-1)}
1237 jpt = ix - iy;// ! 'horizontal' in {-nside+1,nside-1}
1238
1239 //c computes the z coordinate on the sphere
1240 // jr = jrll[face_num+1]*nside - jrt - 1;// ! ring number in {1,4*nside-1}
1241 jr = jrll[face_num]*nside - jrt - 1;
1242 nr = nside;// ! equatorial region (the most frequent)
1243 z = (2*nside-jr)*fact2;
1244 kshift = (int)fmod(jr - nside, 2);
1245 if( jr<nside ) { //then ! north pole region
1246 nr = jr;
1247 z = 1. - nr*nr*fact1;
1248 kshift = 0;
1249 }
1250 else {
1251 if( jr>3*nside ) {// then ! south pole region
1252 nr = nl4 - jr;
1253 z = - 1. + nr*nr*fact1;
1254 kshift = 0;
1255 }
1256 }
1257 theta = acos(z);
1258
1259 //c computes the phi coordinate on the sphere, in [0,2Pi]
1260 // jp = (jpll[face_num+1]*nr + jpt + 1 + kshift)/2;// ! 'phi' number in the ring in {1,4*nr}
1261 jp = (jpll[face_num]*nr + jpt + 1 + kshift)/2;
1262 if( jp>nl4 ) jp = jp - nl4;
1263 if( jp<1 ) jp = jp + nl4;
1264
1265 phi = (jp - (kshift+1)*0.5) * (piover2 / nr);
1266
1267}
1268
1269
1270void SphereGorski::Pix2XY::pix2ang_nest(int nside, int ipix, double& theta, double& phi) const {
1271 /*
1272 c=======================================================================
1273 subroutine pix2ang_nest(nside, ipix, theta, phi)
1274 c=======================================================================
1275 c gives theta and phi corresponding to pixel ipix (NESTED)
1276 c for a parameter nside
1277 c=======================================================================
1278 */
1279 // tranlated from FORTRAN (Gorski) to C, by B. Revenu, revised Guy Le Meur
1280 // (16/12/98)
1281
1282 int npix, npface, face_num;
1283 int ipf, ip_low, ip_trunc, ip_med, ip_hi;
1284 int ix, iy, jrt, jr, nr, jpt, jp, kshift, nl4;
1285 double z, fn, fact1, fact2;
1286 double piover2(Pi/2.);
1287 int ns_max(8192);
1288
1289
1290 // ! coordinate of the lowest corner of each face
1291 int jrll[12]={2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4};//! in unit of nside
1292 int jpll[12]={1, 3, 5, 7, 0, 2, 4, 6, 1, 3, 5, 7};// ! in unit of nside/2
1293
1294 if( nside<1 || nside>ns_max ) {
1295 cout << "nside out of range" << endl;
1296 exit(0);
1297 }
1298 npix = 12 * nside*nside;
1299 if( ipix<0 || ipix>npix-1 ) {
1300 cout << "ipix out of range" << endl;
1301 exit(0);
1302 }
1303
1304 fn = 1.*nside;
1305 fact1 = 1./(3.*fn*fn);
1306 fact2 = 2./(3.*fn);
1307 nl4 = 4*nside;
1308
1309 //c finds the face, and the number in the face
1310 npface = nside*nside;
1311
1312 face_num = ipix/npface;// ! face number in {0,11}
1313 ipf = (int)fmod(ipix,npface);// ! pixel number in the face {0,npface-1}
1314
1315 //c finds the x,y on the face (starting from the lowest corner)
1316 //c from the pixel number
1317 ip_low = (int)fmod(ipf,1024);// ! content of the last 10 bits
1318 ip_trunc = ipf/1024 ;// ! truncation of the last 10 bits
1319 ip_med = (int)fmod(ip_trunc,1024);// ! content of the next 10 bits
1320 ip_hi = ip_trunc/1024 ;//! content of the high weight 10 bits
1321
1322 ix = 1024*pix2x_[ip_hi] + 32*pix2x_[ip_med] + pix2x_[ip_low];
1323 iy = 1024*pix2y_[ip_hi] + 32*pix2y_[ip_med] + pix2y_[ip_low];
1324
1325 //c transforms this in (horizontal, vertical) coordinates
1326 jrt = ix + iy;// ! 'vertical' in {0,2*(nside-1)}
1327 jpt = ix - iy;// ! 'horizontal' in {-nside+1,nside-1}
1328
1329 //c computes the z coordinate on the sphere
1330 // jr = jrll[face_num+1]*nside - jrt - 1;// ! ring number in {1,4*nside-1}
1331 jr = jrll[face_num]*nside - jrt - 1;
1332 nr = nside;// ! equatorial region (the most frequent)
1333 z = (2*nside-jr)*fact2;
1334 kshift = (int)fmod(jr - nside, 2);
1335 if( jr<nside ) { //then ! north pole region
1336 nr = jr;
1337 z = 1. - nr*nr*fact1;
1338 kshift = 0;
1339 }
1340 else {
1341 if( jr>3*nside ) {// then ! south pole region
1342 nr = nl4 - jr;
1343 z = - 1. + nr*nr*fact1;
1344 kshift = 0;
1345 }
1346 }
1347 theta = acos(z);
1348
1349 //c computes the phi coordinate on the sphere, in [0,2Pi]
1350 // jp = (jpll[face_num+1]*nr + jpt + 1 + kshift)/2;// ! 'phi' number in the ring in {1,4*nr}
1351 jp = (jpll[face_num]*nr + jpt + 1 + kshift)/2;
1352 if( jp>nl4 ) jp = jp - nl4;
1353 if( jp<1 ) jp = jp + nl4;
1354
1355 phi = (jp - (kshift+1)*0.5) * (piover2 / nr);
1356
1357}
1358
1359
1360
Note: See TracBrowser for help on using the repository browser.