alm_healpix_tools.cc

00001 /*
00002  *  This file is part of Healpix_cxx.
00003  *
00004  *  Healpix_cxx is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  Healpix_cxx is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with Healpix_cxx; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  *
00018  *  For more information about HEALPix, see http://healpix.sourceforge.net
00019  */
00020 
00021 /*
00022  *  Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik
00023  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00024  *  (DLR).
00025  */
00026 
00027 /*
00028  *  Copyright (C) 2003-2015 Max-Planck-Society
00029  *  Author: Martin Reinecke
00030  */
00031 
00032 #include "alm_healpix_tools.h"
00033 #include "alm.h"
00034 #include "healpix_map.h"
00035 #include "xcomplex.h"
00036 #include "sharp_cxx.h"
00037 
00038 using namespace std;
00039 
00040 namespace {
00041 
00042 void checkLmaxNside(tsize lmax, tsize nside)
00043   {
00044   if (lmax>4*nside)
00045     cout << "\nWARNING: map analysis requested with lmax>4*nside...\n"
00046             "is this really what you want?\n\n";
00047   }
00048 
00049 }
00050 
00051 template<typename T> void map2alm (const Healpix_Map<T> &map,
00052   Alm<xcomplex<T> > &alm, const arr<double> &weight, bool add_alm)
00053   {
00054   planck_assert (map.Scheme()==RING, "map2alm: map must be in RING scheme");
00055   planck_assert (int(weight.size())>=2*map.Nside(),
00056     "map2alm: weight array has too few entries");
00057   planck_assert (map.fullyDefined(),"map contains undefined pixels");
00058   checkLmaxNside(alm.Lmax(), map.Nside());
00059 
00060   sharp_cxxjob<T> job;
00061   job.set_weighted_Healpix_geometry (map.Nside(),&weight[0]);
00062   job.set_triangular_alm_info (alm.Lmax(), alm.Mmax());
00063   job.map2alm(&map[0], &alm(0,0), add_alm);
00064   }
00065 
00066 template void map2alm (const Healpix_Map<float> &map,
00067   Alm<xcomplex<float> > &alm, const arr<double> &weight,
00068   bool add_alm);
00069 template void map2alm (const Healpix_Map<double> &map,
00070   Alm<xcomplex<double> > &alm, const arr<double> &weight,
00071   bool add_alm);
00072 
00073 template<typename T> void map2alm_iter (const Healpix_Map<T> &map,
00074   Alm<xcomplex<T> > &alm, int num_iter, const arr<double> &weight)
00075   {
00076   map2alm(map,alm,weight);
00077   for (int iter=1; iter<=num_iter; ++iter)
00078     {
00079     Healpix_Map<T> map2(map.Nside(),map.Scheme(),SET_NSIDE);
00080     alm2map(alm,map2);
00081     for (int m=0; m<map.Npix(); ++m)
00082       map2[m] = map[m]-map2[m];
00083     map2alm(map2,alm,weight,true);
00084     }
00085   }
00086 
00087 template void map2alm_iter (const Healpix_Map<float> &map,
00088   Alm<xcomplex<float> > &alm, int num_iter,
00089   const arr<double> &weight);
00090 template void map2alm_iter (const Healpix_Map<double> &map,
00091   Alm<xcomplex<double> > &alm, int num_iter,
00092   const arr<double> &weight);
00093 
00094 template<typename T> void map2alm_iter2 (const Healpix_Map<T> &map,
00095   Alm<xcomplex<T> > &alm, double err_abs, double err_rel)
00096   {
00097   double x_err_abs=1./err_abs, x_err_rel=1./err_rel;
00098   arr<double> wgt(2*map.Nside());
00099   wgt.fill(1);
00100   Healpix_Map<T> map2(map);
00101   alm.SetToZero();
00102   while(true)
00103     {
00104     map2alm(map2,alm,wgt,true);
00105     alm2map(alm,map2);
00106     double errmeasure=0;
00107     for (int m=0; m<map.Npix(); ++m)
00108       {
00109       double err = abs(map[m]-map2[m]);
00110       double rel = (map[m]!=0) ? abs(err/map[m]) : 1e300;
00111       errmeasure = max(errmeasure,min(err*x_err_abs,rel*x_err_rel));
00112       map2[m] = map[m]-map2[m];
00113       }
00114 //cout << errmeasure << endl;
00115     if (errmeasure<1) break;
00116     }
00117   }
00118 
00119 template void map2alm_iter2 (const Healpix_Map<double> &map,
00120   Alm<xcomplex<double> > &alm, double err_abs, double err_rel);
00121 
00122 
00123 template<typename T> void map2alm_spin
00124   (const Healpix_Map<T> &map1, const Healpix_Map<T> &map2,
00125    Alm<xcomplex<T> > &alm1, Alm<xcomplex<T> > &alm2,
00126    int spin, const arr<double> &weight, bool add_alm)
00127   {
00128   planck_assert (map1.Scheme()==RING,
00129     "map2alm_spin: maps must be in RING scheme");
00130   planck_assert (map1.conformable(map2),
00131     "map2alm_spin: maps are not conformable");
00132   planck_assert (alm1.conformable(alm1),
00133     "map2alm_spin: a_lm are not conformable");
00134   planck_assert (int(weight.size())>=2*map1.Nside(),
00135     "map2alm_spin: weight array has too few entries");
00136   planck_assert (map1.fullyDefined()&&map2.fullyDefined(),
00137     "map contains undefined pixels");
00138   checkLmaxNside(alm1.Lmax(), map1.Nside());
00139 
00140   sharp_cxxjob<T> job;
00141   job.set_weighted_Healpix_geometry (map1.Nside(),&weight[0]);
00142   job.set_triangular_alm_info (alm1.Lmax(), alm1.Mmax());
00143   job.map2alm_spin(&map1[0],&map2[0],&alm1(0,0),&alm2(0,0),spin,add_alm);
00144   }
00145 
00146 template void map2alm_spin
00147   (const Healpix_Map<float> &map1, const Healpix_Map<float> &map2,
00148    Alm<xcomplex<float> > &alm1, Alm<xcomplex<float> > &alm2,
00149    int spin, const arr<double> &weight, bool add_alm);
00150 template void map2alm_spin
00151   (const Healpix_Map<double> &map1, const Healpix_Map<double> &map2,
00152    Alm<xcomplex<double> > &alm1, Alm<xcomplex<double> > &alm2,
00153    int spin, const arr<double> &weight, bool add_alm);
00154 
00155 template<typename T> void map2alm_spin_iter2
00156   (const Healpix_Map<T> &map1, const Healpix_Map<T> &map2,
00157    Alm<xcomplex<T> > &alm1, Alm<xcomplex<T> > &alm2,
00158    int spin, double err_abs, double err_rel)
00159   {
00160   arr<double> wgt(2*map1.Nside());
00161   wgt.fill(1);
00162   Healpix_Map<T> map1b(map1), map2b(map2);
00163   alm1.SetToZero(); alm2.SetToZero();
00164   while(true)
00165     {
00166     map2alm_spin(map1b,map2b,alm1,alm2,spin,wgt,true);
00167     alm2map_spin(alm1,alm2,map1b,map2b,spin);
00168     double errmeasure=0;
00169     for (int m=0; m<map1.Npix(); ++m)
00170       {
00171       double err = abs(map1[m]-map1b[m]);
00172       double rel = (map1[m]!=0) ? abs(err/map1[m]) : 1e300;
00173       errmeasure = max(errmeasure,min(err/err_abs,rel/err_rel));
00174       map1b[m] = map1[m]-map1b[m];
00175       err = abs(map2[m]-map2b[m]);
00176       rel = (map2[m]!=0) ? abs(err/map2[m]) : 1e300;
00177       errmeasure = max(errmeasure,min(err/err_abs,rel/err_rel));
00178       map2b[m] = map2[m]-map2b[m];
00179       }
00180 //cout << errmeasure << endl;
00181     if (errmeasure<1) break;
00182     }
00183   }
00184 
00185 template void map2alm_spin_iter2
00186   (const Healpix_Map<double> &map1, const Healpix_Map<double> &map2,
00187    Alm<xcomplex<double> > &alm1, Alm<xcomplex<double> > &alm2,
00188    int spin, double err_abs, double err_rel);
00189 
00190 template<typename T> void map2alm_pol
00191   (const Healpix_Map<T> &mapT,
00192    const Healpix_Map<T> &mapQ,
00193    const Healpix_Map<T> &mapU,
00194    Alm<xcomplex<T> > &almT,
00195    Alm<xcomplex<T> > &almG,
00196    Alm<xcomplex<T> > &almC,
00197    const arr<double> &weight,
00198    bool add_alm)
00199   {
00200   planck_assert (mapT.Scheme()==RING,
00201     "map2alm_pol: maps must be in RING scheme");
00202   planck_assert (mapT.conformable(mapQ) && mapT.conformable(mapU),
00203     "map2alm_pol: maps are not conformable");
00204   planck_assert (almT.conformable(almG) && almT.conformable(almC),
00205     "map2alm_pol: a_lm are not conformable");
00206   planck_assert (int(weight.size())>=2*mapT.Nside(),
00207     "map2alm_pol: weight array has too few entries");
00208   planck_assert (mapT.fullyDefined()&&mapQ.fullyDefined()&&mapU.fullyDefined(),
00209     "map contains undefined pixels");
00210   checkLmaxNside(almT.Lmax(), mapT.Nside());
00211 
00212   sharp_cxxjob<T> job;
00213   job.set_weighted_Healpix_geometry (mapT.Nside(),&weight[0]);
00214   job.set_triangular_alm_info (almT.Lmax(), almT.Mmax());
00215   job.map2alm(&mapT[0], &almT(0,0), add_alm);
00216   job.map2alm_spin(&mapQ[0],&mapU[0],&almG(0,0),&almC(0,0),2,add_alm);
00217   }
00218 
00219 template void map2alm_pol
00220   (const Healpix_Map<float> &mapT,
00221    const Healpix_Map<float> &mapQ,
00222    const Healpix_Map<float> &mapU,
00223    Alm<xcomplex<float> > &almT,
00224    Alm<xcomplex<float> > &almG,
00225    Alm<xcomplex<float> > &almC,
00226    const arr<double> &weight,
00227    bool add_alm);
00228 template void map2alm_pol
00229   (const Healpix_Map<double> &mapT,
00230    const Healpix_Map<double> &mapQ,
00231    const Healpix_Map<double> &mapU,
00232    Alm<xcomplex<double> > &almT,
00233    Alm<xcomplex<double> > &almG,
00234    Alm<xcomplex<double> > &almC,
00235    const arr<double> &weight,
00236    bool add_alm);
00237 
00238 
00239 template<typename T> void map2alm_pol_iter
00240   (const Healpix_Map<T> &mapT,
00241    const Healpix_Map<T> &mapQ,
00242    const Healpix_Map<T> &mapU,
00243    Alm<xcomplex<T> > &almT,
00244    Alm<xcomplex<T> > &almG,
00245    Alm<xcomplex<T> > &almC,
00246    int num_iter,
00247    const arr<double> &weight)
00248   {
00249   map2alm_pol(mapT,mapQ,mapU,almT,almG,almC,weight);
00250   for (int iter=1; iter<=num_iter; ++iter)
00251     {
00252     Healpix_Map<T> mapT2(mapT.Nside(),mapT.Scheme(),SET_NSIDE),
00253                    mapQ2(mapT.Nside(),mapT.Scheme(),SET_NSIDE),
00254                    mapU2(mapT.Nside(),mapT.Scheme(),SET_NSIDE);
00255 
00256     alm2map_pol(almT,almG,almC,mapT2,mapQ2,mapU2);
00257     for (int m=0; m<mapT.Npix(); ++m)
00258       {
00259       mapT2[m] = mapT[m]-mapT2[m];
00260       mapQ2[m] = mapQ[m]-mapQ2[m];
00261       mapU2[m] = mapU[m]-mapU2[m];
00262       }
00263     map2alm_pol(mapT2,mapQ2,mapU2,almT,almG,almC,weight,true);
00264     }
00265   }
00266 
00267 template void map2alm_pol_iter
00268   (const Healpix_Map<float> &mapT,
00269    const Healpix_Map<float> &mapQ,
00270    const Healpix_Map<float> &mapU,
00271    Alm<xcomplex<float> > &almT,
00272    Alm<xcomplex<float> > &almG,
00273    Alm<xcomplex<float> > &almC,
00274    int num_iter,
00275    const arr<double> &weight);
00276 template void map2alm_pol_iter
00277   (const Healpix_Map<double> &mapT,
00278    const Healpix_Map<double> &mapQ,
00279    const Healpix_Map<double> &mapU,
00280    Alm<xcomplex<double> > &almT,
00281    Alm<xcomplex<double> > &almG,
00282    Alm<xcomplex<double> > &almC,
00283    int num_iter,
00284    const arr<double> &weight);
00285 
00286 template<typename T> void map2alm_pol_iter2
00287   (const Healpix_Map<T> &mapT,
00288    const Healpix_Map<T> &mapQ,
00289    const Healpix_Map<T> &mapU,
00290    Alm<xcomplex<T> > &almT,
00291    Alm<xcomplex<T> > &almG,
00292    Alm<xcomplex<T> > &almC,
00293    double err_abs, double err_rel)
00294   {
00295   arr<double> wgt(2*mapT.Nside());
00296   wgt.fill(1);
00297   Healpix_Map<T> mapT2(mapT), mapQ2(mapQ), mapU2(mapU);
00298   almT.SetToZero(); almG.SetToZero(); almC.SetToZero();
00299   while(true)
00300     {
00301     map2alm_pol(mapT2,mapQ2,mapU2,almT,almG,almC,wgt,true);
00302     alm2map_pol(almT,almG,almC,mapT2,mapQ2,mapU2);
00303     double errmeasure=0;
00304     for (int m=0; m<mapT.Npix(); ++m)
00305       {
00306       double err = abs(mapT[m]-mapT2[m]);
00307       double rel = (mapT[m]!=0) ? abs(err/mapT[m]) : 1e300;
00308       errmeasure = max(errmeasure,min(err/err_abs,rel/err_rel));
00309       mapT2[m] = mapT[m]-mapT2[m];
00310       err = abs(mapQ[m]-mapQ2[m]);
00311       rel = (mapQ[m]!=0) ? abs(err/mapQ[m]) : 1e300;
00312       errmeasure = max(errmeasure,min(err/err_abs,rel/err_rel));
00313       mapQ2[m] = mapQ[m]-mapQ2[m];
00314       err = abs(mapU[m]-mapU2[m]);
00315       rel = (mapU[m]!=0) ? abs(err/mapU[m]) : 1e300;
00316       errmeasure = max(errmeasure,min(err/err_abs,rel/err_rel));
00317       mapU2[m] = mapU[m]-mapU2[m];
00318       }
00319 //cout << errmeasure << endl;
00320     if (errmeasure<1) break;
00321     }
00322   }
00323 
00324 template void map2alm_pol_iter2
00325   (const Healpix_Map<double> &mapT,
00326    const Healpix_Map<double> &mapQ,
00327    const Healpix_Map<double> &mapU,
00328    Alm<xcomplex<double> > &almT,
00329    Alm<xcomplex<double> > &almG,
00330    Alm<xcomplex<double> > &almC,
00331    double err_abs, double err_rel);
00332 
00333 
00334 template<typename T> void alm2map (const Alm<xcomplex<T> > &alm,
00335   Healpix_Map<T> &map)
00336   {
00337   planck_assert (map.Scheme()==RING, "alm2map: map must be in RING scheme");
00338 
00339   sharp_cxxjob<T> job;
00340   job.set_Healpix_geometry (map.Nside());
00341   job.set_triangular_alm_info (alm.Lmax(), alm.Mmax());
00342   job.alm2map(&alm(0,0), &map[0], false);
00343   }
00344 
00345 template void alm2map (const Alm<xcomplex<double> > &alm,
00346   Healpix_Map<double> &map);
00347 template void alm2map (const Alm<xcomplex<float> > &alm,
00348   Healpix_Map<float> &map);
00349 
00350 template<typename T> void alm2map_spin
00351   (const Alm<xcomplex<T> > &alm1, const Alm<xcomplex<T> > &alm2,
00352    Healpix_Map<T> &map1, Healpix_Map<T> &map2, int spin)
00353   {
00354   planck_assert (map1.Scheme()==RING,
00355     "alm2map_spin: maps must be in RING scheme");
00356   planck_assert (map1.conformable(map2),
00357     "alm2map_spin: maps are not conformable");
00358   planck_assert (alm1.conformable(alm2),
00359     "alm2map_spin: a_lm are not conformable");
00360 
00361   sharp_cxxjob<T> job;
00362   job.set_Healpix_geometry (map1.Nside());
00363   job.set_triangular_alm_info (alm1.Lmax(), alm1.Mmax());
00364   job.alm2map_spin(&alm1(0,0),&alm2(0,0),&map1[0],&map2[0],spin,false);
00365   }
00366 
00367 template void alm2map_spin
00368   (const Alm<xcomplex<double> > &alm1, const Alm<xcomplex<double> > &alm2,
00369    Healpix_Map<double> &map, Healpix_Map<double> &map2, int spin);
00370 template void alm2map_spin
00371   (const Alm<xcomplex<float> > &alm1, const Alm<xcomplex<float> > &alm2,
00372    Healpix_Map<float> &map, Healpix_Map<float> &map2, int spin);
00373 
00374 
00375 template<typename T> void alm2map_pol
00376   (const Alm<xcomplex<T> > &almT,
00377    const Alm<xcomplex<T> > &almG,
00378    const Alm<xcomplex<T> > &almC,
00379    Healpix_Map<T> &mapT,
00380    Healpix_Map<T> &mapQ,
00381    Healpix_Map<T> &mapU)
00382   {
00383   planck_assert (mapT.Scheme()==RING,
00384     "alm2map_pol: maps must be in RING scheme");
00385   planck_assert (mapT.conformable(mapQ) && mapT.conformable(mapU),
00386     "alm2map_pol: maps are not conformable");
00387   planck_assert (almT.conformable(almG) && almT.conformable(almC),
00388     "alm2map_pol: a_lm are not conformable");
00389 
00390   sharp_cxxjob<T> job;
00391   job.set_Healpix_geometry (mapT.Nside());
00392   job.set_triangular_alm_info (almT.Lmax(), almT.Mmax());
00393   job.alm2map(&almT(0,0), &mapT[0], false);
00394   job.alm2map_spin(&almG(0,0), &almC(0,0), &mapQ[0], &mapU[0], 2, false);
00395   }
00396 
00397 template void alm2map_pol (const Alm<xcomplex<double> > &almT,
00398                            const Alm<xcomplex<double> > &almG,
00399                            const Alm<xcomplex<double> > &almC,
00400                            Healpix_Map<double> &mapT,
00401                            Healpix_Map<double> &mapQ,
00402                            Healpix_Map<double> &mapU);
00403 
00404 template void alm2map_pol (const Alm<xcomplex<float> > &almT,
00405                            const Alm<xcomplex<float> > &almG,
00406                            const Alm<xcomplex<float> > &almC,
00407                            Healpix_Map<float> &mapT,
00408                            Healpix_Map<float> &mapQ,
00409                            Healpix_Map<float> &mapU);
00410 
00411 
00412 template<typename T> void alm2map_der1
00413   (const Alm<xcomplex<T> > &alm,
00414    Healpix_Map<T> &map,
00415    Healpix_Map<T> &mapdth,
00416    Healpix_Map<T> &mapdph)
00417   {
00418   planck_assert (map.Scheme()==RING,
00419     "alm2map_der1: maps must be in RING scheme");
00420   planck_assert (map.conformable(mapdth) && map.conformable(mapdph),
00421     "alm2map_der1: maps are not conformable");
00422 
00423   sharp_cxxjob<T> job;
00424   job.set_Healpix_geometry (map.Nside());
00425   job.set_triangular_alm_info (alm.Lmax(), alm.Mmax());
00426   job.alm2map(&alm(0,0), &map[0], false);
00427   job.alm2map_der1(&alm(0,0), &mapdth[0], &mapdph[0], false);
00428   }
00429 
00430 template void alm2map_der1 (const Alm<xcomplex<double> > &alm,
00431                             Healpix_Map<double> &map,
00432                             Healpix_Map<double> &map_dth,
00433                             Healpix_Map<double> &map_dph);
00434 
00435 template void alm2map_der1 (const Alm<xcomplex<float> > &alm,
00436                             Healpix_Map<float> &map,
00437                             Healpix_Map<float> &map_dth,
00438                             Healpix_Map<float> &map_dph);

Generated on Thu Oct 8 14:48:52 2015 for Healpix C++