Healpix C++  3.83
mask_tools.cc
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 mask_tools.cxx
28  * Copyright (C) 2003-2019 Max-Planck-Society
29  * \author Martin Reinecke
30  */
31 
32 #include <vector>
33 #include <functional>
34 #include "mask_tools.h"
35 #include "lsconstants.h"
36 
37 using namespace std;
38 
39 namespace {
40 
41 double pseudodist(const vec3 &v1, const vec3 &v2)
42  { return (v1-v2).SquaredLength(); }
43 double dist2pseudodist(double pdist)
44  { double tmp=2*sin(0.5*pdist); return tmp*tmp; }
45 double pseudodist2dist(double dist)
46  { return 2*asin(sqrt(dist)*0.5); }
47 
48 } //unnamed namespace
49 
50 Healpix_Map<double> dist2holes(const Healpix_Map<double> &mask, double maxdist)
51  {
52  constexpr int FULLY_IN_MASK=1;
53  constexpr int BORDER=2;
54  int maxord = mask.Order();
55  planck_assert(maxord>=0, "Nside must be a power of 2");
56  vector<int> orders;
57  if (maxord<6)
58  orders={maxord};
59  else
60  orders={(maxord+1)/2, maxord};
61  vector<Healpix_Map<uint8>> omask; // masks at requested orders
62  vector<double> buf; // safety distance at requested orders
63  for (size_t i=0; i<orders.size(); ++i)
64  {
65  omask.emplace_back(orders[i], NEST);
66  buf.push_back(2*omask[i].max_pixrad());
67  }
68  auto &maxmask(omask.back());
69  if (mask.Scheme()==RING)
70 #pragma omp parallel for schedule(static)
71  for (int i=0; i<mask.Npix(); ++i)
72  maxmask[i] = (mask[mask.nest2ring(i)]==0) ? FULLY_IN_MASK : 0;
73  else
74 #pragma omp parallel for schedule(static)
75  for (int i=0; i<mask.Npix(); ++i)
76  maxmask[i] = (mask[i]==0) ? FULLY_IN_MASK : 0;
77  // find border pixels
78 #pragma omp parallel for schedule(dynamic,10000)
79  for (int i=0; i<mask.Npix(); ++i)
80  if (maxmask[i])
81  {
82  fix_arr<int, 8> nb;
83  maxmask.neighbors(i, nb);
84  for (size_t j=0; j<8; ++j)
85  if ((nb[j]!=-1) && (maxmask[nb[j]]==0))
86  {
87  maxmask[i] |= BORDER;
88  break;
89  }
90  }
91 
92  // compute coarsened masks
93  for (int j=omask.size()-2; j>=0; --j)
94  {
95  int fct = 1<<(2*(omask[j+1].Order()-omask[j].Order()));
96 #pragma omp parallel for schedule(static)
97  for (int i=0; i<omask[j].Npix(); ++i)
98  {
99  uint8 And=255, Or=0;
100  for (int k=0; k<fct; ++k)
101  {
102  And &= omask[j+1][fct*i+k];
103  Or |= omask[j+1][fct*i+k];
104  }
105  omask[j][i] = (And&FULLY_IN_MASK) | (Or&BORDER);
106  }
107  }
108 
109  Healpix_Map<double> tdist(maxord, NEST);
110 #pragma omp parallel for schedule(static)
111  for (int i=0; i<mask.Npix(); ++i)
112  tdist[i] = (maxmask[i]>0) ? 0. : maxdist;
113 
114  function<void(int, int, const vector<int> &, const vector<vec3> &)> process;
115  process = [&omask,&tdist,maxord,&process,&buf,maxdist]
116  (int oo, int pix, const vector<int> &submask, const vector<vec3> &subvec)->void
117  {
118  int order=omask[oo].Order();
119  if (submask.empty()) return;
120  if (omask[oo][pix]&FULLY_IN_MASK) return; // pixel lies fully in the mask
121  vec3 v=omask[oo].pix2vec(pix);
122  if (order==maxord)
123  {
124  double pd=10;
125  for (auto subv:subvec)
126  pd=min(pd, pseudodist(subv, v));
127  tdist[pix]=min(maxdist,pseudodist2dist(pd));
128  return;
129  }
130  vector<double> psubdist(submask.size());
131  double pdlim=10;
132  for (size_t i=0; i<submask.size(); ++i)
133  {
134  psubdist[i] = pseudodist(v, subvec[i]);
135  pdlim = min(pdlim,psubdist[i]);
136  }
137 
138  double lim0=dist2pseudodist(min(pi,maxdist+buf[oo]));
139  if (pdlim>lim0) return;
140  double lim1=dist2pseudodist(min(pi,pseudodist2dist(pdlim)+2*buf[oo]));
141  // not yet full order;
142  vector<int> submask2;
143  vector<vec3> subvec2;
144  int fct = 1<<(2*(omask[oo+1].Order()-omask[oo].Order()));
145  for (size_t i=0; i<submask.size(); ++i)
146  if (psubdist[i]<lim1)
147  if (psubdist[i]<lim0)
148  for (int j=submask[i]*fct; j<(submask[i]+1)*fct; ++j)
149  if (omask[oo+1][j]&BORDER)
150  {
151  submask2.push_back(j);
152  subvec2.push_back(omask[oo+1].pix2vec(j));
153  }
154  for (int pix2=pix*fct; pix2<(pix+1)*fct; ++pix2)
155  process(oo+1, pix2, submask2, subvec2);
156  };
157 
158  vector<int> submask;
159  vector<vec3> subvec;
160  for (int i=0; i<omask[0].Npix(); ++i)
161  if (omask[0][i]&BORDER)
162  {
163  submask.push_back(i);
164  subvec.push_back(omask[0].pix2vec(i));
165  }
166 #pragma omp parallel for schedule(dynamic)
167  for (int i=0; i<omask[0].Npix(); ++i)
168  process(0, i, submask, subvec);
169 
170  if (mask.Scheme()==RING) tdist.swap_scheme();
171  return tdist;
172  }
I nest2ring(I pix) const
Healpix_Ordering_Scheme Scheme() const
Definition: healpix_base.h:431
int Order() const
Definition: healpix_base.h:425
I Npix() const
Definition: healpix_base.h:429

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