Logo coherent WaveBurst  
Library Reference Guide
Logo
alm.hh
Go to the documentation of this file.
1 /*
2 # Copyright (C) 2019 Gabriele Vedovato
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 
19 /*! \file alm.hh
20  * Class for storing spherical harmonic coefficients.
21  *
22  * alm wat interface to healpix alm.h (aligned with healpix 3.31)
23  */
24 
25 #ifndef ALM_HH
26 #define ALM_HH
27 
28 #ifndef __CINT__
29 #include "alm.h"
30 #include "xcomplex.h" // starting from healpix 3.30 the complex class is the std::complex !!!
31 #include "alm_powspec_tools.h"
32 #endif
33 #include <complex>
34 #include "TMath.h"
35 
36 using namespace std;
37 
38 namespace wat {
39 
40 
41 /*! Base class for calculating the storage layout of spherical harmonic
42  coefficients. */
43 class Alm_Base
44  {
45  protected:
46  int lmax, mmax, tval;
47 
48  public:
49  /*! Constructs an Alm_Base object with given \a lmax and \a mmax. */
50  Alm_Base (int lmax_=0, int mmax_=0)
51  : lmax(lmax_), mmax(mmax_), tval(2*lmax+1) {}
52 
53  /*! Returns the total number of coefficients for maximum quantum numbers
54  \a l and \a m. */
55  int Num_Alms (int l, int m)
56  {
57  planck_assert(m<=l,"mmax must not be larger than lmax");
58  return ((m+1)*(m+2))/2 + (m+1)*(l-m);
59  }
60 
61  /*! Changes the object's maximum quantum numbers to \a lmax and \a mmax. */
62  void Set (int lmax_, int mmax_)
63  {
64  lmax=lmax_;
65  mmax=mmax_;
66  tval=2*lmax+1;
67  }
68 
69  /*! Returns the maximum \a l */
70  int Lmax() const { return lmax; }
71  /*! Returns the maximum \a m */
72  int Mmax() const { return mmax; }
73 
74  /*! Returns an array index for a given m, from which the index of a_lm
75  can be obtained by adding l. */
76  int index_l0 (int m) const
77  { return ((m*(tval-m))>>1); }
78 
79  /*! Returns the array index of the specified coefficient. */
80  int index (int l, int m) const
81  { return index_l0(m) + l; }
82 
83  /*! Returns \a true, if both objects have the same \a lmax and \a mmax,
84  else \a false. */
85  bool conformable (const Alm_Base &other) const
86  { return ((lmax==other.lmax) && (mmax==other.mmax)); }
87 
88  /*! Swaps the contents of two Alm_Base objects. */
89  void swap (Alm_Base &other);
90  };
91 
92 
93 /*! Class for storing spherical harmonic coefficients. */
94 template<typename T> class Alm_Template: public Alm_Base
95  {
96  private:
97 #ifndef __CINT__
98  arr<T> alm;
99 #endif
100 
101  public:
102  /*! Constructs an Alm_Template object with given \a lmax and \a mmax. */
103  Alm_Template (int lmax_=0, int mmax_=0)
104  : Alm_Base(lmax_,mmax_), alm (Num_Alms(lmax,mmax)) {}
105 
106  /*! Deletes the old coefficients and allocates storage according to
107  \a lmax and \a mmax. */
108  void Set (int lmax_, int mmax_)
109  {
110  Alm_Base::Set(lmax_, mmax_);
111  alm.alloc(Num_Alms(lmax,mmax));
112  }
113 
114  /*! Deallocates the old coefficients and uses the content of \a data
115  for storage. \a data is deallocated during the call. */
116 #ifndef __CINT__
117  void Set (arr<T> &data, int lmax_, int mmax_)
118  {
119  planck_assert (Num_Alms(lmax_,mmax_)==data.size(),"wrong array size");
120  Alm_Base::Set(lmax_, mmax_);
121  alm.transfer(data);
122  }
123 #endif
124 
125  /*! Sets all coefficients to zero. */
126  void SetToZero ()
127  { alm.fill (0); }
128 
129  /*! Multiplies all coefficients by \a factor. */
130  template<typename T2> void Scale (const T2 &factor)
131  { for (tsize m=0; m<alm.size(); ++m) alm[m]*=factor; }
132 #ifndef __CINT__
133  /*! \a a(l,m) *= \a factor[l] for all \a l,m. */
134  template<typename T2> void ScaleL (const arr<T2> &factor)
135  {
136  planck_assert(factor.size()>tsize(lmax),
137  "alm.ScaleL: factor array too short");
138  for (int m=0; m<=mmax; ++m)
139  for (int l=m; l<=lmax; ++l)
140  operator()(l,m)*=factor[l];
141  }
142  /*! \a a(l,m) *= \a factor[m] for all \a l,m. */
143  template<typename T2> void ScaleM (const arr<T2> &factor)
144  {
145  planck_assert(factor.size()>tsize(mmax),
146  "alm.ScaleM: factor array too short");
147  for (int m=0; m<=mmax; ++m)
148  for (int l=m; l<=lmax; ++l)
149  operator()(l,m)*=factor[m];
150  }
151 #endif
152  /*! Adds \a num to a_00. */
153  template<typename T2> void Add (const T2 &num)
154  { alm[0]+=num; }
155 
156  /*! Returns a reference to the specified coefficient. */
157  T &operator() (int l, int m)
158  { return alm[index(l,m)]; }
159  /*! Returns a constant reference to the specified coefficient. */
160  const T &operator() (int l, int m) const
161  { return alm[index(l,m)]; }
162 
163  /*! Returns a pointer for a given m, from which the address of a_lm
164  can be obtained by adding l. */
165  T *mstart (int m)
166  { return &alm[index_l0(m)]; }
167  /*! Returns a pointer for a given m, from which the address of a_lm
168  can be obtained by adding l. */
169  const T *mstart (int m) const
170  { return &alm[index_l0(m)]; }
171 
172  /*! Returns a constant reference to the a_lm data. */
173 #ifndef __CINT__
174  const arr<T> &Alms () const { return alm; }
175 #endif
176 
177  /*! Swaps the contents of two Alm_Template objects. */
178  void swap (Alm_Template &other)
179  {
180  Alm_Base::swap(other);
181  alm.swap(other.alm);
182  }
183 
184  /*! Adds all coefficients from \a other to the own coefficients. */
185  void Add (const Alm_Template &other)
186  {
187  planck_assert (conformable(other), "A_lm are not conformable");
188  for (tsize m=0; m<alm.size(); ++m)
189  alm[m] += other.alm[m];
190  }
191  };
192 
193  class Alm: public Alm_Template<complex<double> >
194  {
195  public:
196  Alm (int lmax_=0, int mmax_=0)
197  : Alm_Template<complex<double> >(lmax_,mmax_) {}
198 
199  //: Copy constructors
200  Alm(const Alm& alm) {*this = alm;}
201 
202 #ifndef __CINT__
203  Alm(const ::Alm<xcomplex<double> >& alm) {*this = alm;}
204 #endif
205 
206  // applies gaussian smoothing to alm
207  void smoothWithGauss(double fwhm) {
208 #ifndef __CINT__
209  double deg2rad = PI/180.;
210  fwhm*=deg2rad;
211 
212  ::Alm<xcomplex<double> > alm(Lmax(),Mmax());
213  for(int l=0;l<=Lmax();l++) {
214  int limit = TMath::Min(l,Mmax());
215  for (int m=0; m<=limit; m++)
216  alm(l,m)=complex<double>((*this)(l,m).real(),(*this)(l,m).imag());
217  }
218  //::Alm<xcomplex<double> > alm = *this;
219  ::smoothWithGauss(alm, fwhm);
220  *this = alm;
221 #endif
222  }
223 
224 
225  // Rotates alm through the Euler angles psi, theta and phi.
226  // The Euler angle convention is right handed, rotations are active.
227  // - psi is the first rotation about the z-axis (vertical)
228  // - then theta about the ORIGINAL (unrotated) y-axis
229  // - then phi about the ORIGINAL (unrotated) z-axis (vertical)
230  // relates Alm */
231  void rotate(double psi, double theta, double phi) {
232 #ifndef __CINT__
233  ::Alm<xcomplex<double> > alm(Lmax(),Mmax());
234  for(int l=0;l<=Lmax();l++) {
235  int limit = TMath::Min(l,Mmax());
236  for (int m=0; m<=limit; m++)
237  alm(l,m)=complex<double>((*this)(l,m).real(),(*this)(l,m).imag());
238  }
239  rotate_alm(alm, psi, theta, phi);
240  *this = alm;
241 #endif
242  }
243 #ifndef __CINT__
244  void operator=(const ::Alm<xcomplex<double> >& alm) {
245  Set(alm.Lmax(),alm.Mmax());
246  for(int l=0;l<=Lmax();l++) {
247  int limit = TMath::Min(l,Mmax());
248  for (int m=0; m<=limit; m++)
249  (*this)(l,m) = complex<double>( alm(l,m).real(), alm(l,m).imag());
250  }
251  }
252 /*
253  ::Alm<xcomplex<double> >& operator=(const Alm& a) {
254  ::Alm<xcomplex<double> > alm(Lmax(),Mmax());
255  for(int l=0;l<=Lmax();l++) {
256  int limit = TMath::Min(l,Mmax());
257  for (int m=0; m<=limit; m++)
258  alm(l,m)=complex<double>((*this)(l,m).real(),(*this)(l,m).imag());
259  }
260  return alm;
261  }
262 */
263 #endif
264 
265  };
266 
267 } // end namespace
268 
269 #endif
void smoothWithGauss(double fwhm)
Definition: alm.hh:207
void ScaleM(const arr< T2 > &factor)
a(l,m) *= factor[m] for all l,m.
Definition: alm.hh:143
int Mmax() const
Returns the maximum m.
Definition: alm.hh:72
int index(int l, int m) const
Returns the array index of the specified coefficient.
Definition: alm.hh:80
int tval
Definition: alm.hh:46
void Add(const Alm_Template &other)
Adds all coefficients from other to the own coefficients.
Definition: alm.hh:185
float factor
void operator=(const ::Alm< xcomplex< double > > &alm)
Definition: alm.hh:244
void Set(int lmax_, int mmax_)
Deletes the old coefficients and allocates storage according to lmax and mmax.
Definition: alm.hh:108
float theta
STL namespace.
int m
Definition: cwb_net.C:28
void Set(arr< T > &data, int lmax_, int mmax_)
Deallocates the old coefficients and uses the content of data for storage.
Definition: alm.hh:117
Definition: alm.hh:38
#define PI
Definition: watfun.hh:32
void Set(int lmax_, int mmax_)
Changes the object&#39;s maximum quantum numbers to lmax and mmax.
Definition: alm.hh:62
void swap(Alm_Template &other)
Swaps the contents of two Alm_Template objects.
Definition: alm.hh:178
void Add(const T2 &num)
Adds num to a_00.
Definition: alm.hh:153
float phi
void SetToZero()
Sets all coefficients to zero.
Definition: alm.hh:126
float psi
int Lmax() const
Returns the maximum l.
Definition: alm.hh:70
Alm(const ::Alm< xcomplex< double > > &alm)
Definition: alm.hh:203
double deg2rad
Alm_Template(int lmax_=0, int mmax_=0)
Constructs an Alm_Template object with given lmax and mmax.
Definition: alm.hh:103
int mmax
Definition: alm.hh:46
arr< T > alm
Definition: alm.hh:98
int l
Alm(int lmax_=0, int mmax_=0)
Definition: alm.hh:196
bool conformable(const Alm_Base &other) const
Returns true, if both objects have the same lmax and mmax, else false.
Definition: alm.hh:85
T * mstart(int m)
Returns a pointer for a given m, from which the address of a_lm can be obtained by adding l...
Definition: alm.hh:165
void ScaleL(const arr< T2 > &factor)
a(l,m) *= factor[l] for all l,m.
Definition: alm.hh:134
Alm_Base(int lmax_=0, int mmax_=0)
Constructs an Alm_Base object with given lmax and mmax.
Definition: alm.hh:50
Base class for calculating the storage layout of spherical harmonic coefficients. ...
Definition: alm.hh:43
Definition: alm.hh:193
double T
Definition: testWDM_4.C:11
void rotate(double psi, double theta, double phi)
Definition: alm.hh:231
int Num_Alms(int l, int m)
Returns the total number of coefficients for maximum quantum numbers l and m.
Definition: alm.hh:55
wavearray< int > index
Class for storing spherical harmonic coefficients.
Definition: alm.hh:94
Alm(const Alm &alm)
Definition: alm.hh:200
const T * mstart(int m) const
Returns a pointer for a given m, from which the address of a_lm can be obtained by adding l...
Definition: alm.hh:169
long int num
const arr< T > & Alms() const
Returns a constant reference to the a_lm data.
Definition: alm.hh:174
double mmax
int index_l0(int m) const
Returns an array index for a given m, from which the index of a_lm can be obtained by adding l...
Definition: alm.hh:76
void Scale(const T2 &factor)
Multiplies all coefficients by factor.
Definition: alm.hh:130
int lmax
Definition: alm.hh:46