00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
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
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
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);