Citlali
Loading...
Searching...
No Matches
wiener_filter_omp.h
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4
5#include <Eigen/Core>
6#include <unsupported/Eigen/CXX11/Tensor>
7#include <unsupported/Eigen/Splines>
8
9#include <tula/algorithm/mlinterp/mlinterp.hpp>
10#include <tula/logging.h>
11
14
17
18namespace mapmaking {
19
20class WienerFilter {
21public:
22 // filter template
23 std::string template_type;
24 // normalize filtered map errors
25 bool normalize_error;
26 // uniform weighting
27 bool uniform_weight;
28 // lowpass only
29 bool run_lowpass;
30
31 // if kernel is enabled
33 // number of loops in denom calc
34 int n_loops;
35 // maximum number of loops for denom calc
36 int max_loops = 500;
37 // lower limit to zero out denom values
38 double denom_limit = 1.e-4;
39
40 // kernel map filtering
41 double init_fwhm;
42
43 // fwhms for gaussian tempalte
44 std::map<std::string, double> gaussian_template_fwhm_rad;
45
46 // size of maps
47 int n_rows, n_cols;
48
49 // size of pixel in each dimension
50 double diff_rows, diff_cols;
51
52 // parallelization for ffts
53 std::string parallel_policy;
54
55 // matrices for main calculations from each function
56 Eigen::MatrixXd rr, vvq, denom, nume;
57 // temporarily holds the filtered map
58 Eigen::MatrixXd filtered_map;
59 // filter template
60 Eigen::MatrixXd filter_template;
61
62 // declare fitter class
64
65 template<class MB>
66 void make_gaussian_template(MB &mb, const double);
67
68 template<class MB>
69 void make_airy_template(MB &mb, const double);
70
71 template<class MB, class CD>
72 void make_kernel_template(MB &mb, const int, CD &);
73
74 template<class MB, class CD>
75 void make_template(MB &mb, CD &calib_data, const double gaussian_template_fwhm_rad, const int map_index) {
76 // make sure filtered maps have even dimensions
77 n_rows = 2*(mb.n_rows/2);
78 n_cols = 2*(mb.n_cols/2);
79
80 // x and y spacing should be equal
81 diff_rows = abs(mb.rows_tan_vec(1) - mb.rows_tan_vec(0));
82 diff_cols = abs(mb.cols_tan_vec(1) - mb.cols_tan_vec(0));
83
84 // highpass template
85 if (template_type=="highpass") {
86 SPDLOG_INFO("creating template with highpass only");
88 filter_template(0,0) = 1;
89 }
90
91 // gaussian template
92 else if (template_type=="gaussian") {
93 SPDLOG_INFO("creating gaussian template");
95 }
96
97 // airy template
98 else if (template_type=="airy") {
99 SPDLOG_INFO("creating airy template");
101 }
102
103 // kernel template
104 else {
105 make_kernel_template(mb, map_index, calib_data);
106 }
107 }
108
109 template<class MB>
110 void calc_rr(MB &mb, const int map_index) {
111 if (uniform_weight) {
112 rr = Eigen::MatrixXd::Ones(n_rows,n_cols);
113 }
114 else {
115 rr = sqrt(mb.weight[map_index].array());
116 }
117 }
118
119 template <class MB>
120 void calc_vvq(MB &, const int);
123
124 template<class MB>
125 void run_filter(MB &mb, const int map_index) {
126 SPDLOG_DEBUG("calculating rr");
127 calc_rr(mb, map_index);
128 SPDLOG_DEBUG("rr {}", rr);
129
130 SPDLOG_DEBUG("calculating vvq");
131 calc_vvq(mb, map_index);
132 SPDLOG_DEBUG("vvq {}", vvq);
133
134 SPDLOG_DEBUG("calculating denominator");
136 SPDLOG_DEBUG("denominator {}", denom);
137
138 SPDLOG_DEBUG("calculating numerator");
140 SPDLOG_DEBUG("numerator {}", nume);
141 }
142
143 template<class MB>
144 void filter_maps(MB &mb, const int map_index) {
145 // filter kernel
146 if (run_kernel) {
147 SPDLOG_INFO("filtering kernel");
148 filtered_map = mb.kernel[map_index];
149 uniform_weight = true;
150 run_filter(mb, map_index);
151
152 // divide by filtered weight
153 for (Eigen::Index i=0; i<n_cols; i++) {
154 for (Eigen::Index j=0; j<n_rows; j++) {
155 if (denom(j,i) != 0.0) {
156 mb.kernel[map_index](j,i)=nume(j,i)/denom(j,i);
157 }
158 else {
159 mb.kernel[map_index](j,i)= 0.0;
160 }
161 }
162 }
163
164 SPDLOG_INFO("done");
165 }
166
167 SPDLOG_INFO("filtering signal");
168 // filter signal
169 filtered_map = mb.signal[map_index];
170 uniform_weight = false;
171 // run all filter steps
172 run_filter(mb, map_index);
173
174 // divide by filtered weight
175 for (Eigen::Index i=0; i<n_cols; i++) {
176 for (Eigen::Index j=0; j<n_rows; j ++) {
177 if (denom(j,i) != 0.0) {
178 mb.signal[map_index](j,i) = nume(j,i)/denom(j,i);
179 }
180 else {
181 mb.signal[map_index](j,i)= 0.0;
182 }
183 }
184 }
185
186 SPDLOG_INFO("done");
187
188 // weight map is the denominator
189 mb.weight[map_index] = denom;
190 }
191
192 template<class MB>
193 void filter_noise(MB &mb, const int map_index, const int noise_num) {
194 Eigen::Tensor<double,2> out = mb.noise[map_index].chip(noise_num,2);
195 filtered_map = Eigen::Map<Eigen::MatrixXd>(out.data(),out.dimension(0),out.dimension(1));
197
198 Eigen::MatrixXd ratio(n_rows,n_cols);
199
200 // divide by filtered weight
201 for (Eigen::Index i=0; i<n_cols; i++) {
202 for (Eigen::Index j=0; j<n_rows; j++) {
203 if (denom(j,i) != 0.0) {
204 ratio(j,i) = nume(j,i)/denom(j,i);
205 }
206 else {
207 ratio(j,i)= 0.0;
208 }
209 }
210 }
211
212 // map to tensor
213 Eigen::TensorMap<Eigen::Tensor<double, 2>> in_tensor(ratio.data(), ratio.rows(), ratio.cols());
214 mb.noise[map_index].chip(noise_num,2) = in_tensor;
215 }
216};
217
218template<class MB>
219void WienerFilter::make_gaussian_template(MB &mb, const double gaussian_template_fwhm_rad) {
220 // distance from tangent point
221 Eigen::MatrixXd dist(n_rows,n_cols);
222
223 // calculate distance
224 for (Eigen::Index i=0; i<n_cols; i++) {
225 for (Eigen::Index j=0; j<n_rows; j++) {
226 dist(j,i) = sqrt(pow(mb.rows_tan_vec(j),2) + pow(mb.cols_tan_vec(i),2));
227 }
228 }
229
230 Eigen::Index row_index, col_index;
231
232 // minimum distance
233 double min_dist = dist.minCoeff(&row_index,&col_index);
234 // standard deviation
236
237 // shift indices
238 std::vector<Eigen::Index> shift_indices = {-row_index, -col_index};
239
240 // calculate template
241 filter_template = exp(-0.5 * pow(dist.array() / sigma, 2.));
242 // shift template
244}
245
246template<class MB>
247void WienerFilter::make_airy_template(MB &mb, const double gaussian_template_fwhm_rad) {
248 // distance from tangent point
249 Eigen::MatrixXd dist(n_rows,n_cols);
250
251 // calculate distance
252 for (Eigen::Index i=0; i<n_cols; i++) {
253 for (Eigen::Index j=0; j<n_rows; j++) {
254 dist(j,i) = sqrt(pow(mb.rows_tan_vec(j),2) + pow(mb.cols_tan_vec(i),2));
255 }
256 }
257
258 // to hold minimum distance
259 Eigen::Index row_index, col_index;
260
261 // minimum distance
262 double min_dist = dist.minCoeff(&row_index,&col_index);
263
264 // shift indices
265 std::vector<Eigen::Index> shift_indices = {-row_index, -col_index};
266
267 // calculate template
268 double factor = pi*(1.028/gaussian_template_fwhm_rad);
269
270 // resize template
272
273 // populate template
274 for (Eigen::Index i=0; i<n_cols; i++) {
275 for (Eigen::Index j=0; j<n_rows; j++) {
276 if (dist(j,i)!=0) {
277 filter_template(j,i) = pow(2*boost::math::cyl_bessel_j(1,factor*dist(j,i))/(factor*dist(j,i)),2);
278 }
279 else {
280 filter_template(j,i) = 1;
281 }
282 }
283 }
284
285 // shift template
287}
288
289
290template<class MB, class CD>
291void WienerFilter::make_kernel_template(MB &mb, const int map_index, CD &calib_data) {
292 // collect what we need
293 Eigen::MatrixXd temp_kernel = mb.kernel[map_index];
294
295 // carry out fit to kernel
296 auto [map_params, map_perror, good_fit] =
297 map_fitter.fit_to_gaussian<engine_utils::mapFitter::pointing>(mb.kernel[map_index], mb.weight[map_index], init_fwhm);
298
299 if (!good_fit) {
300 SPDLOG_ERROR("fit to kernel map failed. try setting a small fitting_region_arcsec value.");
301 std::exit(EXIT_FAILURE);
302 }
303
304 // rescale parameters to on-sky units
305 map_params(1) = mb.pixel_size_rad*(map_params(1) - (n_cols)/2);
306 map_params(2) = mb.pixel_size_rad*(map_params(2) - (n_rows)/2);
307
308 Eigen::Index shift_row = -std::round(map_params(2)/diff_rows);
309 Eigen::Index shift_col = -std::round(map_params(1)/diff_cols);
310
311 std::vector<Eigen::Index> shift_indices = {shift_row,shift_col};
312 temp_kernel = engine_utils::shift_2D(temp_kernel, shift_indices);
313
314 // calculate distance
315 Eigen::MatrixXd dist(n_rows,n_cols);
316 for (Eigen::Index i=0; i<n_cols; i++) {
317 for (Eigen::Index j=0; j<n_rows; j++) {
318 dist(j,i) = sqrt(pow(mb.rows_tan_vec(j),2)+pow(mb.cols_tan_vec(i),2));
319 }
320 }
321
322 // pixel closet to tangent point
323 Eigen::Index row_index, col_index;
324 auto min_dist = dist.minCoeff(&row_index,&col_index);
325
326 // create new bins based on diff_rows
327 int n_bins = mb.rows_tan_vec(n_rows-1)/diff_rows;
328 Eigen::VectorXd bin_low = Eigen::VectorXd::LinSpaced(n_bins,0,n_bins-1)*diff_rows;
329
330 Eigen::VectorXd kernel_interp(n_bins-1);
331 kernel_interp.setZero();
332 Eigen::VectorXd dist_interp(n_bins-1);
333 dist_interp.setZero();
334
335 // radial averages
336 for (Eigen::Index i=0; i<n_bins-1; i++) {
337 int c = 0;
338 for (Eigen::Index j=0; j<n_cols; j++) {
339 for (Eigen::Index k=0; k<n_rows; k++) {
340 if (dist(k,j) >= bin_low(i) && dist(k,j) < bin_low(i+1)){
341 c++;
342 kernel_interp(i) += temp_kernel(k,j);
343 dist_interp(i) += dist(k,j);
344 }
345 }
346 }
347 kernel_interp(i) /= c;
348 dist_interp(i) /= c;
349 }
350
351 // now spline interpolate to generate new template array
353
354 // create spline function
355 engine_utils::SplineFunction s(dist_interp, kernel_interp);
356
357 // carry out the interpolation
358 for (Eigen::Index i=0; i<n_cols; i++) {
359 for (Eigen::Index j=0; j<n_rows; j++) {
360 Eigen::Index tj = (j-row_index)%n_rows;
361 Eigen::Index ti = (i-col_index)%n_cols;
362 Eigen::Index shiftj = (tj < 0) ? n_rows+tj : tj;
363 Eigen::Index shifti = (ti < 0) ? n_cols+ti : ti;
364
365 // if within limits
366 if (dist(j,i) <= s.x_max && dist(j,i) >= s.x_min) {
367 filter_template(shiftj,shifti) = s(dist(j,i));
368 }
369 // if above x limit
370 else if (dist(j,i) > s.x_max) {
371 filter_template(shiftj,shifti) = kernel_interp(kernel_interp.size()-1);
372 }
373 // if below x limit
374 else if (dist(j,i) < s.x_min) {
375 filter_template(shiftj,shifti) = kernel_interp(0);
376 }
377 }
378 }
379}
380
381template <class MB>
382void WienerFilter::calc_vvq(MB &mb, const int map_index) {
383 // resize psd_q
384 Eigen::MatrixXd psd_q(n_rows,n_cols);
385
386 // psd and psd freq vectors
387 Eigen::VectorXd psd = mb.noise_psds[map_index];
388 Eigen::VectorXd psd_freq = mb.noise_psd_freqs[map_index];
389
390 // size of psd and psd freq vectors
391 Eigen::Index n_psd = psd.size();
392
393 // modify the psd array to take out lowpassing and highpassing
394 Eigen::Index max_psd_index;
395 double max_psd = psd.maxCoeff(&max_psd_index);
396 double psd_freq_break = 0.;
397 double psd_break = 0.;
398
399 for (Eigen::Index i=0; i<n_psd; i++) {
400 if (psd(i)/max_psd < 1.e-4){
401 psd_freq_break = psd_freq(i);
402 break;
403 }
404 }
405
406 // flatten the response above the lowpass break
407 int count = (psd_freq.array() <= 0.8*psd_freq_break).count();
408
409 if (count > 0) {
410 for (Eigen::Index i=0; i<n_psd; i++) {
411 if (psd_freq_break > 0) {
412 if (psd_freq(i) <= 0.8*psd_freq_break) {
413 psd_break = psd(i);
414 }
415
416 if (psd_freq(i) > 0.8*psd_freq_break) {
417 psd(i) = psd_break;
418 }
419 }
420 }
421 }
422
423 // flatten highpass response if present
424 if (max_psd_index > 0) {
425 psd.head(max_psd_index).setConstant(max_psd);
426 }
427
428 // set up q-space
429 double row_size = n_rows * diff_rows;
430 double col_size = n_cols * diff_cols;
431 double diff_qr = 1. / row_size;
432 double diff_qc = 1. / col_size;
433
434 Eigen::MatrixXd qmap(n_rows,n_cols);
435
436 // shift q_row
437 Eigen::VectorXd q_row = Eigen::VectorXd::LinSpaced(n_rows, -(n_rows - 1) / 2, (n_rows - 1) / 2 + 1) * diff_qr;
438 // shift q_col
439 Eigen::VectorXd q_col = Eigen::VectorXd::LinSpaced(n_cols, -(n_cols - 1) / 2, (n_cols - 1) / 2 + 1) * diff_qc;
440
441 std::vector<Eigen::Index> shift_1 = {-(n_rows-1)/2};
442 engine_utils::shift_1D(q_row, shift_1);
443
444 std::vector<Eigen::Index> shift_2 = {-(n_cols-1)/2};
445 engine_utils::shift_1D(q_col, shift_2);
446
447 for (Eigen::Index i=0; i<n_cols; i++) {
448 for (Eigen::Index j=0; j<n_rows; j++) {
449 qmap(j,i) = sqrt(pow(q_row(j),2)+pow(q_col(i),2));
450 }
451 }
452
453 // set constant if lowpass only
454 if (run_lowpass) {
455 psd_q.setOnes();
456 }
457 else {
458 psd_q.setZero();
459
460 Eigen::Matrix<Eigen::Index, 1, 1> n_psd_matrix;
461 n_psd_matrix << n_psd;
462
463 // interpolate onto psd_q
464 Eigen::Index interp_pts = 1;
465 for (Eigen::Index i=0; i<n_cols; i++) {
466 for (Eigen::Index j=0; j<n_rows; j++) {
467 if ((qmap(j,i) <= psd_freq(psd_freq.size() - 1)) && (qmap(j,i) >= psd_freq(0))) {
468 mlinterp::interp<mlinterp::rnatord>(n_psd_matrix.data(), interp_pts,
469 psd.data(), psd_q.data() + n_rows * i + j,
470 psd_freq.data(), qmap.data() + n_rows * i + j);
471 }
472 else if (qmap(j,i) > psd_freq(n_psd - 1)) {
473 psd_q(j,i) = psd(n_psd- 1);
474 }
475 else if (qmap(j,i) < psd_freq(0)) {
476 psd_q(j,i) = psd(0);
477 }
478 }
479 }
480
481 // find the minimum value of psd
482 auto psd_min = psd.minCoeff();
483
484 for (Eigen::Index i=0; i<n_cols; i++) {
485 for (Eigen::Index j=0; j<n_rows; j++) {
486 if (psd_q(j,i) < psd_min) {
487 psd_q(j,i) = psd_min;
488 }
489 }
490 }
491 }
492
493 // normalize the power spectrum psd_q and place into vvq
494 vvq = psd_q/psd_q.sum();
495}
496
498 // set up fftw
499 fftw_complex *a;
500 fftw_complex *b;
501 fftw_plan pf, pr;
502
503 a = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*n_rows*n_cols);
504 b = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*n_rows*n_cols);
505
506 pf = fftw_plan_dft_2d(n_rows, n_cols, a, b, FFTW_FORWARD, FFTW_ESTIMATE);
507 pr = fftw_plan_dft_2d(n_rows, n_cols, a, b, FFTW_BACKWARD, FFTW_ESTIMATE);
508
509 // set up inputs and outputs
510 Eigen::MatrixXcd in(n_rows,n_cols);
511 Eigen::MatrixXcd out(n_rows,n_cols);
512
513 in.real() = rr.array() * filtered_map.array();
514 in.imag().setZero();
515
516 //out = engine_utils::fft<engine_utils::forward>(in, parallel_policy);
517 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
518
519 in.real() = out.real().array() / vvq.array();
520 in.imag() = out.imag().array() / vvq.array();
521
522 //out = engine_utils::fft<engine_utils::inverse>(in, parallel_policy);
523 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
524
525 in.real() = out.real().array() * rr.array();
526 in.imag().setZero();
527
528 //out = engine_utils::fft<engine_utils::forward>(in, parallel_policy);
529 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
530
531 // copy of out
532 Eigen::MatrixXcd qqq = out;
533
534 in.real() = filter_template;
535 in.imag().setZero();
536
537 //out = engine_utils::fft<engine_utils::forward>(in, parallel_policy);
538 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
539
540 in.real() = out.real().array() * qqq.real().array() + out.imag().array() * qqq.imag().array();
541 in.imag() = -out.imag().array() * qqq.real().array() + out.real().array() * qqq.imag().array();
542
543 //out = engine_utils::fft<engine_utils::inverse>(in, parallel_policy);
544 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
545
546 // populate numerator
547 nume = out.real();
548
549 // destroy fftw plans
550 fftw_destroy_plan(pf);
551 fftw_destroy_plan(pr);
552}
553
555 // set up fftw
556 fftw_complex *a;
557 fftw_complex *b;
558 fftw_plan pf, pr;
559
560 a = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*n_rows*n_cols);
561 b = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*n_rows*n_cols);
562
563 pf = fftw_plan_dft_2d(n_rows, n_cols, a, b, FFTW_FORWARD, FFTW_ESTIMATE);
564 pr = fftw_plan_dft_2d(n_rows, n_cols, a, b, FFTW_BACKWARD, FFTW_ESTIMATE);
565
566 // resize denominator
567 denom.resize(n_rows,n_cols);
568
569 // inputs and outputs to ffts
570 Eigen::MatrixXcd in(n_rows,n_cols);
571 Eigen::MatrixXcd out(n_rows,n_cols);
572
573 // using uniform weights only
574 if (uniform_weight) {
575 in.real() = filter_template;
576 in.imag().setZero();
577
578 //out = engine_utils::fft<engine_utils::forward>(in, parallel_policy);
579 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
580
581 // set denominator
582 denom.setConstant(((out.real().array() * out.real().array() + out.imag().array() * out.imag().array()) / vvq.array()).sum());
583
584 // destroy fftw plans
585 fftw_destroy_plan(pf);
586 fftw_destroy_plan(pr);
587 }
588
589 else {
590 // initialize denominator
591 denom.setZero();
592
593 in.real() = pow(vvq.array(), -1);
594 in.imag().setZero();
595
596 //out = engine_utils::fft<engine_utils::inverse>(in, parallel_policy);
597 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
598
599 // destroy fftw plans
600 fftw_free(a);
601 fftw_free(b);
602
603 fftw_destroy_plan(pf);
604 fftw_destroy_plan(pr);
605
606 Eigen::VectorXd zz2d(n_rows * n_cols);
607
608 // vector of real components of IFFT(1/VVQ)
609 for (Eigen::Index i=0; i<n_cols; i++) {
610 for (Eigen::Index j=0; j<n_rows;j++) {
611 int ii = n_rows*i+j;
612 zz2d(ii) = (out.real()(j,i));
613 }
614 }
615
616 // sort absolute values in ascending order
617 Eigen::VectorXd ss_ord = zz2d.array().abs();
618 auto sorted = engine_utils::sorter(ss_ord);
619
620 // number of iterations for convergence
621 n_loops = n_rows * n_cols / 100;
622
623 // flag for convergence
624 bool done = false;
625
626 tula::logging::progressbar pb(
627 [](const auto &msg) { SPDLOG_INFO("{}", msg); }, 90,
628 "calculating denom");
629
630 Eigen::Index ii;
631 // loop through cols and rows
632 for (Eigen::Index k=0; k<n_cols; k++) {
633 #pragma omp parallel for schedule (dynamic) ordered shared (sorted, n_loops, zz2d, k, done, pb) private (ii) default (none)
634 for (Eigen::Index l=0; l<n_rows; l++) {
635 #pragma omp flush (done)
636 if (!done) {
637 fftw_complex *a,*b;
638 fftw_plan pf, pr;
639 int kk = n_rows*k + l;
640 if (kk >= n_loops) {
641 continue;
642 }
643 #pragma omp critical (wfFFTW)
644 {
645 a = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*n_rows*n_cols);
646 b = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*n_rows*n_cols);
647 pf = fftw_plan_dft_2d(n_rows, n_cols, a, b, FFTW_FORWARD, FFTW_ESTIMATE);
648 pr = fftw_plan_dft_2d(n_rows, n_cols, a, b, FFTW_BACKWARD, FFTW_ESTIMATE);
649 }
650 Eigen::MatrixXcd in(n_rows,n_cols);
651 Eigen::MatrixXcd out(n_rows,n_cols);
652
653 // current element in flattened 1d vector
654 //int kk = n_rows * k + l;
655 // get index in reverse order
656 auto shift_index = std::get<1>(sorted[n_rows * n_cols - kk - 1]);
657
658 double r_shift_n = shift_index / n_rows;
659 double c_shift_n = shift_index % n_rows;
660
661 Eigen::Index shift_1 = -r_shift_n;
662 Eigen::Index shift_2 = -c_shift_n;
663
664 std::vector<Eigen::Index> shift_indices = {shift_1, shift_2};
665
666 Eigen::MatrixXd in_prod = filter_template.array() * engine_utils::shift_2D(filter_template, shift_indices).array();
667
668 in.real() = in_prod;
669 in.imag().setZero();
670
671 //out = engine_utils::fft<engine_utils::forward>(in, parallel_policy);
672 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
673
674 Eigen::MatrixXcd ffdq = out;
675
676 in_prod = rr.array() * engine_utils::shift_2D(rr, shift_indices).array();
677
678 in.real() = in_prod;
679 in.imag().setZero();
680
681 //out = engine_utils::fft<engine_utils::forward>(in, parallel_policy);
682 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
683
684 in.real() = ffdq.real().array() * out.real().array() + ffdq.imag().array() * out.imag().array();
685 in.imag() = -ffdq.imag().array() * out.real().array() + ffdq.real().array() * out.imag().array();
686
687 //out = engine_utils::fft<engine_utils::inverse>(in, parallel_policy);
688 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
689
690 #pragma omp ordered
691 {
692 Eigen::MatrixXd updater = zz2d(shift_index) * out.real()/n_rows/n_cols;
693
694 // update denominator
695 denom = denom + updater;
696
697 #pragma omp critical (wfFFTW)
698 {
699 fftw_free(a);
700 fftw_free(b);
701 fftw_destroy_plan(pf);
702 fftw_destroy_plan(pr);
703 }
704
705 // update progress bar
706 pb.count(n_loops, n_loops / 100);
707
708 // update status
709 if ((kk % 100) == 1) {
710 double max_ratio = -1;
711 double max_denom = denom.maxCoeff();
712
713 for (Eigen::Index i=0; i<n_rows; i++) {
714 for (Eigen::Index j=0; j<n_cols; j++) {
715 if (denom(i, j) > 0.01 * max_denom) {
716 if (abs(updater(i, j) / denom(i, j)) > max_ratio)
717 max_ratio = abs(updater(i, j) / denom(i, j));
718 }
719 }
720 }
721
722 // check if done
723 if (((kk >= max_loops) && (max_ratio < 0.0002)) || max_ratio < 1e-10) {
724 done = true;
725 #pragma omp flush(done)
726 }
727 }
728 }
729 }
730 }
731 }
732 for (Eigen::Index i=0; i<n_rows; i++) {
733 for (Eigen::Index j=0; j<n_cols; j++) {
734 if (denom(i,j) < denom_limit) {
735 denom(i,j) = 0;
736 }
737 }
738 }
739 }
740}
741
742} // namespace mapmaking
Definition utils.h:972
Definition fitting.h:13
auto fit_to_gaussian(Eigen::DenseBase< Derived > &, Eigen::DenseBase< Derived > &, double, double, double)
Definition fitting.h:172
@ pointing
Definition fitting.h:18
Eigen::MatrixXd denom
Definition wiener_filter.h:62
void filter_noise(MB &mb, const int map_index, const int noise_num)
Definition wiener_filter_omp.h:193
std::string template_type
Definition wiener_filter.h:29
void make_airy_template(MB &mb, const double)
std::string parallel_policy
Definition wiener_filter.h:59
void calc_vvq(MB &, const int)
Eigen::MatrixXd rr
Definition wiener_filter.h:62
bool uniform_weight
Definition wiener_filter.h:33
Eigen::MatrixXd vvq
Definition wiener_filter.h:62
bool run_kernel
Definition wiener_filter_omp.h:32
bool normalize_error
Definition wiener_filter.h:31
void make_template(MB &mb, CD &calib_data, const double gaussian_template_fwhm_rad, const int map_index)
Definition wiener_filter_omp.h:75
int max_loops
Definition wiener_filter.h:40
void run_filter(MB &mb, const int map_index)
Definition wiener_filter_omp.h:125
void calc_rr(MB &, const int)
Definition wiener_filter.h:330
double init_fwhm
Definition wiener_filter.h:47
engine_utils::mapFitter map_fitter
Definition wiener_filter.h:69
double denom_limit
Definition wiener_filter.h:42
void make_gaussian_template(MB &mb, const double)
std::map< std::string, double > gaussian_template_fwhm_rad
Definition wiener_filter_omp.h:44
Eigen::MatrixXd filtered_map
Definition wiener_filter.h:64
int n_cols
Definition wiener_filter.h:53
Eigen::MatrixXd filter_template
Definition wiener_filter.h:66
int n_rows
Definition wiener_filter.h:53
Eigen::MatrixXd nume
Definition wiener_filter.h:62
double diff_cols
Definition wiener_filter.h:56
void run_filter(MB &, const int)
Definition wiener_filter.h:730
void filter_maps(MB &mb, const int map_index)
Definition wiener_filter_omp.h:144
int n_loops
Definition wiener_filter.h:38
double diff_rows
Definition wiener_filter.h:56
void calc_rr(MB &mb, const int map_index)
Definition wiener_filter_omp.h:110
void make_kernel_template(MB &mb, const int, CD &)
bool run_lowpass
Definition wiener_filter.h:35
#define FWHM_TO_STD
Definition constants.h:48
constexpr auto pi
Definition constants.h:6
std::vector< std::tuple< double, int > > sorter(Eigen::DenseBase< Derived > &vec)
Definition utils.h:318
auto shift_2D(Eigen::DenseBase< Derived > &in, std::vector< Eigen::Index > shift_indices)
Definition utils.h:882
auto shift_1D(Eigen::DenseBase< Derived > &in, std::vector< Eigen::Index > shift_indices)
Definition utils.h:865
FreqStat psd(const Eigen::DenseBase< DerivedA > &_scan, Eigen::DenseBase< DerivedB > &psd, Eigen::DenseBase< DerivedC > *freqs, double fsmp)
Definition sensitivity.h:152
Definition jinc_mm.h:24