3#include <tula/logging.h>
5#include <tula/algorithm/ei_stats.h>
34 template <
typename config_t>
35 void get_config(config_t &, std::vector<std::vector<std::string>> &,
36 std::vector<std::vector<std::string>> &);
42 template <
class calib_type>
44 calib_type &, std::string, std::string);
47 template <
typename apt_type,
class tel_type>
51 template <
typename calib_t>
55 template <
typename calib_t,
typename po
inting_offset_t>
57 pointing_offset_t &, calib_t &);
61template <
typename config_t>
63 std::vector<std::vector<std::string>> &invalid_keys) {
67 std::tuple{
"timestream",
"processed_time_chunk",
"weighting",
"type"},{
"full",
"approximate",
"const"});
70 std::tuple{
"timestream",
"processed_time_chunk",
"weighting",
"median_map_weight_factor"});
73 std::tuple{
"timestream",
"processed_time_chunk",
"flagging",
"lower_tod_inv_var_factor"});
76 std::tuple{
"timestream",
"processed_time_chunk",
"flagging",
"upper_tod_inv_var_factor"});
80 std::tuple{
"timestream",
"processed_time_chunk",
"weighting",
"lower_map_weight_factor"});
83 std::tuple{
"timestream",
"processed_time_chunk",
"weighting",
"upper_map_weight_factor"});
87 std::tuple{
"timestream",
"fruit_loops",
"enabled"});
92 std::tuple{
"timestream",
"fruit_loops",
"save_all_iters"});
95 std::tuple{
"timestream",
"fruit_loops",
"path"});
98 std::tuple{
"timestream",
"fruit_loops",
"type"});
101 std::tuple{
"timestream",
"fruit_loops",
"mode"}, {
"upper",
"lower",
"both"});
108 std::tuple{
"timestream",
"fruit_loops",
"sig2noise_limit"});
110 auto fruit_loops_flux_vec = config.template get_typed<std::vector<double>>(std::tuple{
"timestream",
"fruit_loops",
"array_flux_limit"});
111 fruit_loops_flux = Eigen::Map<Eigen::VectorXd>(fruit_loops_flux_vec.data(), fruit_loops_flux_vec.size());
115 std::tuple{
"timestream",
"fruit_loops",
"max_iters"});
120 std::tuple{
"timestream",
"processed_time_chunk",
"clean",
"enabled"});
124 cleaner.
grouping = config.template get_typed<std::vector<std::string>>(std::tuple{
"timestream",
"processed_time_chunk",
"clean",
"grouping"});
127 auto n_eig_to_cut = config.template get_typed<std::vector<Eigen::Index>>(std::tuple{
"timestream",
"processed_time_chunk",
"clean",
128 "n_eig_to_cut",arr_name});
130 cleaner.
n_eig_to_cut[arr_index] = (Eigen::Map<Eigen::VectorXI>(n_eig_to_cut.data(),n_eig_to_cut.size()));
135 std::tuple{
"timestream",
"processed_time_chunk",
"clean",
"stddev_limit"});
138 std::tuple{
"timestream",
"processed_time_chunk",
"clean",
"mask_radius_arcsec"});
142 std::tuple{
"timestream",
"processed_time_chunk",
"clean",
"tau"});
148 auto f = (in.flags.data.derived().array().cast <
double> ().array() - 1).abs();
150 Eigen::RowVectorXd col_mean = (in.scans.data.derived().array()*f).colwise().sum()/
154 Eigen::RowVectorXd dm = (col_mean).array().isNaN().select(0,col_mean);
157 in.scans.data.noalias() = in.scans.data.derived().rowwise() - dm;
160 if (in.kernel.data.size()!=0) {
161 Eigen::RowVectorXd col_mean = (in.kernel.data.derived().array()*f).colwise().sum()/
165 Eigen::RowVectorXd dm = (col_mean).array().isNaN().select(0,col_mean);
168 in.kernel.data.noalias() = in.kernel.data.derived().rowwise() - dm;
172template <
class calib_type>
174 calib_type &calib, std::string pixel_axes, std::string map_grouping) {
182 Eigen::Index n_pts = in.scans.data.rows();
184 Eigen::Index indx = 0;
189 logger->debug(
"cleaning with {} grouping", group);
193 out.evals.data.emplace_back();
194 out.evecs.data.emplace_back();
198 std::map<Eigen::Index, std::tuple<Eigen::Index, Eigen::Index>> grp_limits;
201 if (group ==
"all") {
202 grp_limits[0] = std::make_tuple(0,in.scans.data.cols());
206 grp_limits =
get_grouping(group, calib, in.scans.data.cols());
209 for (
auto const& [key, val] : grp_limits) {
210 Eigen::Index arr_index;
213 arr_index = calib.arrays(0);
216 else if (group==
"nw" || group==
"network") {
220 else if (group==
"array") {
225 auto [start_index, n_dets] = std::make_tuple(std::get<0>(val), std::get<1>(val) - std::get<0>(val));
228 Eigen::Matrix<bool, Eigen::Dynamic, Eigen::Dynamic> masked_flags;
233 masked_flags =
mask_region(in, calib, pixel_axes, map_grouping, n_pts, n_dets, start_index);
237 masked_flags = in.flags.data.block(0, start_index, n_pts, n_dets);
240 auto in_scans_block = in.scans.data.block(0, start_index, n_pts, n_dets);
241 auto out_scans_block = out.scans.data.block(0, start_index, n_pts, n_dets);
244 auto apt_flags = calib.apt[
"flag"].segment(start_index, n_dets);
247 if ((apt_flags.array()==0).any()) {
248 logger->info(
"cleaning {} {}", group, key);
259 logger->debug(
"evals {}", ev);
260 logger->debug(
"evecs {}", evc);
263 out.evals.data[indx].push_back(std::move(ev));
264 out.evecs.data[indx].push_back(std::move(evc));
271 if (in.kernel.data.size()!=0) {
273 logger->debug(
"cleaning kernel");
274 auto in_kernel_block = in.kernel.data.block(0, start_index, n_pts, n_dets);
275 auto out_kernel_block = in.kernel.data.block(0, start_index, n_pts, n_dets);
284 logger->debug(
"no good detectors found. skipping clean.");
286 out.scans.data.block(0, start_index, n_pts, n_dets) = in.scans.data.block(0, start_index, n_pts, n_dets);
288 if (in.kernel.data.size()!=0) {
289 out.kernel.data.block(0, start_index, n_pts, n_dets) = in.kernel.data.block(0, start_index, n_pts, n_dets);
295 out.status.cleaned =
true;
300template <
typename apt_type,
class tel_type>
303 Eigen::Index n_dets = in.scans.data.cols();
306 in.weights.data = Eigen::VectorXd::Zero(n_dets);
310 logger->debug(
"calculating weights using detector sensitivities");
312 double conversion_factor;
315 for (Eigen::Index i=0; i<n_dets; ++i) {
317 Eigen::Index det_index = i;
319 if (in.status.calibrated) {
320 conversion_factor = in.fcf.data(i);
324 conversion_factor = 1;
327 if (conversion_factor*apt[
"sens"](det_index)!=0) {
329 in.weights.data(i) = pow(sqrt(telescope.d_fsmp)*apt[
"sens"](det_index)*conversion_factor,-2.0);
332 in.weights.data(i) = 0;
338 logger->debug(
"calculating weights using timestream variance");
341 for (Eigen::Index i=0; i<n_dets; ++i) {
343 if (apt[
"flag"](i)==0) {
345 Eigen::Map<Eigen::Matrix<double, Eigen::Dynamic, 1>> scans(
346 in.scans.data.col(i).data(), in.scans.data.rows());
347 Eigen::Map<Eigen::Matrix<bool, Eigen::Dynamic, 1>> flags(
348 in.flags.data.col(i).data(), in.flags.data.rows());
353 if (det_std_dev !=0) {
355 in.weights.data(i) = pow(det_std_dev,-2);
359 in.weights.data(i) = 0;
364 in.weights.data(i) = 0;
370 for (Eigen::Index i=0; i<n_dets; ++i) {
372 if (apt[
"flag"](i)==0) {
373 in.weights.data(i) = 1;
377 in.weights.data(i) = 0;
383template <
typename calib_t>
387 calib_t calib_scan = calib;
392 Eigen::Index n_dets = in.scans.data.cols();
398 for (
auto const& [key, val] : grp_limits) {
400 auto grp_weights = in.weights.data(Eigen::seq(std::get<0>(grp_limits[key]),
401 std::get<1>(grp_limits[key])-1));
403 Eigen::Index n_good_dets = 0;
405 Eigen::Index j = std::get<0>(grp_limits[key]);
408 for (Eigen::Index m=0; m<grp_weights.size(); ++m) {
410 if (calib.apt[
"flag"](j)==0 && grp_weights(m)>0) {
417 Eigen::VectorXd good_wt;
421 good_wt.resize(n_good_dets);
424 j = std::get<0>(grp_limits[key]);
426 for (Eigen::Index m=0; m<grp_weights.size(); ++m) {
427 if (calib.apt[
"flag"](j)==0 && grp_weights(m)>0) {
428 good_wt(k) = grp_weights(m);
436 good_wt = grp_weights;
440 auto med_wt = tula::alg::median(good_wt);
442 in.median_weights.data.push_back(med_wt);
449 j = std::get<0>(grp_limits[key]);
451 for (Eigen::Index m=0; m<grp_weights.size(); ++m) {
455 in.weights.data(j) = med_wt;
460 if (calib.apt[
"flag"](j)==0) {
463 if (map_grouping!=
"detector") {
464 in.flags.data.col(j).setOnes();
467 calib_scan.apt[
"flag"](j) = 1;
475 if (map_grouping!=
"detector") {
476 in.flags.data.col(j).setOnes();
479 calib_scan.apt[
"flag"](j) = 1;
487 logger->info(
"array {} had {} outlier weights", key, outliers);
488 logger->info(
"array {}: {}/{} dets below weight limit. {}/{} dets above weight limit.", key,
489 n_dets_low, n_good_dets, n_dets_high, n_good_dets);
495 return std::move(calib_scan);
498template <
typename calib_t,
typename po
inting_offset_t>
500 std::string &pixel_axes, pointing_offset_t &pointing_offsets_arcsec, calib_t &calib) {
503 using netCDF::NcFile;
504 using netCDF::NcType;
506 using namespace netCDF::exceptions;
510 NcFile fo(filepath, netCDF::NcFile::write);
516 NcDim n_dets_dim = fo.getDim(
"n_dets");
519 unsigned long n_dets_exists = n_dets_dim.getSize();
522 std::vector<std::size_t> start_index_weights = {
static_cast<unsigned long>(in.index.data), 0};
523 std::vector<std::size_t> size_weights = {1, n_dets_exists};
526 NcVar weights_v = fo.getVar(
"weights");
529 weights_v.putVar(start_index_weights, size_weights, in.weights.data.data());
533 NcDim n_eigs_dim = fo.getDim(
"n_eigs");
534 netCDF::NcDim n_eig_grp_dim = fo.getDim(
"n_eig_grp");
537 if (n_eig_grp_dim.isNull()) {
538 n_eig_grp_dim = fo.addDim(
"n_eig_grp",in.evals.data[0].size());
542 std::vector<netCDF::NcDim> eval_dims = {n_eig_grp_dim, n_eigs_dim};
545 for (Eigen::Index i=0; i<in.evals.data.size(); ++i) {
546 NcVar eval_v = fo.addVar(
"evals_" +
cleaner.
grouping[i] +
"_" + std::to_string(i) +
547 "_chunk_" + std::to_string(in.index.data), netCDF::ncDouble,eval_dims);
548 std::vector<std::size_t> start_eig_index = {0, 0};
549 std::vector<std::size_t> size = {1, TULA_SIZET(
cleaner.
n_calc)};
552 for (
const auto &evals: in.evals.data[i]) {
553 eval_v.putVar(start_eig_index,size,evals.data());
554 start_eig_index[0] += 1;
559 std::vector<netCDF::NcDim> eig_dims = {n_dets_dim, n_eigs_dim};
562 for (Eigen::Index i=0; i<in.evecs.data.size(); ++i) {
564 std::vector<std::size_t> start_eig_index = {0, 0};
566 NcVar evec_v = fo.addVar(
"evecs_" +
cleaner.
grouping[i] +
"_" + std::to_string(i) +
"_chunk_" +
567 std::to_string(in.index.data),netCDF::ncDouble,eig_dims);
570 for (
const auto &evecs: in.evecs.data[i]) {
571 std::vector<std::size_t> size = {TULA_SIZET(evecs.rows()), TULA_SIZET(
cleaner.
n_calc)};
574 Eigen::MatrixXd ev = evecs.transpose();
575 evec_v.putVar(start_eig_index, size, ev.data());
578 start_eig_index[0] += TULA_SIZET(evecs.rows());
587 logger->info(
"tod chunk written to {}", filepath);
589 }
catch (NcException &e) {
590 logger->error(
"{}", e.what());
std::map< Eigen::Index, std::string > array_name_map
Definition toltec_io.h:54
std::map< Eigen::Index, Eigen::Index > nw_to_array_map
Definition toltec_io.h:37
double stddev_limit
Definition clean.h:24
auto remove_eig_values(const Eigen::DenseBase< DerivedA > &, const Eigen::DenseBase< DerivedB > &, const Eigen::DenseBase< DerivedC > &, const Eigen::DenseBase< DerivedD > &, Eigen::DenseBase< DerivedA > &, const Eigen::Index)
Definition clean.h:245
double tau
Definition clean.h:33
std::map< Eigen::Index, Eigen::VectorXI > n_eig_to_cut
Definition clean.h:27
int n_calc
Definition clean.h:30
auto calc_eig_values(const Eigen::DenseBase< DerivedA > &, const Eigen::DenseBase< DerivedB > &, Eigen::DenseBase< DerivedC > &, const Eigen::Index)
Definition clean.h:126
@ SpectraBackend
Definition clean.h:20
std::vector< std::string > grouping
Definition clean.h:36
void get_config(config_t &, std::vector< std::vector< std::string > > &, std::vector< std::vector< std::string > > &)
Definition ptcproc.h:62
bool run_clean
Definition ptcproc.h:22
timestream::Cleaner cleaner
Definition ptcproc.h:31
double upper_weight_factor
Definition ptcproc.h:26
void append_to_netcdf(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, std::string, std::string, std::string &, pointing_offset_t &, calib_t &)
Definition ptcproc.h:499
void calc_weights(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, apt_type &, tel_type &)
Definition ptcproc.h:301
void run(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, TCData< TCDataKind::PTC, Eigen::MatrixXd > &, calib_type &, std::string, std::string)
Definition ptcproc.h:173
double lower_weight_factor
Definition ptcproc.h:26
auto reset_weights(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, calib_t &, std::string)
Definition ptcproc.h:384
std::string weighting_type
Definition ptcproc.h:28
double med_weight_factor
Definition ptcproc.h:24
void subtract_mean(TCData< TCDataKind::PTC, Eigen::MatrixXd > &)
Definition ptcproc.h:146
Definition timestream.h:257
auto mask_region(TCData< tcdata_t, Eigen::MatrixXd > &, calib_t &, std::string, std::string, int, int, int)
Definition timestream.h:918
auto get_grouping(std::string, calib_t &, int)
Definition timestream.h:572
std::string fruit_loops_path
Definition timestream.h:281
std::shared_ptr< spdlog::logger > logger
Definition timestream.h:260
double upper_inv_var_factor
Definition timestream.h:302
double fruit_loops_sig2noise
Definition timestream.h:289
bool save_all_iters
Definition timestream.h:293
double mask_radius_arcsec
Definition timestream.h:305
bool run_tod_output
Definition timestream.h:276
void append_base_to_netcdf(netCDF::NcFile &, TCData< tcdata_t, Eigen::MatrixXd > &, std::string, std::string &, pointing_offset_t &, calib_t &)
Definition timestream.h:968
bool write_evals
Definition timestream.h:276
engine_utils::toltecIO toltec_io
Definition timestream.h:263
int fruit_loops_iters
Definition timestream.h:287
bool run_fruit_loops
Definition timestream.h:279
std::string fruit_mode
Definition timestream.h:285
Eigen::VectorXd fruit_loops_flux
Definition timestream.h:291
double lower_inv_var_factor
Definition timestream.h:302
std::string fruit_loops_type
Definition timestream.h:285
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
auto calc_std_dev(Eigen::DenseBase< DerivedA > &data)
Definition utils.h:336
TC data class.
Definition timestream.h:55