6#include <unsupported/Eigen/CXX11/Tensor>
7#include <unsupported/Eigen/Splines>
9#include <tula/algorithm/mlinterp/mlinterp.hpp>
10#include <tula/logging.h>
71 template<
class MB,
class CD>
74 template<
class MB,
class CD>
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));
86 SPDLOG_INFO(
"creating template with highpass only");
93 SPDLOG_INFO(
"creating gaussian template");
99 SPDLOG_INFO(
"creating airy template");
115 rr = sqrt(mb.weight[map_index].array());
126 SPDLOG_DEBUG(
"calculating rr");
128 SPDLOG_DEBUG(
"rr {}",
rr);
130 SPDLOG_DEBUG(
"calculating vvq");
132 SPDLOG_DEBUG(
"vvq {}",
vvq);
134 SPDLOG_DEBUG(
"calculating denominator");
136 SPDLOG_DEBUG(
"denominator {}",
denom);
138 SPDLOG_DEBUG(
"calculating numerator");
140 SPDLOG_DEBUG(
"numerator {}",
nume);
147 SPDLOG_INFO(
"filtering kernel");
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);
159 mb.kernel[map_index](j,i)= 0.0;
167 SPDLOG_INFO(
"filtering signal");
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);
181 mb.signal[map_index](j,i)= 0.0;
189 mb.weight[map_index] =
denom;
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));
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) {
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;
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));
230 Eigen::Index row_index, col_index;
233 double min_dist = dist.minCoeff(&row_index,&col_index);
238 std::vector<Eigen::Index> shift_indices = {-row_index, -col_index};
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));
259 Eigen::Index row_index, col_index;
262 double min_dist = dist.minCoeff(&row_index,&col_index);
265 std::vector<Eigen::Index> shift_indices = {-row_index, -col_index};
274 for (Eigen::Index i=0; i<
n_cols; i++) {
275 for (Eigen::Index j=0; j<
n_rows; j++) {
277 filter_template(j,i) = pow(2*boost::math::cyl_bessel_j(1,factor*dist(j,i))/(factor*dist(j,i)),2);
290template<
class MB,
class CD>
293 Eigen::MatrixXd temp_kernel = mb.kernel[map_index];
296 auto [map_params, map_perror, good_fit] =
300 SPDLOG_ERROR(
"fit to kernel map failed. try setting a small fitting_region_arcsec value.");
301 std::exit(EXIT_FAILURE);
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);
308 Eigen::Index shift_row = -std::round(map_params(2)/
diff_rows);
309 Eigen::Index shift_col = -std::round(map_params(1)/
diff_cols);
311 std::vector<Eigen::Index> shift_indices = {shift_row,shift_col};
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));
323 Eigen::Index row_index, col_index;
324 auto min_dist = dist.minCoeff(&row_index,&col_index);
328 Eigen::VectorXd bin_low = Eigen::VectorXd::LinSpaced(n_bins,0,n_bins-1)*
diff_rows;
330 Eigen::VectorXd kernel_interp(n_bins-1);
331 kernel_interp.setZero();
332 Eigen::VectorXd dist_interp(n_bins-1);
333 dist_interp.setZero();
336 for (Eigen::Index i=0; i<n_bins-1; i++) {
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)){
342 kernel_interp(i) += temp_kernel(k,j);
343 dist_interp(i) += dist(k,j);
347 kernel_interp(i) /= c;
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;
366 if (dist(j,i) <= s.x_max && dist(j,i) >= s.x_min) {
370 else if (dist(j,i) > s.x_max) {
371 filter_template(shiftj,shifti) = kernel_interp(kernel_interp.size()-1);
374 else if (dist(j,i) < s.x_min) {
387 Eigen::VectorXd
psd = mb.noise_psds[map_index];
388 Eigen::VectorXd psd_freq = mb.noise_psd_freqs[map_index];
391 Eigen::Index n_psd =
psd.size();
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.;
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);
407 int count = (psd_freq.array() <= 0.8*psd_freq_break).count();
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) {
416 if (psd_freq(i) > 0.8*psd_freq_break) {
424 if (max_psd_index > 0) {
425 psd.head(max_psd_index).setConstant(max_psd);
431 double diff_qr = 1. / row_size;
432 double diff_qc = 1. / col_size;
437 Eigen::VectorXd q_row = Eigen::VectorXd::LinSpaced(
n_rows, -(
n_rows - 1) / 2, (
n_rows - 1) / 2 + 1) * diff_qr;
439 Eigen::VectorXd q_col = Eigen::VectorXd::LinSpaced(
n_cols, -(
n_cols - 1) / 2, (
n_cols - 1) / 2 + 1) * diff_qc;
441 std::vector<Eigen::Index> shift_1 = {-(
n_rows-1)/2};
444 std::vector<Eigen::Index> shift_2 = {-(
n_cols-1)/2};
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));
460 Eigen::Matrix<Eigen::Index, 1, 1> n_psd_matrix;
461 n_psd_matrix << n_psd;
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);
472 else if (qmap(j,i) > psd_freq(n_psd - 1)) {
473 psd_q(j,i) =
psd(n_psd- 1);
475 else if (qmap(j,i) < psd_freq(0)) {
482 auto psd_min =
psd.minCoeff();
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;
494 vvq = psd_q/psd_q.sum();
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);
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);
517 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
519 in.real() = out.real().array() /
vvq.array();
520 in.imag() = out.imag().array() /
vvq.array();
523 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
525 in.real() = out.real().array() *
rr.array();
529 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
532 Eigen::MatrixXcd qqq = out;
538 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
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();
544 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
550 fftw_destroy_plan(pf);
551 fftw_destroy_plan(pr);
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);
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);
579 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
582 denom.setConstant(((out.real().array() * out.real().array() + out.imag().array() * out.imag().array()) /
vvq.array()).sum());
585 fftw_destroy_plan(pf);
586 fftw_destroy_plan(pr);
593 in.real() = pow(
vvq.array(), -1);
597 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
603 fftw_destroy_plan(pf);
604 fftw_destroy_plan(pr);
609 for (Eigen::Index i=0; i<
n_cols; i++) {
610 for (Eigen::Index j=0; j<
n_rows;j++) {
612 zz2d(ii) = (out.real()(j,i));
617 Eigen::VectorXd ss_ord = zz2d.array().abs();
626 tula::logging::progressbar pb(
627 [](
const auto &msg) { SPDLOG_INFO(
"{}", msg); }, 90,
628 "calculating denom");
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)
643 #pragma omp critical (wfFFTW)
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);
656 auto shift_index = std::get<1>(sorted[
n_rows *
n_cols - kk - 1]);
658 double r_shift_n = shift_index /
n_rows;
659 double c_shift_n = shift_index %
n_rows;
661 Eigen::Index shift_1 = -r_shift_n;
662 Eigen::Index shift_2 = -c_shift_n;
664 std::vector<Eigen::Index> shift_indices = {shift_1, shift_2};
672 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
674 Eigen::MatrixXcd ffdq = out;
682 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
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();
688 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
692 Eigen::MatrixXd updater = zz2d(shift_index) * out.real()/
n_rows/
n_cols;
697 #pragma omp critical (wfFFTW)
701 fftw_destroy_plan(pf);
702 fftw_destroy_plan(pr);
709 if ((kk % 100) == 1) {
710 double max_ratio = -1;
711 double max_denom =
denom.maxCoeff();
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));
723 if (((kk >=
max_loops) && (max_ratio < 0.0002)) || max_ratio < 1e-10) {
725 #pragma omp flush(done)
732 for (Eigen::Index i=0; i<
n_rows; i++) {
733 for (Eigen::Index j=0; j<
n_cols; j++) {
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