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;
325 in.flags.data.resize(n_pts, in.scans.data.cols());
326 in.flags.data.setConstant(
false);
330 logger->debug(
"despiking");
337 logger->debug(
"replacing spikes");
338 for (
auto const& [key, val] : grp_limits) {
340 auto start_index = std::get<0>(val);
342 auto n_dets = std::get<1>(val) - std::get<0>(val);
345 Eigen::Ref<Eigen::MatrixXd> in_scans_ref = in.scans.data.block(0, start_index, n_pts, n_dets);
347 Eigen::Map<Eigen::MatrixXd, 0, Eigen::OuterStride<>>
348 in_scans(in_scans_ref.data(), in_scans_ref.rows(), in_scans_ref.cols(),
349 Eigen::OuterStride<>(in_scans_ref.outerStride()));
352 Eigen::Ref<Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>> in_flags_ref =
353 in.flags.data.block(0, start_index, n_pts, n_dets);
355 Eigen::Map<Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>, 0, Eigen::OuterStride<> >
356 in_flags(in_flags_ref.data(), in_flags_ref.rows(), in_flags_ref.cols(),
357 Eigen::OuterStride<>(in_flags_ref.outerStride()));
363 in.status.despiked =
true;
368 logger->debug(
"convolving signal with tod filter");
374 logger->debug(
"convolving kernel with tod filter");
378 in.status.tod_filtered =
true;
382 logger->debug(
"downsampling data");
384 Eigen::Ref<Eigen::Map<Eigen::MatrixXd>> in_scans =
385 in.scans.data.block(si, 0, sl, in.scans.data.cols());
388 Eigen::Ref<Eigen::Matrix<bool,Eigen::Dynamic,Eigen::Dynamic>> in_flags =
389 in.flags.data.block(si, 0, sl, in.flags.data.cols());
397 logger->debug(
"downsampling telescope");
398 for (
auto const& x: in.tel_data.data) {
400 Eigen::Ref<Eigen::VectorXd> in_tel =
401 in.tel_data.data[x.first].segment(si,sl);
407 for (
auto const& x: in.pointing_offsets_arcsec.data) {
408 Eigen::Ref<Eigen::VectorXd> in_pointing =
409 in.pointing_offsets_arcsec.data[x.first].segment(si,sl);
415 if (calib.run_hwpr) {
417 Eigen::Ref<Eigen::VectorXd> in_hwpr =
418 in.hwpr_angle.data.segment(si,sl);
422 Eigen::Ref<Eigen::VectorXd> in_angle =
423 in.angle.data.segment(si, sl);
428 logger->debug(
"downsampling kernel");
430 Eigen::Ref<Eigen::MatrixXd> in_kernel =
431 in.kernel.data.block(si, 0, sl, in.kernel.data.cols());
436 in.status.downsampled =
true;
441 out.scans.data = in.scans.data.block(si, 0, sl, in.scans.data.cols());
443 out.flags.data = in.flags.data.block(si, 0, sl, in.flags.data.cols());
446 out.kernel.data = in.kernel.data.block(si, 0, sl, in.kernel.data.cols());
449 for (
auto const& x: in.tel_data.data) {
450 out.tel_data.data[x.first] = in.tel_data.data[x.first].segment(si,sl);
453 for (
auto const& x: in.pointing_offsets_arcsec.data) {
454 out.pointing_offsets_arcsec.data[x.first] = in.pointing_offsets_arcsec.data[x.first].segment(si,sl);
459 if (calib.run_hwpr) {
460 out.hwpr_angle.data = in.hwpr_angle.data.segment(si,sl);
463 out.angle.data = in.angle.data.segment(si,sl);
468 out.scan_indices.data = in.scan_indices.data;
470 out.index.data = in.index.data;
472 out.fcf.data = in.fcf.data;
474 out.status = in.status;
476 out.noise.data = in.noise.data;
479 in.scans.data.resize(0,0);
480 in.flags.data.resize(0,0);
481 in.kernel.data.resize(0,0);
482 in.tel_data.data.clear();
483 in.pointing_offsets_arcsec.data.clear();
485 if (calib.run_hwpr) {
486 in.hwpr_angle.data.resize(0);
488 in.angle.data.resize(0);
491 in.noise.data.resize(0,0);