72 std::vector<std::vector<std::string>> &invalid_keys) {
75 std::tuple{
"timestream",
"raw_time_chunk",
"flagging",
"lower_tod_inv_var_factor"});
78 std::tuple{
"timestream",
"raw_time_chunk",
"flagging",
"upper_tod_inv_var_factor"});
81 std::tuple{
"timestream",
"raw_time_chunk",
"flagging",
"delta_f_min_Hz"});
85 std::tuple{
"timestream",
"polarimetry",
"enabled"});
91 std::tuple{
"timestream",
"polarimetry",
"grouping"});
100 std::tuple{
"timestream",
"raw_time_chunk",
"kernel",
"enabled"});
104 std::tuple{
"timestream",
"raw_time_chunk",
"kernel",
"filepath"});
107 std::tuple{
"timestream",
"raw_time_chunk",
"kernel",
"type"});
110 std::tuple{
"timestream",
"raw_time_chunk",
"kernel",
"fwhm_arcsec"});
120 auto img_ext_name_node = config.get_node(std::tuple{
"timestream",
"raw_time_chunk",
"kernel",
"image_ext_names"});
122 for (Eigen::Index i=0; i<img_ext_name_node.size(); ++i) {
123 std::string img_ext_name = config.template get_str(std::tuple{
"timestream",
"raw_time_chunk",
"kernel",
"image_ext_names",
124 i, std::to_string(i)});
132 std::tuple{
"timestream",
"raw_time_chunk",
"despike",
"enabled"});
136 std::tuple{
"timestream",
"raw_time_chunk",
"despike",
"min_spike_sigma"});
139 std::tuple{
"timestream",
"raw_time_chunk",
"despike",
"time_constant_sec"});
142 std::tuple{
"timestream",
"raw_time_chunk",
"despike",
"window_size"});
150 std::tuple{
"timestream",
"raw_time_chunk",
"filter",
"enabled"});
154 std::tuple{
"timestream",
"raw_time_chunk",
"filter",
"a_gibbs"});
157 std::tuple{
"timestream",
"raw_time_chunk",
"filter",
"freq_low_Hz"});
160 std::tuple{
"timestream",
"raw_time_chunk",
"filter",
"freq_high_Hz"});
163 std::tuple{
"timestream",
"raw_time_chunk",
"filter",
"n_terms"});
175 std::tuple{
"timestream",
"raw_time_chunk",
"downsample",
"enabled"});
179 logger->error(
"running downsampling without tod filtering will lose data!");
180 std::exit(EXIT_FAILURE);
184 std::tuple{
"timestream",
"raw_time_chunk",
"downsample",
"factor"},{},{0});
187 std::tuple{
"timestream",
"raw_time_chunk",
"downsample",
"downsampled_freq_Hz"});
192 std::tuple{
"timestream",
"raw_time_chunk",
"flux_calibration",
"enabled"});
195 std::tuple{
"timestream",
"raw_time_chunk",
"extinction_correction",
"enabled"});
201 Eigen::VectorXI indices(calib.n_dets), map_indices(calib.n_dets);
207 if (map_grouping ==
"nw") {
208 indices = calib.apt[
"nw"].template cast<Eigen::Index> ();
209 n_maps = calib.n_nws;
212 else if (map_grouping ==
"array") {
213 indices = calib.apt[
"array"].template cast<Eigen::Index> ();
214 n_maps = calib.n_arrays;
217 else if (map_grouping ==
"detector") {
218 indices = Eigen::VectorXI::LinSpaced(calib.n_dets,0,calib.n_dets-1);
219 n_maps = calib.n_dets;
222 else if (map_grouping ==
"fg") {
223 indices = calib.apt[
"fg"].template cast<Eigen::Index> ();
224 n_maps = calib.fg.size()*calib.n_arrays;
227 if (map_grouping !=
"fg") {
228 Eigen::Index map_index = 0;
231 for (Eigen::Index i=0; i<indices.size()-1; ++i) {
233 if (indices(i+1) > indices(i)) {
236 map_indices(i+1) = map_index;
241 std::map<Eigen::Index, Eigen::Index> fg_to_index, array_to_index;
244 for (Eigen::Index i=0; i<calib.fg.size(); ++i) {
245 fg_to_index[calib.fg(i)] = i;
248 for (Eigen::Index i=0; i<calib.arrays.size(); ++i) {
249 array_to_index[calib.arrays(i)] = i;
252 for (Eigen::Index i=0; i<indices.size(); ++i) {
253 map_indices(i) = fg_to_index[indices(i)] + calib.fg.size()*array_to_index[calib.apt[
"array"](i)];
257 return std::move(map_indices);
262 calib_t &calib, telescope_t &telescope,
double pixel_size_rad, std::string map_grouping) {
265 Eigen::Index n_pts = in.scans.data.rows();
270 auto sl = in.scan_indices.data(1) - in.scan_indices.data(0) + 1;
278 in.fcf.data.setOnes(in.scans.data.cols());
281 logger->debug(
"calculating map indices");
285 logger->debug(
"calibrating timestream");
289 in.status.calibrated =
true;
293 logger->debug(
"correcting extinction");
299 in.status.extinction_corrected =
true;
304 logger->debug(
"creating kernel timestream");
307 logger->debug(
"creating symmetric gaussian kernel");
312 logger->debug(
"creating airy kernel");
317 logger->debug(
"getting kernel from fits");
321 in.status.kernel_generated =
true;
326 logger->debug(
"despiking");
333 logger->debug(
"replacing spikes");
334 for (
auto const& [key, val] : grp_limits) {
336 auto start_index = std::get<0>(val);
338 auto n_dets = std::get<1>(val) - std::get<0>(val);
341 Eigen::Ref<Eigen::MatrixXd> in_scans_ref = in.scans.data.block(0, start_index, n_pts, n_dets);
343 Eigen::Map<Eigen::MatrixXd, 0, Eigen::OuterStride<>>
344 in_scans(in_scans_ref.data(), in_scans_ref.rows(), in_scans_ref.cols(),
345 Eigen::OuterStride<>(in_scans_ref.outerStride()));
348 Eigen::Ref<Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>> in_flags_ref =
349 in.flags.data.block(0, start_index, n_pts, n_dets);
351 Eigen::Map<Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>, 0, Eigen::OuterStride<> >
352 in_flags(in_flags_ref.data(), in_flags_ref.rows(), in_flags_ref.cols(),
353 Eigen::OuterStride<>(in_flags_ref.outerStride()));
359 in.status.despiked =
true;
364 logger->debug(
"convolving signal with tod filter");
370 logger->debug(
"convolving kernel with tod filter");
374 in.status.tod_filtered =
true;
378 logger->debug(
"downsampling data");
380 Eigen::Ref<Eigen::Map<Eigen::MatrixXd>> in_scans =
381 in.scans.data.block(si, 0, sl, in.scans.data.cols());
384 Eigen::Ref<Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>> in_flags =
385 in.flags.data.block(si, 0, sl, in.flags.data.cols());
393 logger->debug(
"downsampling telescope");
394 for (
auto const& x: in.tel_data.data) {
396 Eigen::Ref<Eigen::VectorXd> in_tel =
397 in.tel_data.data[x.first].segment(si,sl);
403 for (
auto const& x: in.pointing_offsets_arcsec.data) {
404 Eigen::Ref<Eigen::VectorXd> in_pointing =
405 in.pointing_offsets_arcsec.data[x.first].segment(si,sl);
411 if (calib.run_hwpr) {
413 Eigen::Ref<Eigen::VectorXd> in_hwpr =
414 in.hwpr_angle.data.segment(si,sl);
418 Eigen::Ref<Eigen::VectorXd> in_angle =
419 in.angle.data.segment(si, sl);
424 logger->debug(
"downsampling kernel");
426 Eigen::Ref<Eigen::MatrixXd> in_kernel =
427 in.kernel.data.block(si, 0, sl, in.kernel.data.cols());
432 in.status.downsampled =
true;
437 out.scans.data = in.scans.data.block(si, 0, sl, in.scans.data.cols());
439 out.flags.data = in.flags.data.block(si, 0, sl, in.flags.data.cols());
442 out.kernel.data = in.kernel.data.block(si, 0, sl, in.kernel.data.cols());
445 for (
auto const& x: in.tel_data.data) {
446 out.tel_data.data[x.first] = in.tel_data.data[x.first].segment(si,sl);
449 for (
auto const& x: in.pointing_offsets_arcsec.data) {
450 out.pointing_offsets_arcsec.data[x.first] = in.pointing_offsets_arcsec.data[x.first].segment(si,sl);
455 if (calib.run_hwpr) {
456 out.hwpr_angle.data = in.hwpr_angle.data.segment(si,sl);
459 out.angle.data = in.angle.data.segment(si,sl);
464 out.scan_indices.data = in.scan_indices.data;
466 out.index.data = in.index.data;
468 out.fcf.data = in.fcf.data;
470 out.status = in.status;
472 out.noise.data = in.noise.data;
475 in.scans.data.resize(0,0);
476 in.flags.data.resize(0,0);
477 in.kernel.data.resize(0,0);
478 in.tel_data.data.clear();
479 in.pointing_offsets_arcsec.data.clear();
481 if (calib.run_hwpr) {
482 in.hwpr_angle.data.resize(0);
484 in.angle.data.resize(0);
487 in.noise.data.resize(0,0);