5#include <boost/math/special_functions/bessel.hpp>
8#include <unsupported/Eigen/CXX11/Tensor>
9#include <unsupported/Eigen/Splines>
11#include <tula/algorithm/mlinterp/mlinterp.hpp>
12#include <tula/logging.h>
26 std::shared_ptr<spdlog::logger>
logger = spdlog::get(
"citlali_logger");
72 template <
typename config_t>
73 void get_config(config_t &, std::vector<std::vector<std::string>> &, std::vector<std::vector<std::string>> &);
84 template<
class MB,
class CD>
88 template<
class MB,
class CD>
125template <
typename config_t>
127 std::vector<std::vector<std::string>> &invalid_keys) {
134 std::tuple{
"post_processing",
"map_filtering",
"type"},{
"wiener_filter",
"convolve",
"destripe"});
137 std::tuple{
"wiener_filter",
"template_type"},{
"kernel",
"gaussian",
"airy",
"highpass"});
140 std::tuple{
"wiener_filter",
"lowpass_only"});
143 std::tuple{
"post_processing",
"map_filtering",
"normalize_errors"});
148 for (
auto const& [arr_index, arr_name] : toltec_io.
array_name_map) {
150 std::tuple{
"wiener_filter",
"template_fwhm_arcsec",arr_name});
165 for (Eigen::Index i=0; i<
n_rows; ++i) {
166 for (Eigen::Index j=0; j<
n_cols; ++j) {
167 dist(i,j) = sqrt(pow(mb.rows_tan_vec(i)+0.5*mb.pixel_size_rad,2) + pow(mb.cols_tan_vec(j)+0.5*mb.pixel_size_rad,2));
172 Eigen::Index row_index, col_index;
175 double min_dist = dist.minCoeff(&row_index,&col_index);
180 std::vector<Eigen::Index> shift_indices = {-row_index, -col_index};
194 for (Eigen::Index i=0; i<
n_rows; ++i) {
195 for (Eigen::Index j=0; j<
n_cols; ++j) {
196 dist(i,j) = sqrt(pow(mb.rows_tan_vec(i)+0.5*mb.pixel_size_rad,2) + pow(mb.cols_tan_vec(j)+0.5*mb.pixel_size_rad,2));
201 Eigen::Index row_index, col_index;
204 double min_dist = dist.minCoeff(&row_index,&col_index);
207 std::vector<Eigen::Index> shift_indices = {-row_index, -col_index};
216 for (Eigen::Index i=0; i<
n_rows; ++i) {
217 for (Eigen::Index j=0; j<
n_cols; ++j) {
219 filter_template(i,j) = pow(2*boost::math::cyl_bessel_j(1,factor*dist(i,j))/(factor*dist(i,j)),2);
231template<
class MB,
class CD>
234 Eigen::MatrixXd temp_kernel = mb.kernel[map_index];
236 double init_row = -99;
237 double init_col = -99;
240 auto [map_params, map_perror, good_fit] =
246 logger->error(
"fit to kernel map failed. try setting a small fitting_region_arcsec value.");
247 std::exit(EXIT_FAILURE);
251 map_params(1) = mb.pixel_size_rad*(map_params(1) - (
n_cols)/2);
252 map_params(2) = mb.pixel_size_rad*(map_params(2) - (
n_rows)/2);
254 Eigen::Index shift_row = -std::round(map_params(2)/
diff_rows);
255 Eigen::Index shift_col = -std::round(map_params(1)/
diff_cols);
257 std::vector<Eigen::Index> shift_indices = {shift_row,shift_col};
263 for (Eigen::Index i=0; i<
n_rows; ++i) {
264 for (Eigen::Index j=0; j<
n_cols; ++j) {
265 dist(i,j) = sqrt(pow(mb.rows_tan_vec(i)+0.5*mb.pixel_size_rad,2) + pow(mb.cols_tan_vec(j)+0.5*mb.pixel_size_rad,2));
270 Eigen::Index row_index, col_index;
271 auto min_dist = dist.minCoeff(&row_index,&col_index);
275 Eigen::VectorXd bin_low = Eigen::VectorXd::LinSpaced(n_bins,0,n_bins-1)*
diff_rows;
277 Eigen::VectorXd kernel_interp(n_bins-1);
278 kernel_interp.setZero();
279 Eigen::VectorXd dist_interp(n_bins-1);
280 dist_interp.setZero();
283 for (Eigen::Index i=0; i<n_bins-1; ++i) {
285 for (Eigen::Index j=0; j<
n_cols; ++j) {
286 for (Eigen::Index k=0; k<
n_rows; ++k) {
287 if (dist(k,j) >= bin_low(i) && dist(k,j) < bin_low(i+1)){
289 kernel_interp(i) += temp_kernel(k,j);
290 dist_interp(i) += dist(k,j);
294 kernel_interp(i) /= c;
305 for (Eigen::Index i=0; i<
n_cols; ++i) {
306 Eigen::Index ti = (i-col_index)%
n_cols;
307 Eigen::Index shifti = (ti < 0) ?
n_cols+ti : ti;
308 for (Eigen::Index j=0; j<
n_rows; ++j) {
309 Eigen::Index tj = (j-row_index)%
n_rows;
310 Eigen::Index shiftj = (tj < 0) ?
n_rows+tj : tj;
313 if (dist(j,i) <= s.
x_max && dist(j,i) >= s.
x_min) {
317 else if (dist(j,i) > s.
x_max) {
318 filter_template(shiftj,shifti) = kernel_interp(kernel_interp.size()-1);
321 else if (dist(j,i) < s.
x_min) {
335 rr = sqrt(mb.weight[map_index].array());
350 Eigen::VectorXd psd = mb.noise_psds[map_index];
351 Eigen::VectorXd psd_freq = mb.noise_psd_freqs[map_index];
354 Eigen::Index n_psd = psd.size();
357 Eigen::Index max_psd_index;
358 double max_psd = psd.maxCoeff(&max_psd_index);
359 double psd_freq_break = 0.;
360 double psd_break = 0.;
362 for (Eigen::Index i=0; i<n_psd; ++i) {
363 if (psd(i)/max_psd <
psd_lim) {
364 psd_freq_break = psd_freq(i);
370 int count = (psd_freq.array() <= 0.8*psd_freq_break).count();
374 for (Eigen::Index i=0; i<n_psd; ++i) {
375 if (psd_freq_break > 0) {
376 if (psd_freq(i) <= 0.8*psd_freq_break) {
380 if (psd_freq(i) > 0.8*psd_freq_break) {
388 if (max_psd_index > 0) {
389 psd.head(max_psd_index).setConstant(max_psd);
399 Eigen::VectorXd q_row = Eigen::VectorXd::LinSpaced(
n_rows, -
n_rows / 2,
n_rows / 2) * diff_qr;
401 Eigen::VectorXd q_col = Eigen::VectorXd::LinSpaced(
n_cols, -
n_cols / 2,
n_cols / 2) * diff_qc;
404 std::vector<Eigen::Index> shift_1 = {-
n_rows/2};
407 std::vector<Eigen::Index> shift_2 = {
n_cols/2};
410 for (Eigen::Index i=0; i<
n_rows; ++i) {
411 for (Eigen::Index j=0; j<
n_cols; ++j) {
412 q_map(i,j) = sqrt(pow(q_row(i),2)+pow(q_col(j),2));
419 Eigen::Matrix<Eigen::Index, 1, 1> n_psd_matrix;
420 n_psd_matrix << n_psd;
423 Eigen::Index interp_pts = 1;
424 for (Eigen::Index i=0; i<
n_cols; ++i) {
425 for (Eigen::Index j=0; j<
n_rows; ++j) {
426 if ((q_map(j,i) <= psd_freq(psd_freq.size() - 1)) && (q_map(j,i) >= psd_freq(0))) {
427 mlinterp::interp<mlinterp::rnatord>(n_psd_matrix.data(), interp_pts,
428 psd.data(), psd_q.data() +
n_rows * i + j,
429 psd_freq.data(), q_map.data() +
n_rows * i + j);
431 else if (q_map(j,i) > psd_freq(n_psd - 1)) {
432 psd_q(j,i) = psd(n_psd- 1);
434 else if (q_map(j,i) < psd_freq(0)) {
441 auto psd_min = psd.minCoeff();
443 for (Eigen::Index i=0; i<
n_rows; ++i) {
444 for (Eigen::Index j=0; j<
n_cols; ++j) {
445 if (psd_q(i,j) < psd_min) {
446 psd_q(i,j) = psd_min;
454 vvq = psd_q/psd_q.sum();
464 a = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex)*
n_rows*
n_cols);
465 b = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex)*
n_rows*
n_cols);
468 pf = fftw_plan_dft_2d(
n_rows,
n_cols, a, b, FFTW_FORWARD, FFTW_ESTIMATE);
469 pr = fftw_plan_dft_2d(
n_rows,
n_cols, a, b, FFTW_BACKWARD, FFTW_ESTIMATE);
478 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
481 in.real() = out.real().array() /
vvq.array();
482 in.imag() = out.imag().array() /
vvq.array();
485 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
488 in.real() = out.real().array() *
rr.array();
492 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
495 Eigen::MatrixXcd Q = out;
502 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
505 in.real() = out.real().array() * Q.real().array() + out.imag().array() * Q.imag().array();
506 in.imag() = -out.imag().array() * Q.real().array() + out.real().array() * Q.imag().array();
509 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
519 fftw_destroy_plan(pf);
520 fftw_destroy_plan(pr);
530 a = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex)*
n_rows*
n_cols);
531 b = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex)*
n_rows*
n_cols);
534 pf = fftw_plan_dft_2d(
n_rows,
n_cols, a, b, FFTW_FORWARD, FFTW_ESTIMATE);
535 pr = fftw_plan_dft_2d(
n_rows,
n_cols, a, b, FFTW_BACKWARD, FFTW_ESTIMATE);
549 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
552 denom.setConstant(((out.real().array() * out.real().array() + out.imag().array() * out.imag().array()) /
vvq.array()).sum());
559 in.real() = pow(
vvq.array(),-1);
563 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
569 for (Eigen::Index i=0; i<
n_cols; ++i) {
570 for (Eigen::Index j=0; j<
n_rows;++j) {
572 Z(ii) = (out.real()(j,i));
577 Eigen::VectorXd Z_abs = Z.array().abs();
586 tula::logging::progressbar pb(
587 [&](
const auto &msg) {
logger->info(
"{}", msg); }, 90,
588 "calculating denom");
591 for (Eigen::Index k=0; k<
n_cols; ++k) {
592 for (Eigen::Index l=0; l<
n_rows; ++l) {
600 auto shift_index = std::get<1>(Z_indices_sorted[
n_rows *
n_cols - kk - 1]);
603 std::vector<Eigen::Index> shift_indices = {
static_cast<Eigen::Index
>(-shift_index %
n_rows),
604 static_cast<Eigen::Index
>(-shift_index /
n_rows)};
614 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
617 Eigen::MatrixXcd ffdq = out;
627 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
630 in.real() = ffdq.real().array() * out.real().array() + ffdq.imag().array() * out.imag().array();
631 in.imag() = -ffdq.imag().array() * out.real().array() + ffdq.real().array() * out.imag().array();
634 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
637 Eigen::MatrixXd delta_denom = Z(shift_index) * out.real()/
n_rows/
n_cols;
643 if ((kk % 100) == 1) {
644 double max_ratio = -1;
646 double max_denom = 0.01 *
denom.maxCoeff();
649 for (Eigen::Index i=0; i<
n_rows; ++i) {
650 for (Eigen::Index j=0; j<
n_cols; ++j) {
652 if (
denom(i,j) > max_denom) {
654 auto ratio = max_ratio = abs(delta_denom(i,j) /
denom(i,j));
656 if (ratio > max_ratio) {
663 logger->info(
"{} iteration(s) complete. denom ratio = {}", kk,
static_cast<float>(max_ratio));
666 if (((kk >=
max_loops) && (max_ratio < 0.0002)) || max_ratio < 1e-10) {
675 for (Eigen::Index i=0; i<
n_rows; ++i) {
676 for (Eigen::Index j=0; j<
n_cols; ++j) {
689 fftw_destroy_plan(pf);
690 fftw_destroy_plan(pr);
693template<
class MB,
class CD>
700 diff_rows = abs(mb.rows_tan_vec(1) - mb.rows_tan_vec(0));
701 diff_cols = abs(mb.cols_tan_vec(1) - mb.cols_tan_vec(0));
705 logger->info(
"creating highpass template");
712 logger->info(
"creating gaussian template");
718 logger->info(
"creating airy template");
724 logger->info(
"creating template from kernel map");
732 logger->debug(
"calculating rr");
737 logger->debug(
"calculating vvq");
742 logger->debug(
"calculating denominator");
747 logger->debug(
"calculating numerator");
759 a = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex)*
n_rows*
n_cols);
760 b = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex)*
n_rows*
n_cols);
763 pf = fftw_plan_dft_2d(
n_rows,
n_cols, a, b, FFTW_FORWARD, FFTW_ESTIMATE);
764 pr = fftw_plan_dft_2d(
n_rows,
n_cols, a, b, FFTW_BACKWARD, FFTW_ESTIMATE);
775 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
778 Eigen::MatrixXcd fft_filter = out;
783 out = engine_utils::fft2<engine_utils::forward>(in, pf, a, b);
787 in.real() = out.real().array() * fft_filter.real().array() - out.imag().array() * fft_filter.imag().array();
788 in.imag() = out.imag().array() * fft_filter.real().array() + out.real().array() * fft_filter.imag().array();
790 out = engine_utils::fft2<engine_utils::inverse>(in, pr, a, b);
801 fftw_destroy_plan(pf);
802 fftw_destroy_plan(pr);
808 fftw_complex *in, *out;
809 fftw_plan p_forward, p_backward;
811 in = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex) *
n_rows *
n_cols);
812 out = (fftw_complex*) fftw_malloc(
sizeof(fftw_complex) *
n_rows *
n_cols);
815 p_forward = fftw_plan_dft_2d(
n_rows,
n_cols, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
816 p_backward = fftw_plan_dft_2d(
n_rows,
n_cols, out, in, FFTW_BACKWARD, FFTW_ESTIMATE);
819 for (
int i = 0; i <
n_rows; ++i) {
820 for (
int j = 0; j <
n_cols; ++j) {
822 in[i *
n_cols + j][1] = 0.0;
827 fftw_execute(p_forward);
830 double max_magnitude = 0.0;
832 double magnitude = std::sqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1]);
833 if (magnitude > max_magnitude) {
834 max_magnitude = magnitude;
839 double threshold = threshold_factor * max_magnitude;
842 double magnitude = std::sqrt(out[i][0] * out[i][0] + out[i][1] * out[i][1]);
843 if (magnitude < threshold) {
850 logger->info(
"number of pixels below threshold {}", n_pixels);
853 fftw_execute(p_backward);
856 for (
int i = 0; i <
n_rows; ++i) {
857 for (
int j = 0; j <
n_cols; ++j) {
863 fftw_destroy_plan(p_forward);
864 fftw_destroy_plan(p_backward);
878 logger->info(
"filtering kernel");
890 for (Eigen::Index i=0; i<
n_rows; ++i) {
891 for (Eigen::Index j=0; j<
n_cols; ++j) {
892 if (
denom(i,j) != 0.0) {
893 mb.kernel[map_index](i,j) =
nume(i,j)/
denom(i,j);
896 mb.kernel[map_index](i,j) = 0.0;
901 logger->info(
"kernel filtering done");
903 logger->info(
"filtering signal");
915 for (Eigen::Index i=0; i<
n_rows; ++i) {
916 for (Eigen::Index j=0; j<
n_cols; ++j) {
917 if (
denom(i,j) != 0.0) {
918 mb.signal[map_index](i,j) =
nume(i,j)/
denom(i,j);
921 mb.signal[map_index](i,j) = 0.0;
927 mb.weight[map_index] =
denom;
932 mb.weight[map_index] =
nume;
935 logger->info(
"signal/weight map filtering done");
941 filtered_map = Eigen::Map<Eigen::MatrixXd>(mb.noise[map_index].data() + noise_num * mb.n_rows * mb.n_cols,
942 mb.n_rows, mb.n_cols);
955 for (Eigen::Index i=0; i<
n_rows; ++i) {
956 for (Eigen::Index j=0; j<
n_cols; ++j) {
957 if (
denom(i,j) != 0.0) {
967 Eigen::TensorMap<Eigen::Tensor<double, 2>> in_tensor(ratio.data(), ratio.rows(), ratio.cols());
968 mb.noise[map_index].chip(noise_num,2) = in_tensor;
double x_min
Definition utils.h:974
double x_max
Definition utils.h:975
auto fit_to_gaussian(Eigen::DenseBase< Derived > &, Eigen::DenseBase< Derived > &, double, double, double)
Definition fitting.h:172
@ pointing
Definition fitting.h:18
Definition toltec_io.h:10
std::map< Eigen::Index, std::string > array_name_map
Definition toltec_io.h:54
Definition wiener_filter.h:23
void filter_noise(MB &mb, const int, const int)
Definition wiener_filter.h:939
Eigen::MatrixXd denom
Definition wiener_filter.h:62
std::string template_type
Definition wiener_filter.h:29
void make_airy_template(MB &mb, const double)
Definition wiener_filter.h:189
std::string parallel_policy
Definition wiener_filter.h:59
void calc_vvq(MB &, const int)
Definition wiener_filter.h:340
std::map< std::string, double > template_fwhm_rad
Definition wiener_filter.h:50
double psd_lim
Definition wiener_filter.h:44
Eigen::MatrixXd rr
Definition wiener_filter.h:62
bool uniform_weight
Definition wiener_filter.h:33
Eigen::MatrixXd vvq
Definition wiener_filter.h:62
std::shared_ptr< spdlog::logger > logger
Definition wiener_filter.h:26
void calc_numerator()
Definition wiener_filter.h:457
std::string filter_type
Definition wiener_filter.h:29
bool normalize_error
Definition wiener_filter.h:31
int max_loops
Definition wiener_filter.h:40
void filter_maps(MB &, const int)
Definition wiener_filter.h:870
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
void get_config(config_t &, std::vector< std::vector< std::string > > &, std::vector< std::vector< std::string > > &)
Definition wiener_filter.h:126
void make_template(MB &, CD &c, const double, const int)
Definition wiener_filter.h:694
double denom_limit
Definition wiener_filter.h:42
void make_gaussian_template(MB &mb, const double)
Definition wiener_filter.h:160
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
void calc_denominator()
Definition wiener_filter.h:523
void run_convolve()
Definition wiener_filter.h:752
void destripe(double)
Definition wiener_filter.h:805
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
int n_loops
Definition wiener_filter.h:38
double diff_rows
Definition wiener_filter.h:56
void make_kernel_template(MB &mb, const int, CD &)
Definition wiener_filter.h:232
bool run_lowpass
Definition wiener_filter.h:35
void get_config_value(config_t config, param_t ¶m, key_vec_t &missing_keys, key_vec_t &invalid_keys, option_t option, std::vector< param_t > allowed={}, std::vector< param_t > min_val={}, std::vector< param_t > max_val={})
Definition config.h:58
#define FWHM_TO_STD
Definition constants.h:48
#define ASEC_TO_RAD
Definition constants.h:33
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