Citlali
Loading...
Searching...
No Matches
beammap.h
Go to the documentation of this file.
1#pragma once
2
3#include <map>
4#include <vector>
5#include <string>
6
8
12
13// selects the type of TCData
14using timestream::TCDataKind;
15
16class Beammap: public Engine {
17public:
18 // parallel policies for each section
20
21 // vector to store each scan's PTCData
22 std::vector<TCData<TCDataKind::PTC,Eigen::MatrixXd>> ptcs0, ptcs;
23
24 // copy of obs map buffer for map iteration
26
27 // vector to store each scan's calib class
28 std::vector<engine::Calib> calib_scans0, calib_scans;
29
30 // beammap iteration parameters
31 Eigen::Index current_iter;
32
33 // vector for convergence check
34 Eigen::Matrix<bool, Eigen::Dynamic, 1> converged;
35
36 // vector to record convergence iteration
37 Eigen::Vector<int, Eigen::Dynamic> converge_iter;
38
39 // previous iteration fit parameters
40 Eigen::MatrixXd p0, perror0;
41
42 // current iteration fit parameters
43 Eigen::MatrixXd params, perrors;
44
45 // reference detector
46 Eigen::Index beammap_reference_det_found = -99;
47
48 // bitwise flags
49 enum AptFlags {
50 Good = 0,
51 BadFit = 1 << 0,
52 AzFWHM = 1 << 1,
53 ElFWHM = 1 << 2,
54 Sig2Noise = 1 << 3,
55 Sens = 1 << 4,
56 Position = 1 << 5,
57 };
58
59 // holds bitwise flags
60 Eigen::Matrix<uint16_t,Eigen::Dynamic,1> flag2;
61
62 // good fits
63 Eigen::Matrix<bool, Eigen::Dynamic, 1> good_fits;
64
65 // placeholder vectors for grppi maps
66 std::vector<int> scan_in_vec, scan_out_vec;
67 std::vector<int> det_in_vec, det_out_vec;
68
69 // initial setup for each obs
70 void setup();
71
72 // timestream grppi pipeline
73 template <class KidsProc, class RawObs>
74 void timestream_pipeline(KidsProc &, RawObs &);
75
76 // run the raw time chunk processing
77 template <class KidsProc>
78 auto run_timestream(KidsProc &);
79
80 // run the loop pipeline
81 void loop_pipeline();
82
83 // run the iterative stage
84 void run_loop();
85
86 // flag detectors
87 void set_apt_flags();
88
89 // derotate apt and subtract reference detector
90 void process_apt();
91
92 // main pipeline process
93 template <class KidsProc, class RawObs>
94 void pipeline(KidsProc &, RawObs &);
95
96 // output files
97 template <mapmaking::MapType map_type>
98 void output();
99};
100
102 // assign parallel policies
104
105 // run obsnum setup
106 obsnum_setup();
107
108 // create kids tone apt row
109 calib.apt["kids_tone"].resize(calib.n_dets);
110
111 Eigen::Index j = 0;
112 // set kids tone (det number on network)
113 calib.apt["kids_tone"](0) = 0;
114 for (Eigen::Index i=1; i<calib.n_dets; ++i) {
115 if (calib.apt["nw"](i) > calib.apt["nw"](i-1)) {
116 j = 0;
117 }
118 else {
119 j++;
120 }
121
122 calib.apt["kids_tone"](i) = j;
123 }
124
125 // add kids tone to apt header
126 calib.apt_header_keys.push_back("kids_tone");
127 calib.apt_header_units["kids_tone"] = "N/A";
128
129 // resize the PTCData vector to number of scans
130 ptcs0.resize(telescope.scan_indices.cols());
131
132 // resize the calib vector to number of scans
133 calib_scans0.resize(telescope.scan_indices.cols());
134
135 // resize the initial fit matrix
136 p0.setZero(n_maps, map_fitter.n_params);
137 // resize the initial fit error matrix
139 // resize the current fit matrix
142
143 // resize good fits
144 good_fits.setZero(n_maps);
145
146 // initially all detectors are unconverged
147 converged.setZero(n_maps);
148 // convergence iteration
149 converge_iter.resize(n_maps);
150 converge_iter.setConstant(1);
151 // set the initial iteration
152 current_iter = 0;
153
154 /* update apt table meta data */
155 calib.apt_meta.reset();
156
157 // add obsnum to meta data
158 calib.apt_meta["obsnum"] = obsnum;
159
160 // add source name
162
163 // add project id to meta data
164 calib.apt_meta["project_id"] = telescope.project_id;
165
166 // add input source flux
167 for (const auto &beammap_flux: beammap_fluxes_mJy_beam) {
168 auto key = beammap_flux.first + "_flux";
169 calib.apt_meta[key].push_back(beammap_flux.second);
170 calib.apt_meta[key].push_back("units: mJy/beam");
171 calib.apt_meta[key].push_back(beammap_flux.first + " flux density");
172 }
173
174 // add date of file creation
176
177 // add observation date
178 calib.apt_meta["date"] = date_obs.back();
179
180 // mean Modified Julian Date
182
183 // reference frame
184 calib.apt_meta["Radesys"] = telescope.pixel_axes;
185
186 // add mean tau to apt meta
188 Eigen::VectorXd tau_el(1);
189 tau_el << telescope.tel_data["TelElAct"].mean();
190 auto tau_freq = rtcproc.calibration.calc_tau(tau_el, telescope.tau_225_GHz);
191
192 Eigen::Index i = 0;
193 for (auto const& [key, val] : tau_freq) {
194 calib.apt_meta[toltec_io.array_name_map[calib.arrays(i)]+"_tau"] = val[0];
195 i++;
196 }
197 }
198 else {
199 for (Eigen::Index i=0; i<calib.arrays.size(); ++i) {
201 }
202 }
203
204 // add apt header keys
205 for (const auto &[param,unit]: calib.apt_header_units) {
206 calib.apt_meta[param].push_back("units: " + unit);
207 }
208 // add apt header descriptions
209 for (const auto &[param,description]: calib.apt_header_description) {
210 calib.apt_meta[param].push_back(description);
211 }
212
213 // kids tone
214 calib.apt_meta["kids_tone"].push_back("units: N/A");
215 calib.apt_meta["kids_tone"].push_back("index of tone in network");
216
217 // bitwise flag
218 calib.apt_meta["flag2"].push_back("units: N/A");
219 calib.apt_meta["flag2"].push_back("bitwise flag");
220 calib.apt_meta["flag2"].push_back("Good=0");
221 calib.apt_meta["flag2"].push_back("BadFit=1");
222 calib.apt_meta["flag2"].push_back("AzFWHM=2");
223 calib.apt_meta["flag2"].push_back("ElFWHM=3");
224 calib.apt_meta["flag2"].push_back("Sig2Noise=4");
225 calib.apt_meta["flag2"].push_back("Sens=5");
226 calib.apt_meta["flag2"].push_back("Position=6");
227
228 // add array mapping
229 for (const auto &[arr_index,arr_name]: toltec_io.array_name_map) {
230 calib.apt_meta["array_order"].push_back(std::to_string(arr_index) + ": " + arr_name);
231 }
232
233 calib.apt_header_units["flag2"] = "N/A";
234 calib.apt_header_keys.push_back("flag2");
235
236 // is the detector rotated?
237 calib.apt_meta["is_derotated"] = beammap_derotate;
238 // was a reference detector subtracted?
239 calib.apt_meta["reference_detector_subtracted"] = beammap_subtract_reference;
240 // reference detector
241 calib.apt_meta["reference_det"] = beammap_reference_det_found;
242}
243
244template <class KidsProc, class RawObs>
245void Beammap::pipeline(KidsProc &kidsproc, RawObs &rawobs) {
246 // only get kids params if not simulation
247 if (!telescope.sim_obs) {
248 // add kids models to apt
249 auto [kids_models, kids_model_header] = kidsproc.load_fit_report(rawobs);
250
251 Eigen::Index i = 0;
252 // loop through kids header
253 for (const auto &h: kids_model_header) {
254 std::string name = h;
255 if (name=="flag") {
256 name = "kids_flag";
257 }
258 calib.apt[name].resize(calib.n_dets);
259 Eigen::Index j = 0;
260 for (const auto &v: kids_models) {
261 calib.apt[name].segment(j,v.rows()) = v.col(i);
262 j = j + v.rows();
263 }
264
265 // search for key
266 bool found = false;
267 for (const auto &key: calib.apt_header_keys){
268 if (key==name) {
269 found = true;
270 }
271 }
272 // if not found, push back placeholder
273 if (!found) {
274 calib.apt_header_keys.push_back(name);
275 calib.apt_header_units[name] = "N/A";
276 }
277
278 // detector orientation
279 calib.apt_meta[name].push_back("units: N/A");
280 calib.apt_meta[name].push_back(name);
281 i++;
282 }
283 }
284
285 // run timestream pipeline
286 timestream_pipeline(kidsproc, rawobs);
287
288 // placeholder vectors of size nscans for grppi maps
289 scan_in_vec.resize(ptcs0.size());
290 std::iota(scan_in_vec.begin(), scan_in_vec.end(), 0);
291 scan_out_vec.resize(ptcs0.size());
292
293 // placeholder vectors of size ndet for grppi maps
294 det_in_vec.resize(n_maps);
295 std::iota(det_in_vec.begin(), det_in_vec.end(), 0);
296 det_out_vec.resize(n_maps);
297
298 // run iterative pipeline
300}
301
302template <class KidsProc, class RawObs>
303void Beammap::timestream_pipeline(KidsProc &kidsproc, RawObs &rawobs) {
304 using tuple_t = std::tuple<TCData<TCDataKind::RTC, Eigen::MatrixXd>,
305 std::vector<kids::KidsData<kids::KidsDataKind::RawTimeStream>>>;
306 // initialize number of completed scans
307 n_scans_done = 0;
308
309 // progress bar
310 tula::logging::progressbar pb(
311 [&](const auto &msg) { logger->info("{}", msg); }, 100, "RTC progress ");
312
313 // grppi generator function. gets time chunk data from files sequentially and passes them to grppi::farm
314 grppi::pipeline(tula::grppi_utils::dyn_ex(parallel_policy),
315 [&]() -> std::optional<tuple_t> {
316
317 // variable to hold current scan
318 static int scan = 0;
319 // loop through scans
320 while (scan < telescope.scan_indices.cols()) {
321 // update progress bar
322 pb.count(telescope.scan_indices.cols(), 1);
323
324 // create rtcdata
325 TCData<TCDataKind::RTC, Eigen::MatrixXd> rtcdata;
326 // get scan indices
327 rtcdata.scan_indices.data = telescope.scan_indices.col(scan);
328 // current scan
329 rtcdata.index.data = scan;
330
331 // vector to store kids data
332 std::vector<kids::KidsData<kids::KidsDataKind::RawTimeStream>> scan_rawobs;
333 // get kids data
334 scan_rawobs = kidsproc.load_rawobs(rawobs, scan, telescope.scan_indices, start_indices, end_indices);
335
336 // increment scan
337 scan++;
338 // return rtcdata, kidsproc, and raw data
339 return tuple_t(rtcdata,scan_rawobs);
340 }
341 // reset scan to zero for each obs
342 scan = 0;
343 return {};
344 },
345 // run the raw time chunk processing
346 run_timestream(kidsproc));
347}
348
349template <class KidsProc>
350auto Beammap::run_timestream(KidsProc &kidsproc) {
351 auto farm = grppi::farm(n_threads,[&](auto &input_tuple) -> TCData<TCDataKind::PTC,Eigen::MatrixXd> {
352 // RTCData input
353 auto& rtcdata = std::get<0>(input_tuple);
354 // start index input
355 auto& scan_rawobs = std::get<1>(input_tuple);
356
357 // allocate up bitwise timestream flags
358 rtcdata.flags2.data.setConstant(timestream::TimestreamFlags::Good);
359
360 // starting index for scan (outer scan)
361 Eigen::Index si = rtcdata.scan_indices.data(2);
362
363 // current length of outer scans
364 Eigen::Index sl = rtcdata.scan_indices.data(3) - rtcdata.scan_indices.data(2) + 1;
365
366 // copy scan's telescope vectors
367 for (const auto& x: telescope.tel_data) {
368 rtcdata.tel_data.data[x.first] = telescope.tel_data[x.first].segment(si,sl);
369 }
370
371 // copy pointing offsets
372 for (const auto& [axis,offset]: pointing_offsets_arcsec) {
373 rtcdata.pointing_offsets_arcsec.data[axis] = offset.segment(si,sl);
374 }
375
376 // get hwpr
378 rtcdata.hwpr_angle.data = calib.hwpr_angle.segment(si + hwpr_start_indices, sl);
379 }
380
381 // get raw tod from files
382 rtcdata.scans.data = kidsproc.populate_rtc(scan_rawobs, sl, calib.n_dets, tod_type);
383 std::vector<kids::KidsData<kids::KidsDataKind::RawTimeStream>>().swap(scan_rawobs);
384
385 // create PTCData
387
388 logger->info("starting scan {}. {}/{} scans completed", rtcdata.index.data + 1, n_scans_done,
389 telescope.scan_indices.cols());
390
391 // run rtcproc
392 logger->info("raw time chunk processing for scan {}", rtcdata.index.data + 1);
393 auto map_indices = rtcproc.run(rtcdata, ptcdata, calib, telescope, omb.pixel_size_rad, map_grouping);
394
395 if (map_grouping!="detector") {
396 // remove flagged detectors
398 }
399
400 // remove outliers before cleaning
401 auto calib_scan = rtcproc.remove_bad_dets(ptcdata, calib, map_grouping);
402
403 // remove duplicate tones
404 if (!telescope.sim_obs) {
405 calib_scan = rtcproc.remove_nearby_tones(ptcdata, calib_scan, map_grouping);
406 }
407
408 // write rtc timestreams
409 if (run_tod_output && !tod_filename.empty()) {
410 if (tod_output_type == "rtc" || tod_output_type == "both") {
411 logger->info("writing raw time chunk");
413 ptcdata.pointing_offsets_arcsec.data, calib_scan);
414 }
415 }
416
417 // store indices for each ptcdata
418 ptcdata.map_indices.data = std::move(map_indices);
419
420 // move out ptcdata the PTCData vector at corresponding index
421 ptcs0.at(ptcdata.index.data) = std::move(ptcdata);
422 calib_scans0.at(ptcdata.index.data) = std::move(calib_scan);
423
424 // increment number of completed scans
425 n_scans_done++;
426 logger->info("done with scan {}. {}/{} scans completed", ptcdata.index.data + 1, n_scans_done, telescope.scan_indices.cols());
427
428 return ptcdata;
429 });
430
431 return farm;
432}
433
435 // run iterative stage
436 run_loop();
437
438 // write map summary
439 if (verbose_mode) {
441 }
442
443 // empty initial ptcdata vector to save memory
444 ptcs0.clear();
445
446 // set to input parallel policy
448
449 if (map_grouping=="detector") {
450 logger->info("calculating sensitivity");
451 // parallelize on detectors
452 grppi::map(tula::grppi_utils::dyn_ex(parallel_policy), det_in_vec, det_out_vec, [&](auto i) {
453 Eigen::MatrixXd det_sens, noise_flux;
454 // calc sensitivity within psd freq range
455 calc_sensitivity(ptcs, det_sens, noise_flux, telescope.d_fsmp, i, {sens_psd_limits_Hz(0), sens_psd_limits_Hz(1)});
456 // copy into apt table
457 calib.apt["sens"](i) = tula::alg::median(det_sens);
458
459 return 0;
460 });
461 }
462
463 // apt and sensitivity only relevant if beammapping
464 if (map_grouping=="detector") {
465 // rescale fit params from pixel to on-sky units
466 calib.apt["amp"] = params.col(0);
467 calib.apt["x_t"] = RAD_TO_ASEC*omb.pixel_size_rad*(params.col(1).array() - (omb.n_cols)/2);
468 calib.apt["y_t"] = RAD_TO_ASEC*omb.pixel_size_rad*(params.col(2).array() - (omb.n_rows)/2);
471 calib.apt["angle"] = params.col(5);
472
473 // rescale fit errors from pixel to on-sky units
474 calib.apt["amp_err"] = perrors.col(0);
475 calib.apt["x_t_err"] = RAD_TO_ASEC*omb.pixel_size_rad*(perrors.col(1));
476 calib.apt["y_t_err"] = RAD_TO_ASEC*omb.pixel_size_rad*(perrors.col(2));
477 calib.apt["a_fwhm_err"] = RAD_TO_ASEC*STD_TO_FWHM*omb.pixel_size_rad*(perrors.col(3));
478 calib.apt["b_fwhm_err"] = RAD_TO_ASEC*STD_TO_FWHM*omb.pixel_size_rad*(perrors.col(4));
479 calib.apt["angle_err"] = perrors.col(5);
480
481 // add convergence iteration to apt table
482 calib.apt["converge_iter"] = converge_iter.cast<double> ();
483
484 // flag detectors in apt based on config limits
486
487 // subtract reference detector position and derotate
488 process_apt();
489
490 // add final apt table to timestream files
491 if (run_tod_output && !tod_filename.empty()) {
492 // vectors to hold tangent plane pointing for all ptcs (n_chunks x [n_pts x n_dets])
493 std::vector<Eigen::MatrixXd> lat, lon;
494
495 // recalculate tangent plane pointing for tod output
496 for (Eigen::Index i=0; i<ptcs.size(); ++i) {
497 // tangent plane pointing for each detector
498 Eigen::MatrixXd ptc_lat(ptcs[i].scans.data.rows(), ptcs[i].scans.data.cols());
499 Eigen::MatrixXd ptc_lon(ptcs[i].scans.data.rows(), ptcs[i].scans.data.cols());
500 // loop through detectors
501 grppi::map(tula::grppi_utils::dyn_ex(parallel_policy), det_in_vec, det_out_vec, [&](auto j) {
502 // det indices
503 auto det_index = j;
504 double az_off = calib.apt["x_t"](det_index);
505 double el_off = calib.apt["y_t"](det_index);
506
507 // get tangent pointing
508 auto [det_lat, det_lon] = engine_utils::calc_det_pointing(ptcs[i].tel_data.data, az_off,
509 el_off, telescope.pixel_axes,
510 ptcs[i].pointing_offsets_arcsec.data,
512 ptc_lat.col(j) = std::move(det_lat);
513 ptc_lon.col(j) = std::move(det_lon);
514
515 return 0;
516 });
517 lat.push_back(std::move(ptc_lat));
518 lon.push_back(std::move(ptc_lon));
519 }
520
521 // set parallel policy to sequential for tod output
522 parallel_policy = "seq";
523
524 logger->info("adding final apt and detector pointing to tod files");
525 // loop through tod files
526 for (const auto & [key, val]: tod_filename) {
527 netCDF::NcFile fo(val, netCDF::NcFile::write);
528 // overwrite apt table
529 for (auto const& x: calib.apt) {
530 if (x.first!="flag2") {
531 // start index for apt table
532 std::vector<std::size_t> start_index_apt = {0};
533 // size for apt
534 std::vector<std::size_t> size_apt = {1};
535 netCDF::NcVar apt_v = fo.getVar("apt_" + x.first);
536 if (!apt_v.isNull()) {
537 for (std::size_t i=0; i< TULA_SIZET(calib.n_dets); ++i) {
538 start_index_apt[0] = i;
539 apt_v.putVar(start_index_apt, size_apt, &calib.apt[x.first](i));
540 }
541 }
542 }
543 }
544
545 // detector tangent plane pointing
546 netCDF::NcVar det_lat_v = fo.getVar("det_lat");
547 netCDF::NcVar det_lon_v = fo.getVar("det_lon");
548
549 // detector absolute pointing
550 netCDF::NcVar det_ra_v = fo.getVar("det_ra");
551 netCDF::NcVar det_dec_v = fo.getVar("det_dec");
552
553 // start indices for data
554 std::vector<std::size_t> start_index = {0, 0};
555 // size for data
556 std::vector<std::size_t> size = {1, TULA_SIZET(calib.n_dets)};
557 std::size_t k = 0;
558 // loop through ptcs
559 for (Eigen::Index i=0; i<lat.size(); ++i) {
560 // loop through n_pts
561 for (std::size_t j=0; j < TULA_SIZET(lat[i].rows()); ++j) {
562 start_index[0] = k;
563 k++;
564 // append detector latitudes
565 Eigen::VectorXd lat_row = lat[i].row(j);
566 det_lat_v.putVar(start_index, size, lat_row.data());
567
568 // append detector longitudes
569 Eigen::VectorXd lon_row = lon[i].row(j);
570 det_lon_v.putVar(start_index, size, lon_row.data());
571
572 if (telescope.pixel_axes == "radec") {
573 // get absolute pointing
574 auto [dec, ra] = engine_utils::tangent_to_abs(lat_row, lon_row, telescope.tel_header["Header.Source.Ra"](0),
575 telescope.tel_header["Header.Source.Dec"](0));
576 // append detector ra
577 det_ra_v.putVar(start_index, size, ra.data());
578
579 // append detector dec
580 det_dec_v.putVar(start_index, size, dec.data());
581 }
582 }
583 }
584 }
585
586 // empty ptcdata vector to save memory
587 ptcs.clear();
588 }
589 }
590
591 else {
592 // calculate map psds
593 logger->info("calculating map psd");
595 // calculate map histograms
596 logger->info("calculating map histogram");
598 }
599}
600
601
603 // variable to control iteration
604 bool keep_going = true;
605
606 // declare random number generator
607 boost::random::mt19937 eng;
608
609 // boost random number generator (0,1)
610 boost::random::uniform_int_distribution<> rands{0,1};
611
612 // iterative loop
613 while (keep_going) {
614 logger->info("starting iter {}", current_iter);
615
616 // copy ptcs
617 ptcs = ptcs0;
618 // copy calibs
620
621 // copy signal for convergence test
624 // calc mean rms
625 if (current_iter == 1) {
626 // use obs map buffer
627 if (!omb.noise.empty()) {
629 }
630 }
631 }
632
633 // progress bar
634 tula::logging::progressbar pb(
635 [&](const auto &msg) { logger->info("{}", msg); }, 100, "PTC progress ");
636
637
638 // cleaning (separate from mapmaking loop due to jinc mapmaking parallelization)
639 grppi::map(tula::grppi_utils::dyn_ex(omb.parallel_policy), scan_in_vec, scan_out_vec, [&](auto i) {
640 if (run_mapmaking) {
641 if (current_iter > 0) {
642 if (!ptcproc.run_fruit_loops) {
643 // if not running fruit loops use source fit
644 logger->info("subtracting gaussian from tod");
645 // subtract gaussian
646 ptcproc.add_gaussian<timestream::TCProc::SourceType::NegativeGaussian>(ptcs[i], params, telescope.pixel_axes, map_grouping,
647 calib.apt,omb.pixel_size_rad, omb.n_rows, omb.n_cols);
648 }
649 else {
650 logger->info("subtracting map from tod");
651 // subtract map
652 ptcproc.map_to_tod<timestream::TCProc::SourceType::NegativeMap>(omb, ptcs[i], calib, ptcs[i].map_indices.data, telescope.pixel_axes,
653 map_grouping);
654 }
655 }
656 }
657
658 // clean the maps
659 logger->info("processed time chunk processing for scan {}", i + 1);
661
662 if (run_mapmaking) {
663 if (current_iter > 0) {
664 // if not running fruit loops use source fit
666 logger->info("adding gaussian to tod");
667 // add gaussian back
670 }
671 else {
672 logger->info("adding map to tod");
673 // add map back
676 }
677 }
678 }
679
680 // remove outliers after clean
682
683 if (map_grouping == "detector") {
684 // set weights to a constant value
685 ptcs[i].weights.data.resize(ptcs[i].scans.data.cols());
686 ptcs[i].weights.data.setOnes();
687 }
688 else {
689 // calculate weights
690 logger->info("calculating weights");
692
693 // reset weights to median
695 }
696
697 // write out chunk summary
699 logger->debug("writing chunk summary");
701 }
702
703 // calc stats
704 logger->debug("calculating stats");
706
707 return 0;
708 });
709
710 // write ptc timestreams
711 if (run_tod_output && !tod_filename.empty()) {
712 if (tod_output_type == "ptc" || tod_output_type == "both") {
713 logger->info("writing processed time chunk");
715 for (Eigen::Index i=0; i<telescope.scan_indices.cols(); ++i) {
717 ptcs[i].pointing_offsets_arcsec.data, calib_scans[i]);
718 }
719 }
720 }
721 }
722
723 logger->info("starting mapmaking");
724
725 if (run_mapmaking) {
726 // set maps to zero for each iteration
727 for (Eigen::Index i=0; i<n_maps; ++i) {
728 omb.signal[i].setZero();
729 omb.weight[i].setZero();
730
731 // clear coverage
732 if (!omb.coverage.empty()) {
733 omb.coverage[i].setZero();
734 }
735 // clear kernel
736 if (rtcproc.run_kernel) {
737 omb.kernel[i].setZero();
738 }
739 // clear noise
740 if (!omb.noise.empty()) {
741 omb.noise[i].setZero();
742 }
743
744 if (run_noise) {
745 for (auto& ptcdata: ptcs) {
746 if (omb.randomize_dets) {
747 ptcdata.noise.data = Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic>::Zero(omb.n_noise, calib.n_dets)
748 .unaryExpr([&](int dummy){ return 2 * rands(eng) - 1; });
749 } else {
750 ptcdata.noise.data = Eigen::Matrix<int, Eigen::Dynamic, 1>::Zero(omb.n_noise)
751 .unaryExpr([&](int dummy){ return 2 * rands(eng) - 1; });
752 }
753 }
754 }
755 }
756
757 logger->info("running mapmaking");
758
759 if (map_grouping == "detector") {
760 bool run_omb = true;
761 for (auto& ptc : ptcs) {
762 if (map_method == "naive") {
763 // naive mapmaker
765 calib.apt, telescope.d_fsmp, run_omb, run_noise);
766 }
767 else if (map_method == "jinc") {
768 // jinc mapmaker
769 jinc_mm.populate_maps_jinc_parallel(ptc, omb, cmb, ptc.map_indices.data, telescope.pixel_axes,
770 calib.apt, telescope.d_fsmp, run_omb, run_noise);
771 }
772 // update progress bar
773 pb.count(telescope.scan_indices.cols(), 1);
774 }
775 }
776
777 else {
778 // mapmaking
779 grppi::map(tula::grppi_utils::dyn_ex(map_parallel_policy), scan_in_vec, scan_out_vec, [&](auto i) {
780 bool run_omb = true;
781 // naive mapmaker
782 if (map_method == "naive") {
783 naive_mm.populate_maps_naive(ptcs[i], omb, cmb, ptcs[i].map_indices.data, telescope.pixel_axes,
784 calib.apt, telescope.d_fsmp, run_omb, run_noise);
785 }
786 else if (map_method == "jinc") {
787 jinc_mm.populate_maps_jinc(ptcs[i], omb, cmb, ptcs[i].map_indices.data, telescope.pixel_axes,
788 calib.apt, telescope.d_fsmp, run_omb, run_noise);
789 }
790
791 // update progress bar
792 pb.count(telescope.scan_indices.cols(), 1);
793
794 return 0;
795 });
796 }
797
798 // normalize maps
799 logger->info("normalizing maps");
801
802 // initial position for fitting
803 double init_row = -99;
804 double init_col = -99;
805
806 logger->info("fitting maps");
807 grppi::map(tula::grppi_utils::dyn_ex(omb.parallel_policy), det_in_vec, det_out_vec, [&](auto i) {
808 // only fit if not converged
809 if (!converged(i)) {
810 // get array number
811 auto array = maps_to_arrays(i);
812 // get initial guess fwhm from theoretical fwhms for the arrays
813 double init_fwhm = toltec_io.array_fwhm_arcsec[array]*ASEC_TO_RAD/omb.pixel_size_rad;
814 // fit the maps
815 auto [det_params, det_perror, good_fit] =
816 map_fitter.fit_to_gaussian<engine_utils::mapFitter::beammap>(omb.signal[i], omb.weight[i],
817 init_fwhm, init_row, init_col);
818
819 params.row(i) = det_params;
820 perrors.row(i) = det_perror;
821 good_fits(i) = good_fit;
822 }
823 // otherwise keep value from previous iteration
824 else {
825 params.row(i) = p0.row(i);
826 perrors.row(i) = perror0.row(i);
827 }
828
829 return 0;
830 });
831
832 logger->info("number of good fits {}/{}", good_fits.cast<double>().sum(), n_maps);
833 }
834
835 // increment loop iteration
836 current_iter++;
837
838 if (current_iter < beammap_iter_max) {
839 // check if all detectors are converged
840 if ((converged.array() == true).all()) {
841 logger->info("all maps converged");
842 keep_going = false;
843 }
844 else if (current_iter > 1) {
845 // only do convergence test if tolerance is above zero, otherwise run all iterations
846 if (beammap_iter_tolerance > 0) {
847 // loop through maps and check if it is converged
848 logger->info("checking convergence");
849 grppi::map(tula::grppi_utils::dyn_ex(omb.parallel_policy), det_in_vec, det_out_vec, [&](auto i) {
850 if (!converged(i)) {
851 // get relative change from last iteration
852 Eigen::ArrayXd diff;
853 if (!ptcproc.run_fruit_loops) {
854 diff = abs((params.row(i).array() - p0.row(i).array())/p0.row(i).array());
855 }
856 else {
857 diff = abs(omb_copy.signal[i].array() - omb.signal[i].array()/omb_copy.signal[i].array());
858 }
859 // if a variable is constant, make sure no nans are present
860 auto d = (diff.array()).isNaN().select(0,diff);
861 if ((d.array() <= beammap_iter_tolerance).all()) {
862 // set as converged
863 converged(i) = true;
864 // set convergence iteration
865 converge_iter(i) = current_iter;
866 }
867 }
868 return 0;
869 });
870
871 logger->info("{} maps converged on iter {}", (converged.array() == true).count(), current_iter);
872
873 // stop if all maps converged
874 if ((converged.array() == true).all()) {
875 logger->info("all maps converged");
876 keep_going = false;
877 }
878 }
879 else {
880 logger->info("bypassing convergence check");
881 }
882 }
883
884 // set previous iteration fits to current iteration fits
885 p0 = params;
886 perror0 = perrors;
887 }
888 else {
889 logger->info("max iteration reached");
890 keep_going = false;
891 }
892 }
893}
894
896 // setup bitwise flags
897 flag2.resize(calib.n_dets);
898 flag2.setConstant(AptFlags::Good);
899
900 // track number of flagged detectors
901 int n_flagged_dets = 0;
902
903 logger->info("flagging detectors");
904 // first flag based on fit values and signal-to-noise
905 grppi::map(tula::grppi_utils::dyn_ex(parallel_policy), det_in_vec, det_out_vec, [&](auto i) {
906 // get array of current detector
907 auto array_index = calib.apt["array"](i);
908 std::string array_name = toltec_io.array_name_map[array_index];
909
910 // calculate map standard deviation
911 double map_std_dev = engine_utils::calc_std_dev(omb.signal[i]);
912
913 // set apt signal to noise
914 calib.apt["sig2noise"](i) = params(i,0)/perrors(i,0);
915
916 // flag bad fits
917 if (!good_fits(i)) {
918 if (calib.apt["flag"](i)==0) {
919 n_flagged_dets++;
920 calib.apt["flag"](i) = 1;
921 }
923 }
924 // flag detectors with outlier a_fwhm values
925 if (calib.apt["a_fwhm"](i) < lower_fwhm_arcsec[array_name] ||
926 ((calib.apt["a_fwhm"](i) > upper_fwhm_arcsec[array_name]) && upper_fwhm_arcsec[array_name] > 0)) {
927 if (calib.apt["flag"](i)==0) {
928 n_flagged_dets++;
929 calib.apt["flag"](i) = 1;
930 }
932 }
933 // flag detectors with outlier b_fwhm values
934 if (calib.apt["b_fwhm"](i) < lower_fwhm_arcsec[array_name] ||
935 ((calib.apt["b_fwhm"](i) > upper_fwhm_arcsec[array_name] && upper_fwhm_arcsec[array_name] > 0))) {
936 if (calib.apt["flag"](i)==0) {
937 n_flagged_dets++;
938 calib.apt["flag"](i) = 1;
939 }
941 }
942 // flag detectors with outlier S/N values
943 if ((params(i,0)/map_std_dev < lower_sig2noise[array_name]) ||
944 ((params(i,0)/map_std_dev > upper_sig2noise[array_name]) && (upper_sig2noise[array_name] > 0))) {
945 if (calib.apt["flag"](i)==0) {
946 n_flagged_dets++;
947 calib.apt["flag"](i) = 1;
948 }
950 }
951 return 0;
952 });
953
954
955 // median network sensitivity for flagging
956 std::map<Eigen::Index, double> nw_median_sens;
957
958 // calc median sens from unflagged detectors for each nw
959 logger->debug("calculating mean sensitivities");
960 for (Eigen::Index i=0; i<calib.n_nws; ++i) {
961 Eigen::Index nw = calib.nws(i);
962
963 // nw sensitivity
964 auto nw_sens = calib.apt["sens"](Eigen::seq(std::get<0>(calib.nw_limits[nw]),
965 std::get<1>(calib.nw_limits[nw])-1));
966
967 // number of good detectors
968 Eigen::Index n_good_det = (calib.apt["flag"](Eigen::seq(std::get<0>(calib.nw_limits[nw]),
969 std::get<1>(calib.nw_limits[nw])-1)).array()==0).count();
970
971 if (n_good_det>0) {
972 // to hold good detectors
973 Eigen::VectorXd sens(n_good_det);
974
975 // remove flagged dets
976 Eigen::Index j = std::get<0>(calib.nw_limits[nw]);
977 Eigen::Index k = 0;
978 for (Eigen::Index m=0; m<sens.size(); m++) {
979 if (calib.apt["flag"](j)==0) {
980 sens(k) = nw_sens(m);
981 k++;
982 }
983 j++;
984 }
985 // calculate median sens
986 nw_median_sens[nw] = tula::alg::median(sens);
987 }
988 else {
989 nw_median_sens[nw] = tula::alg::median(nw_sens);
990 }
991 }
992
993
994 // flag too low/high sensitivies based on the median unflagged sensitivity of each nw
995 logger->debug("flagging sensitivities");
996 grppi::map(tula::grppi_utils::dyn_ex(parallel_policy), det_in_vec, det_out_vec, [&](auto i) {
997 // get nw of current detector
998 auto nw_index = calib.apt["nw"](i);
999
1000 // flag outlier sensitivities
1001 if (calib.apt["sens"](i) < lower_sens_factor*nw_median_sens[nw_index] ||
1002 (calib.apt["sens"](i) > upper_sens_factor*nw_median_sens[nw_index] && upper_sens_factor > 0)) {
1003 if (calib.apt["flag"](i)==0) {
1004 calib.apt["flag"](i) = 1;
1005 n_flagged_dets++;
1006 }
1007 flag2(i) |= AptFlags::Sens;
1008 }
1009
1010 return 0;
1011 });
1012
1013 // std maps to hold median unflagged x and y positions
1014 std::map<std::string, double> array_median_x_t, array_median_y_t;
1015
1016 // calc median x_t and y_t values from unflagged detectors for each arrays
1017 logger->debug("calculating array median positions");
1018 for (Eigen::Index i=0; i<calib.n_arrays; ++i) {
1019 Eigen::Index array = calib.arrays(i);
1020 std::string array_name = toltec_io.array_name_map[array];
1021
1022 // x_t
1023 auto array_x_t = calib.apt["x_t"](Eigen::seq(std::get<0>(calib.array_limits[array]),
1024 std::get<1>(calib.array_limits[array])-1));
1025 // y_t
1026 auto array_y_t = calib.apt["y_t"](Eigen::seq(std::get<0>(calib.array_limits[array]),
1027 std::get<1>(calib.array_limits[array])-1));
1028 // number of good detectors
1029 Eigen::Index n_good_det = (calib.apt["flag"](Eigen::seq(std::get<0>(calib.array_limits[array]),
1030 std::get<1>(calib.array_limits[array])-1)).array()==0).count();
1031
1032 // to hold good detectors
1033 Eigen::VectorXd x_t, y_t;
1034
1035 if (n_good_det>0) {
1036 x_t.resize(n_good_det);
1037 y_t.resize(n_good_det);
1038
1039 // remove flagged dets
1040 Eigen::Index j = std::get<0>(calib.array_limits[array]);
1041 Eigen::Index k = 0;
1042 for (Eigen::Index m=0; m<array_x_t.size(); m++) {
1043 if (calib.apt["flag"](j)==0) {
1044 x_t(k) = array_x_t(m);
1045 y_t(k) = array_y_t(m);
1046 k++;
1047 }
1048 j++;
1049 }
1050 // calculate medians
1051 array_median_x_t[array_name] = tula::alg::median(x_t);
1052 array_median_y_t[array_name] = tula::alg::median(y_t);
1053 }
1054 else {
1055 // if no good dets, use all dets to calculate median
1056 array_median_x_t[array_name] = tula::alg::median(array_x_t);
1057 array_median_y_t[array_name] = tula::alg::median(array_y_t);
1058 }
1059 }
1060
1061 // remove detectors above distance limits
1062 logger->debug("flagging detector positions");
1063 grppi::map(tula::grppi_utils::dyn_ex(parallel_policy), det_in_vec, det_out_vec, [&](auto i) {
1064 // get array of current detector
1065 auto array_index = calib.apt["array"](i);
1066 std::string array_name = toltec_io.array_name_map[array_index];
1067
1068 // calculate distance of detector from mean position of all detectors
1069 double dist = sqrt(pow(calib.apt["x_t"](i) - array_median_x_t[array_name],2) +
1070 pow(calib.apt["y_t"](i) - array_median_y_t[array_name],2));
1071
1072 // flag detectors that are further than the mean value than the distance limit
1073 if (dist > max_dist_arcsec[array_name] && max_dist_arcsec[array_name] > 0) {
1074 if (calib.apt["flag"](i)==0) {
1075 n_flagged_dets++;
1076 calib.apt["flag"](i) = 1;
1077 }
1079 }
1080
1081 return 0;
1082 });
1083
1084 // print number of flagged detectors
1085 logger->info("{} detectors were flagged", n_flagged_dets);
1086
1087 // calculate fcf
1088 logger->debug("calculating flux conversion factors");
1089 grppi::map(tula::grppi_utils::dyn_ex(parallel_policy), det_in_vec, det_out_vec, [&](auto i) {
1090 // get array of current detector
1091 auto array_index = calib.apt["array"](i);
1092 std::string array_name = toltec_io.array_name_map[array_index];
1093
1094 // calc flux scale (always in mJy/beam)
1095 if (params(i,0)!=0) {
1096 calib.apt["flxscale"](i) = beammap_fluxes_mJy_beam[array_name]/params(i,0);
1097 calib.apt["sens"](i) = calib.apt["sens"](i)*calib.apt["flxscale"](i);
1098 }
1099 // set fluxscale (fcf) to zero if flagged
1100 else {
1101 calib.apt["flxscale"](i) = 0;
1102 calib.apt["sens"](i) = 0;
1103 }
1104 return 0;
1105 });
1106
1107 // re-run calib setup to get average fwhms and beam areas
1108 calib.setup();
1109
1110 // calculate source flux in MJy/sr from average beamsizes
1111 for (Eigen::Index i=0; i<calib.n_arrays; ++i) {
1112 Eigen::Index array = calib.arrays(i);
1113 std::string array_name = toltec_io.array_name_map[array];
1114
1115 // get source flux in MJy/Sr
1117 }
1118}
1119
1121 // reference detector x and y
1122 double ref_det_x_t = 0;
1123 double ref_det_y_t = 0;
1124
1125 // initial reference det
1127
1128 // if particular reference detector is requested
1130 if (beammap_reference_det >= 0) {
1132 // set reference x_t and y_t
1133 ref_det_x_t = calib.apt["x_t"](beammap_reference_det_found);
1134 ref_det_y_t = calib.apt["y_t"](beammap_reference_det_found);
1135 }
1136 // else use closest to (0,0) in map 0 apt
1137 else {
1138 logger->info("finding a reference detector");
1139 // calc x_t and y_t values from unflagged detectors for each arrays
1140 Eigen::Index array = calib.arrays(0);
1141
1142 // x_t
1143 auto array_x_t = calib.apt["x_t"](Eigen::seq(std::get<0>(calib.array_limits[array]),
1144 std::get<1>(calib.array_limits[array])-1));
1145 // y_t
1146 auto array_y_t = calib.apt["y_t"](Eigen::seq(std::get<0>(calib.array_limits[array]),
1147 std::get<1>(calib.array_limits[array])-1));
1148 // number of good detectors
1149 Eigen::Index n_good_det = (calib.apt["flag"](Eigen::seq(std::get<0>(calib.array_limits[array]),
1150 std::get<1>(calib.array_limits[array])-1)).array()==0).count();
1151
1152 Eigen::VectorXd x_t, y_t, det_indices, dist;
1153
1154 if (n_good_det>0) {
1155 x_t.resize(n_good_det);
1156 y_t.resize(n_good_det);
1157 det_indices.resize(n_good_det);
1158
1159 // get good detector positions
1160 Eigen::Index j = std::get<0>(calib.array_limits[array]);
1161 Eigen::Index k = 0;
1162 for (Eigen::Index i=0; i<array_x_t.size(); ++i) {
1163 if (calib.apt["flag"](j)==0) {
1164 x_t(k) = array_x_t(i);
1165 y_t(k) = array_y_t(i);
1166 det_indices(k) = j;
1167 k++;
1168 }
1169 j++;
1170 }
1171
1172 // distance from (0,0)
1173 dist = pow(x_t.array(),2) + pow(y_t.array(),2);
1174 }
1175 else {
1176 dist = pow(array_x_t.array(),2) + pow(array_y_t.array(),2);
1177 det_indices = Eigen::VectorXd::LinSpaced(array_x_t.size(), std::get<0>(calib.array_limits[array]),
1178 std::get<1>(calib.array_limits[array]));
1179 }
1180
1181 // index of detector closest to zero
1182 auto min_dist = dist.minCoeff(&beammap_reference_det_found);
1183
1184 // get row in apt table
1186
1187 // set reference x_t and y_t
1188 ref_det_x_t = calib.apt["x_t"](beammap_reference_det_found);
1189 ref_det_y_t = calib.apt["y_t"](beammap_reference_det_found);
1190 }
1191 logger->info("using detector {} at ({},{}) arcsec",beammap_reference_det_found,
1192 static_cast<float>(ref_det_x_t),static_cast<float>(ref_det_y_t));
1193 }
1194 else {
1195 logger->info("no reference detector selected");
1196 }
1197
1198 // add reference detector to APT meta data
1199 calib.apt_meta["reference_x_t"] = ref_det_x_t;
1200 calib.apt_meta["reference_y_t"] = ref_det_y_t;
1201
1202 // raw (not derotated or reference detector subtracted) detector x and y values
1203 calib.apt["x_t_raw"] = calib.apt["x_t"];
1204 calib.apt["y_t_raw"] = calib.apt["y_t"];
1205
1206 // align to reference detector if specified and subtract its position from x and y
1207 calib.apt["x_t"] = calib.apt["x_t"].array() - ref_det_x_t;
1208 calib.apt["y_t"] = calib.apt["y_t"].array() - ref_det_y_t;
1209
1210 // derotated detector x and y values
1211 calib.apt["x_t_derot"] = calib.apt["x_t"];
1212 calib.apt["y_t_derot"] = calib.apt["y_t"];
1213
1214 // derotation elevation
1215 calib.apt["derot_elev"].setConstant(telescope.tel_data["TelElAct"].mean());
1216
1217 // calculate derotated positions
1218 Eigen::VectorXd rot_az_off = cos(-calib.apt["derot_elev"].array())*calib.apt["x_t_derot"].array() -
1219 sin(-calib.apt["derot_elev"].array())*calib.apt["y_t_derot"].array();
1220 Eigen::VectorXd rot_alt_off = sin(-calib.apt["derot_elev"].array())*calib.apt["x_t_derot"].array() +
1221 cos(-calib.apt["derot_elev"].array())*calib.apt["y_t_derot"].array();
1222
1223 // overwrite x_t and y_t
1224 calib.apt["x_t_derot"] = -rot_az_off;
1225 calib.apt["y_t_derot"] = -rot_alt_off;
1226
1227 if (beammap_derotate) {
1228 logger->info("derotating apt");
1229 // if derotation requested set default positions to derotated positions
1230 calib.apt["x_t"] = calib.apt["x_t_derot"];
1231 calib.apt["y_t"] = calib.apt["y_t_derot"];
1232 }
1233}
1234
1235template <mapmaking::MapType map_type>
1237 // pointer to map buffer
1238 mapmaking::MapBuffer* mb = nullptr;
1239 // pointer to data file fits vector
1240 std::vector<fitsIO<file_type_enum::write_fits, CCfits::ExtHDU*>>* f_io = nullptr;
1241 // pointer to noise file fits vector
1242 std::vector<fitsIO<file_type_enum::write_fits, CCfits::ExtHDU*>>* n_io = nullptr;
1243
1244 // directory name
1245 std::string dir_name;
1246
1247 // raw obs maps
1248 if constexpr (map_type == mapmaking::RawObs) {
1249 mb = &omb;
1250 f_io = &fits_io_vec;
1251 n_io = &noise_fits_io_vec;
1252 dir_name = obsnum_dir_name + "raw/";
1253
1254 // write stats file
1255 write_stats();
1256
1257 // add header informqtion to tod
1258 if (run_tod_output && !tod_filename.empty()) {
1260 }
1261
1262 // only write apt table if beammapping
1263 if (map_grouping=="detector") {
1264 logger->info("writing apt table");
1268
1269 Eigen::MatrixXd apt_table(calib.n_dets, calib.apt_header_keys.size());
1270
1271 // copy to table
1272 Eigen::Index i = 0;
1273 for (auto const& x: calib.apt_header_keys) {
1274 if (x != "flag2") {
1275 apt_table.col(i) = calib.apt[x];
1276 }
1277 else {
1278 apt_table.col(i) = flag2.cast<double> ();
1279 }
1280 i++;
1281 }
1282
1283 // write to ecsv
1284 to_ecsv_from_matrix(apt_filename, apt_table, calib.apt_header_keys, calib.apt_meta);
1285
1286 logger->info("done writing apt table {}.ecsv",apt_filename);
1287 }
1288 }
1289
1290 // filtered obs maps
1291 else if constexpr (map_type == mapmaking::FilteredObs) {
1292 mb = &omb;
1293 f_io = &filtered_fits_io_vec;
1295 dir_name = obsnum_dir_name + "filtered/";
1296 }
1297
1298 // raw coadded maps
1299 else if constexpr (map_type == mapmaking::RawCoadd) {
1300 mb = &cmb;
1301 f_io = &coadd_fits_io_vec;
1303 dir_name = coadd_dir_name + "raw/";
1304 }
1305
1306 // filtered coadded maps
1307 else if constexpr (map_type == mapmaking::FilteredCoadd) {
1308 mb = &cmb;
1311 dir_name = coadd_dir_name + "filtered/";
1312 }
1313
1314 if (run_mapmaking) {
1315 // wiener filtered maps write before this and are deleted from the vector.
1316 if (!f_io->empty()) {
1317 {
1318 // progress bar
1319 tula::logging::progressbar pb(
1320 [&](const auto &msg) { logger->info("{}", msg); }, 100, "output progress ");
1321
1322 for (Eigen::Index i=0; i<f_io->size(); ++i) {
1323 // get the array for the given map
1324 // add primary hdu
1325 logger->debug("adding primary header to file {}",i);
1326 add_phdu(f_io, mb, i);
1327
1328 if (!mb->noise.empty()) {
1329 logger->debug("adding primary header to noise file {}",i);
1330 add_phdu(n_io, mb, i);
1331 }
1332 }
1333
1334 logger->debug("done adding primary headers");
1335
1336 // write the maps
1337 Eigen::Index k = 0;
1338 Eigen::Index step = 2;
1339
1340 if (!mb->kernel.empty()) {
1341 step++;
1342 }
1343 if (!mb->coverage.empty()) {
1344 step++;
1345 }
1346
1347 // write the maps
1348 for (Eigen::Index i=0; i<n_maps; ++i) {
1349 // update progress bar
1350 pb.count(n_maps, 1);
1351 logger->debug("adding map");
1352 write_maps(f_io,n_io,mb,i);
1353
1354 if (map_grouping=="detector") {
1355 if constexpr (map_type == mapmaking::RawObs) {
1356 // get the array for the given map
1357 Eigen::Index map_index = arrays_to_maps(i);
1358
1359 // check if we move from one file to the next
1360 // if so go back to first hdu layer
1361 if (i>0) {
1362 if (map_index > arrays_to_maps(i-1)) {
1363 k = 0;
1364 }
1365 }
1366
1367 // add apt table
1368 logger->debug("adding beammap header keys");
1369 for (auto const& key: calib.apt_header_keys) {
1370 if (key!="flag2") {
1371 try {
1372 f_io->at(map_index).hdus.at(k)->addKey("BEAMMAP." + key, calib.apt[key](i), key
1373 + " (" + calib.apt_header_units[key] + ")");
1374 } catch(...) {
1375 f_io->at(map_index).hdus.at(k)->addKey("BEAMMAP." + key, 0.0, key
1376 + " (" + calib.apt_header_units[key] + ")");
1377 }
1378 }
1379 else {
1380 f_io->at(map_index).hdus.at(k)->addKey("BEAMMAP." + key, flag2(i), key
1381 + " (" + calib.apt_header_units[key] + ")");
1382 }
1383 }
1384 // increment hdu layer
1385 k = k + step;
1386 }
1387 }
1388 }
1389 }
1390
1391 logger->info("maps have been written to:");
1392 for (Eigen::Index i=0; i<f_io->size(); ++i) {
1393 logger->info("{}.fits",f_io->at(i).filepath);
1394 }
1395 }
1396
1397 // clear fits file vectors to ensure its closed.
1398 f_io->clear();
1399 n_io->clear();
1400
1401 if (map_grouping!="detector") {
1402 // write psd and histogram files
1403 logger->debug("writing psds");
1404 write_psd<map_type>(mb, dir_name);
1405 logger->debug("writing histograms");
1406 write_hist<map_type>(mb, dir_name);
1407 }
1408 }
1409}
1410
Definition beammap.h:16
Eigen::Vector< int, Eigen::Dynamic > converge_iter
Definition beammap.h:37
void run_loop()
Definition beammap.h:602
Eigen::Index beammap_reference_det_found
Definition beammap.h:46
Eigen::Matrix< uint16_t, Eigen::Dynamic, 1 > flag2
Definition beammap.h:60
void setup()
Definition beammap.h:101
Eigen::MatrixXd perror0
Definition beammap.h:40
AptFlags
Definition beammap.h:49
@ Position
Definition beammap.h:56
@ ElFWHM
Definition beammap.h:53
@ Good
Definition beammap.h:50
@ Sens
Definition beammap.h:55
@ AzFWHM
Definition beammap.h:52
@ Sig2Noise
Definition beammap.h:54
@ BadFit
Definition beammap.h:51
void timestream_pipeline(KidsProc &, RawObs &)
Definition beammap.h:303
void pipeline(KidsProc &, RawObs &)
Definition beammap.h:245
std::vector< int > det_in_vec
Definition beammap.h:67
std::vector< TCData< TCDataKind::PTC, Eigen::MatrixXd > > ptcs
Definition beammap.h:22
Eigen::Index current_iter
Definition beammap.h:31
void output()
Definition beammap.h:1236
std::vector< int > det_out_vec
Definition beammap.h:67
void loop_pipeline()
Definition beammap.h:434
Eigen::Matrix< bool, Eigen::Dynamic, 1 > good_fits
Definition beammap.h:63
std::vector< engine::Calib > calib_scans0
Definition beammap.h:28
std::vector< TCData< TCDataKind::PTC, Eigen::MatrixXd > > ptcs0
Definition beammap.h:22
Eigen::MatrixXd p0
Definition beammap.h:40
std::vector< int > scan_out_vec
Definition beammap.h:66
std::vector< engine::Calib > calib_scans
Definition beammap.h:28
Eigen::Matrix< bool, Eigen::Dynamic, 1 > converged
Definition beammap.h:34
Eigen::MatrixXd perrors
Definition beammap.h:43
std::string map_parallel_policy
Definition beammap.h:19
std::vector< int > scan_in_vec
Definition beammap.h:66
void set_apt_flags()
Definition beammap.h:895
mapmaking::MapBuffer omb_copy
Definition beammap.h:25
void process_apt()
Definition beammap.h:1120
Eigen::MatrixXd params
Definition beammap.h:43
auto run_timestream(KidsProc &)
Definition beammap.h:350
Definition engine.h:153
Eigen::Index hwpr_start_indices
Definition engine.h:201
void obsnum_setup()
Definition engine.h:346
std::string obsnum_dir_name
Definition engine.h:177
void write_stats()
Definition engine.h:2239
std::string parallel_policy
Definition engine.h:189
void write_map_summary(map_buffer_t &)
Definition engine.h:1574
std::map< std::string, Eigen::VectorXd > pointing_offsets_arcsec
Definition engine.h:234
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > filtered_coadd_fits_io_vec
Definition engine.h:244
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > noise_fits_io_vec
Definition engine.h:239
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > coadd_noise_fits_io_vec
Definition engine.h:243
std::string tod_output_type
Definition engine.h:216
std::string coadd_dir_name
Definition engine.h:177
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > filtered_noise_fits_io_vec
Definition engine.h:240
bool verbose_mode
Definition engine.h:165
int n_maps
Definition engine.h:222
Eigen::VectorXI arrays_to_maps
Definition engine.h:225
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > filtered_fits_io_vec
Definition engine.h:240
int n_scans_done
Definition engine.h:192
void add_tod_header()
Definition engine.h:1044
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > filtered_coadd_noise_fits_io_vec
Definition engine.h:244
void add_phdu(fits_io_type &, map_buffer_t &, Eigen::Index)
Definition engine.h:1727
std::string redu_type
Definition engine.h:207
std::string map_grouping
Definition engine.h:219
std::shared_ptr< spdlog::logger > logger
Definition engine.h:159
std::map< std::string, std::string > tod_filename
Definition engine.h:180
std::string tod_type
Definition engine.h:204
std::string obsnum
Definition engine.h:210
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > coadd_fits_io_vec
Definition engine.h:243
std::vector< std::string > date_obs
Definition engine.h:162
void write_chunk_summary(TCData< tc_t, Eigen::MatrixXd > &)
Definition engine.h:1519
std::vector< fitsIO< file_type_enum::write_fits, CCfits::ExtHDU * > > fits_io_vec
Definition engine.h:239
int n_threads
Definition engine.h:186
std::string map_method
Definition engine.h:219
void write_maps(fits_io_type &, fits_io_type &, map_buffer_t &, Eigen::Index)
Definition engine.h:2018
Eigen::Index n_nws
Definition calib.h:50
Eigen::Index n_arrays
Definition calib.h:53
std::map< Eigen::Index, std::tuple< Eigen::Index, Eigen::Index > > array_limits
Definition calib.h:56
std::map< Eigen::Index, double > array_beam_areas
Definition calib.h:65
Eigen::VectorXI nws
Definition calib.h:44
Eigen::VectorXI arrays
Definition calib.h:44
std::map< std::string, std::string > apt_header_units
Definition calib.h:116
YAML::Node apt_meta
Definition calib.h:38
std::map< std::string, Eigen::VectorXd > apt
Definition calib.h:22
std::map< std::string, std::string > apt_header_description
Definition calib.h:151
Eigen::VectorXd hwpr_angle
Definition calib.h:24
std::map< Eigen::Index, std::tuple< Eigen::Index, Eigen::Index > > nw_limits
Definition calib.h:56
std::vector< std::string > apt_header_keys
Definition calib.h:81
Eigen::Index n_dets
Definition calib.h:47
void setup()
Definition calib.cpp:245
void calc_stats(timestream::TCData< tcdata_kind, Eigen::MatrixXd > &)
Definition diagnostics.h:61
bool sim_obs
Definition telescope.h:20
std::map< std::string, Eigen::VectorXd > tel_data
Definition telescope.h:54
std::string source_name
Definition telescope.h:23
double d_fsmp
Definition telescope.h:42
double tau_225_GHz
Definition telescope.h:45
Eigen::MatrixXI scan_indices
Definition telescope.h:51
std::string project_id
Definition telescope.h:23
std::string pixel_axes
Definition telescope.h:59
std::map< std::string, Eigen::VectorXd > tel_header
Definition telescope.h:56
int n_params
Definition fitting.h:23
@ map
Definition toltec_io.h:22
std::map< Eigen::Index, std::string > array_name_map
Definition toltec_io.h:54
@ apt
Definition toltec_io.h:15
@ raw
Definition toltec_io.h:33
std::string create_filename(const std::string, const std::string, std::string, std::string, const bool)
Definition toltec_io.h:86
void populate_maps_jinc(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, map_buffer_t &, map_buffer_t &, Eigen::DenseBase< Derived > &, std::string &, apt_t &, double, bool, bool)
Definition jinc_mm.h:211
void populate_maps_jinc_parallel(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, map_buffer_t &, map_buffer_t &, Eigen::DenseBase< Derived > &, std::string &, apt_t &, double, bool, bool)
Definition jinc_mm.h:485
Definition map.h:45
void calc_median_rms()
Definition map.cpp:416
void calc_map_hist()
Definition map.cpp:346
Eigen::Index n_rows
Definition map.h:65
std::string parallel_policy
Definition map.h:59
Eigen::Index n_cols
Definition map.h:65
void calc_map_psd()
Definition map.cpp:269
std::vector< Eigen::MatrixXd > coverage
Definition map.h:78
std::vector< Eigen::MatrixXd > signal
Definition map.h:78
std::vector< Eigen::MatrixXd > weight
Definition map.h:78
bool randomize_dets
Definition map.h:87
std::vector< Eigen::MatrixXd > kernel
Definition map.h:78
Eigen::Index n_noise
Definition map.h:67
void normalize_maps()
Definition map.cpp:126
std::vector< Eigen::Tensor< double, 3 > > noise
Definition map.h:81
double pixel_size_rad
Definition map.h:69
void populate_maps_naive(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, map_buffer_t &, map_buffer_t &, Eigen::DenseBase< Derived > &, std::string &, apt_t &, double, bool, bool)
Definition naive_mm.h:95
void populate_maps_naive_parallel(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, map_buffer_t &, map_buffer_t &, Eigen::DenseBase< Derived > &, std::string &, apt_t &, double, bool, bool)
Definition naive_mm.h:439
auto calc_tau(Eigen::DenseBase< Derived > &, double)
Definition calibrate.h:128
Definition ptcproc.h:19
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
auto reset_weights(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, calib_t &, std::string)
Definition ptcproc.h:384
Definition rtcproc.h:18
void remove_flagged_dets(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, apt_t &)
Definition rtcproc.h:497
bool run_polarization
Definition rtcproc.h:23
bool run_kernel
Definition rtcproc.h:24
auto remove_nearby_tones(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, calib_t &, std::string)
Definition rtcproc.h:520
bool run_extinction
Definition rtcproc.h:29
timestream::Calibration calibration
Definition rtcproc.h:37
void append_to_netcdf(TCData< TCDataKind::PTC, Eigen::MatrixXd > &, std::string, std::string, std::string &, pointing_offset_t &, calib_t &)
Definition rtcproc.h:557
auto run(TCData< TCDataKind::RTC, Eigen::MatrixXd > &, TCData< TCDataKind::PTC, Eigen::MatrixXd > &, calib_t &, telescope_t &, double, std::string)
Definition rtcproc.h:261
void map_to_tod(mb_t &, TCData< tcdata_t, Eigen::MatrixXd > &, calib_t &, Eigen::DenseBase< Derived > &, std::string, std::string)
Definition timestream.h:624
auto remove_bad_dets(TCData< tcdata_t, Eigen::MatrixXd > &, calib_t &, std::string)
Definition timestream.h:703
@ Map
Definition timestream.h:271
@ Gaussian
Definition timestream.h:267
bool run_fruit_loops
Definition timestream.h:279
void add_gaussian(TCData< tcdata_t, Eigen::MatrixXd > &, Eigen::DenseBase< Derived > &, std::string &, std::string &, apt_t &, double, Eigen::Index, Eigen::Index)
Definition timestream.h:838
#define STD_TO_FWHM
Definition constants.h:45
#define mJY_ASEC_to_MJY_SR
Definition constants.h:54
#define RAD_TO_ASEC
Definition constants.h:36
void to_ecsv_from_matrix(std::string filepath, Eigen::DenseBase< Derived > &table, std::vector< std::string > header, YAML::Node meta)
Definition ecsv_io.h:50
static double unix_to_modified_julian_date(double unix_time)
Definition utils.h:170
auto calc_det_pointing(tel_data_t &tel_data, double az_off, double el_off, const std::string pixel_axes, pointing_offset_t &pointing_offsets, const std::string map_grouping)
Definition pointing.h:11
auto tangent_to_abs(Eigen::DenseBase< Derived > &lat, Eigen::DenseBase< Derived > &lon, const double cra, const double cdec)
Definition pointing.h:88
static const std::string current_date_time()
Definition utils.h:91
auto calc_std_dev(Eigen::DenseBase< DerivedA > &data)
Definition utils.h:336
@ FilteredObs
Definition map.h:19
@ FilteredCoadd
Definition map.h:21
@ RawObs
Definition map.h:18
@ RawCoadd
Definition map.h:20
@ Good
Definition timestream.h:27
void calc_sensitivity(std::vector< tc_t > &ptcs, Eigen::DenseBase< DerivedA > &sensitivities, Eigen::DenseBase< DerivedB > &noisefluxes, double fsmp, Eigen::Index det, internal::Interval< double > freqrange={3., 5.})
Definition sensitivity.h:259
The raw obs struct This represents a single observation that contains a set of data items and calibra...
Definition io.h:50
bool beammap_subtract_reference
Definition engine.h:131
std::map< std::string, double > lower_sig2noise
Definition engine.h:146
std::map< std::string, double > beammap_fluxes_mJy_beam
Definition engine.h:121
Eigen::Index beammap_reference_det
Definition engine.h:134
std::map< std::string, double > upper_fwhm_arcsec
Definition engine.h:146
std::map< std::string, double > max_dist_arcsec
Definition engine.h:147
double lower_sens_factor
Definition engine.h:150
std::map< std::string, double > lower_fwhm_arcsec
Definition engine.h:146
int beammap_tod_output_iter
Definition engine.h:140
std::map< std::string, double > beammap_fluxes_MJy_Sr
Definition engine.h:122
bool beammap_derotate
Definition engine.h:137
std::map< std::string, double > upper_sig2noise
Definition engine.h:147
double upper_sens_factor
Definition engine.h:150
mapmaking::NaiveMapmaker naive_mm
Definition engine.h:107
engine::Telescope telescope
Definition engine.h:94
engine_utils::mapFitter map_fitter
Definition engine.h:97
engine::Diagnostics diagnostics
Definition engine.h:96
engine_utils::toltecIO toltec_io
Definition engine.h:95
timestream::PTCProc ptcproc
Definition engine.h:103
mapmaking::JincMapmaker jinc_mm
Definition engine.h:108
mapmaking::MapBuffer omb
Definition engine.h:106
mapmaking::MapBuffer cmb
Definition engine.h:106
timestream::RTCProc rtcproc
Definition engine.h:100
engine::Calib calib
Definition engine.h:93
bool run_noise
Definition engine.h:84
bool run_tod_output
Definition engine.h:79
bool run_mapmaking
Definition engine.h:82
TC data class.
Definition timestream.h:55