Healpix C++  3.83
alice3.cc
Go to the documentation of this file.
1 /*
2  * This file is part of Healpix_cxx.
3  *
4  * Healpix_cxx 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 2 of the License, or
7  * (at your option) any later version.
8  *
9  * Healpix_cxx 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 Healpix_cxx; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  *
18  * For more information about HEALPix, see http://healpix.sourceforge.net
19  */
20 
21 /*
22  * Healpix_cxx is being developed at the Max-Planck-Institut fuer Astrophysik
23  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
24  * (DLR).
25  */
26 
27 /*! \file alice3.cc
28  * Copyright (C) 2005-2015 David Larson, Max-Planck-Society
29  * \author David Larson \author Martin Reinecke
30  */
31 
32 #include "alice3.h"
33 #include "lsconstants.h"
34 #include "arr.h"
35 #include "vec3.h"
36 #include "alm.h"
37 #include "alm_healpix_tools.h"
38 #include "healpix_map.h"
39 
40 using namespace std;
41 
42 void PolarizationHolder::getQU(const pointing &p, double &q, double &u) const
43  {
44  fix_arr<int,4> pix;
45  fix_arr<double,4> wgt;
46  Q.get_interpol(p,pix,wgt);
47  q=u=0.f;
48  for (tsize i=0;i<4;++i) {q+=Q[pix[i]]*wgt[i];u+=U[pix[i]]*wgt[i]; }
49  }
50 
51 vec3 PolarizationHolder::getQUDir(const vec3 &loc) const
52  {
53  double q,u;
54  getQU(loc,q,u);
55  vec3 east(1,0,0);
56  if (abs(loc.x)+abs(loc.y) > 0.0)
57  east = vec3(-loc.y,loc.x,0).Norm();
58  vec3 north = crossprod(loc, east);
59  double angle = 0.5*safe_atan2(u,q);
60  return north*(-cos(angle)) + east*sin(angle);
61  }
62 
63 // Return the magnitude of the polarization at some pointing.
64 double PolarizationHolder::getQUMagnitude(const pointing& p) const
65  {
66  double q,u;
67  getQU(p,q,u);
68  return sqrt(q*q + u*u);
69  }
70 
71 /*! Steps from loc in direction dir for an angle theta and updates loc and dir. */
72 void get_step(const PolarizationHolder &ph, vec3 &loc, vec3 &dir, double theta)
73  {
74  loc=(loc+dir*theta).Norm();
75  vec3 tdir=ph.getQUDir(loc);
76  dir = (dotprod(dir,tdir)<0) ? -tdir : tdir;
77  }
78 
79 /*! Performs one Runge-Kutta second order step. Updates loc and dir. */
80 void runge_kutta_step(vec3 &loc, vec3 &dir, const PolarizationHolder &ph,
81  double theta)
82  {
83  // Take a half-theta step
84  vec3 tloc=loc;
85  get_step(ph, tloc, dir, theta/2.0);
86 
87  // Then take a full step with the new direction
88  get_step(ph, loc, dir, theta);
89  }
90 
91 /*! Second order Runge-Kutta integration on the sphere. Given a
92  starting location, a qu map of the sky, and a step size theta, this
93  subroutine returns an array of vectors extending in both
94  directions from the starting location. */
95 void runge_kutta_2(const vec3 &location, const PolarizationHolder &ph,
96  double theta, arr<vec3> &locs)
97  {
98  vec3 first_dir=ph.getQUDir(location);
99  vec3 dir = first_dir;
100  vec3 loc = location;
101 
102  locs[locs.size()/2] = loc;
103 
104  for(int i = 1 + locs.size()/2; i<int(locs.size()); i++)
105  {
106  runge_kutta_step(loc, dir, ph, theta);
107  locs[i] = loc;
108  }
109 
110  dir = -first_dir;
111  loc = location;
112  for(int i = -1 + locs.size()/2; i>=0; i--)
113  {
114  runge_kutta_step(loc, dir, ph, theta);
115  locs[i] = loc;
116  }
117  }
118 
119 /*! Create a sinusoidal kernel. */
120 void make_kernel(arr<double> &kernel)
121  {
122  for(tsize i=0; i<kernel.size(); i++)
123  {
124  double sinx = sin(pi*(i+1) / (kernel.size()+1));
125  kernel[i] = sinx*sinx;
126  }
127  }
128 
129 /*! Convolve an array with a kernel. */
130 void convolve(const arr<double> &kernel, const arr<double> &raw, arr<double> &convolution)
131  {
132  convolution.alloc(raw.size()-kernel.size()+1);
133  for(tsize i=0; i<convolution.size(); i++)
134  {
135  double total=0;
136  for (tsize j=0; j<kernel.size(); j++)
137  total += kernel[j] * raw[i+j];
138  convolution[i] = total;
139  }
140  }
141 
142 /*! Perform line integral convolution on sphere. */
144  const PolarizationHolder &ph, const Healpix_Map<double> &th, int steps,
145  int kernel_steps, double step_radian)
146  {
147  arr<double> kernel(kernel_steps), convolution, rawtexture;
148  make_kernel(kernel);
149  arr<vec3> curve(steps);
150 
151  texture.fill(0.);
152  int num_curves=0;
153 
154  for(int i=0; i<texture.Npix(); i++)
155  {
156  if (hitcount[i]<1.0)
157  {
158  num_curves++;
159  runge_kutta_2(texture.pix2vec(i), ph, step_radian, curve);
160  rawtexture.alloc(curve.size());
161  for (tsize i2=0; i2<curve.size(); i2++)
162  rawtexture[i2] = th.interpolated_value(curve[i2]);
163  convolve(kernel, rawtexture, convolution);
164  for (tsize j=0; j<convolution.size(); j++)
165  {
166  int k = texture.vec2pix(curve[j+kernel.size()/2]);
167  texture[k] += convolution[j];
168  hitcount[k] += 1.;
169  }
170  }
171  }
172  return num_curves;
173  }
174 
175 /*! Expose line integral convolution for external use. */
178  int steps, int kernel_steps, double step_radian, double polmin, double polmax)
179  {
180  PolarizationHolder ph;
181  ph.Q = Q;
182  ph.U = U;
183 
184  hit.fill(0.);
185 
186  for (int i=0; i<mag.Npix(); i++)
187  {
188  pointing p = mag.pix2ang(i);
189 
190  mag[i] = min(polmax,max(polmin,ph.getQUMagnitude(p)));
191  tex[i] = th.interpolated_value(p);
192  }
193 
194  lic_function(hit, tex, ph, th, steps, kernel_steps, step_radian);
195 
196  for (int i=0; i<tex.Npix(); ++i)
197  tex[i]/=hit[i];
198  double tmin,tmax,mmin,mmax;
199  tex.minmax(tmin,tmax);
200  mag.minmax(mmin,mmax);
201  for (int i=0; i<tex.Npix(); ++i)
202  {
203  mag[i]*=(tex[i]-tmin);
204  tex[i]=1.0-(tex[i]-tmin)/(tmax-tmin);
205  }
206  mag.minmax(mmin,mmax);
207  for (int i=0; i<mag.Npix(); ++i)
208  mag[i]=1.0-(mag[i]-mmin)/(mmax-mmin);
209  }
void minmax(T &Min, T &Max) const
Definition: healpix_map.cc:75
vec3 pix2vec(I pix) const
Definition: healpix_base.h:193
I vec2pix(const vec3 &vec) const
Definition: healpix_base.h:162
void lic_main(const Healpix_Map< double > &Q, const Healpix_Map< double > &U, const Healpix_Map< double > &th, Healpix_Map< double > &hit, Healpix_Map< double > &tex, Healpix_Map< double > &mag, int steps, int kernel_steps, double step_radian, double polmin, double polmax)
Definition: alice3.cc:176
void make_kernel(arr< double > &kernel)
Definition: alice3.cc:120
int lic_function(Healpix_Map< double > &hitcount, Healpix_Map< double > &texture, const PolarizationHolder &ph, const Healpix_Map< double > &th, int steps, int kernel_steps, double step_radian)
Definition: alice3.cc:143
void runge_kutta_2(const vec3 &location, const PolarizationHolder &ph, double theta, arr< vec3 > &locs)
Definition: alice3.cc:95
T interpolated_value(const pointing &ptg) const
Definition: healpix_map.h:219
void get_step(const PolarizationHolder &ph, vec3 &loc, vec3 &dir, double theta)
Definition: alice3.cc:72
pointing pix2ang(I pix) const
Definition: healpix_base.h:185
void convolve(const arr< double > &kernel, const arr< double > &raw, arr< double > &convolution)
Definition: alice3.cc:130
void runge_kutta_step(vec3 &loc, vec3 &dir, const PolarizationHolder &ph, double theta)
Definition: alice3.cc:80
I Npix() const
Definition: healpix_base.h:429
void fill(const T &val)
Definition: healpix_map.h:90

Generated on Wed Nov 13 2024 12:18:30 for Healpix C++