Citlali
Loading...
Searching...
No Matches
kidsproc.h
Go to the documentation of this file.
1#pragma once
2
3#include <kids/core/kidsdata.h>
4#include <kids/sweep/fitter.h>
5#include <kids/timestream/solver.h>
6#include <kids/toltec/toltec.h>
7#include <kidscpp_config/gitversion.h>
8
9#include <tula/datatable.h>
10
12
18bool extra_output = 0;
19struct KidsDataProc : ConfigMapper<KidsDataProc> {
21 using Fitter = kids::SweepFitter;
22 using Solver = kids::TimeStreamSolver;
23
24 // get logger
25 std::shared_ptr<spdlog::logger> logger = spdlog::get("citlali_logger");
26
27 KidsDataProc(config_t config)
28 : Base{std::move(config)},
30 {"weight_window_type", this->config().get_str(std::tuple{
31 "fitter", "weight_window", "type"})},
32 {"weight_window_fwhm", this->config().get_typed<double>(
33 std::tuple{"fitter", "weight_window", "fwhm_Hz"})},
34 {"modelspec", config.get_str(std::tuple{"fitter", "modelspec"})}}},
35 m_solver{Solver::Config{
36 {"fitreportdir", this->config().get_str(std::tuple{"solver", "fitreportdir"})},
37 {"exmode", this->config().get_str(std::tuple{"solver", "parallel_policy"})},
38 {"extra_output", extra_output},
39 }} {}
40
41 static auto check_config(const config_t &config)
42 -> std::optional<std::string> {
43 // get logger
44 std::shared_ptr<spdlog::logger> logger = spdlog::get("citlali_logger");
45
46 std::vector<std::string> missing_keys;
47 logger->debug("check kids data proc config\n{}", config);
48 if (!config.has("fitter")) {
49 missing_keys.push_back("fitter");
50 }
51 if (!config.has("solver")) {
52 missing_keys.push_back("solver");
53 }
54 if (missing_keys.empty()) {
55 return std::nullopt;
56 }
57 return fmt::format("invalid or missing keys={}", missing_keys);
58 }
59
60 // get data item meta data
61 auto get_data_item_meta(const RawObs::DataItem &);
62
63 // get meta data from rawobs
64 std::vector<kids::KidsData<>::meta_t> get_rawobs_meta(const RawObs &);
65
66 // populate rtc meta data
67 auto populate_rtc_meta(const RawObs &);
68
69 // reduce data item
70 auto reduce_data_item(const RawObs::DataItem &,
71 const tula::container_utils::Slice<int> &);
72 // reduce rawobs
73 auto reduce_rawobs(const RawObs &rawobs,
74 const tula::container_utils::Slice<int> &);
75 // load data item
76 auto load_data_item(const RawObs::DataItem &,
77 const tula::container_utils::Slice<int> &);
78 // load kids fit report
79 auto load_fit_report(const RawObs &);
80
81 // load rawobs
82 template <typename Derived>
83 auto load_rawobs(const RawObs &, const Eigen::Index,
84 Eigen::DenseBase<Derived> &,
85 std::vector<Eigen::Index> &,
86 std::vector<Eigen::Index> &);
87
88 // populate rtc
89 template <typename loaded_t>
90 auto populate_rtc(loaded_t &, const int, const int,
91 const std::string);
92
93 // load rawobs with gaps
94 template <typename DerivedA, typename DerivedB, typename DerivedC>
95 auto load_rawobs_gaps(const RawObs &, const Eigen::Index,
96 Eigen::DenseBase<DerivedA>&,
97 std::vector<Eigen::Index>&,
98 Eigen::DenseBase<DerivedB>&,
99 std::vector<DerivedC>&,
100 const double);
101
102 // populate rtc with gaps
103 template <typename LoadedType, typename DerivedA, typename DerivedB, typename DerivedC, typename DerivedD>
104 auto populate_rtc_gaps(LoadedType &, Eigen::DenseBase<DerivedA>&,
105 std::vector<DerivedB>&,
106 std::vector<DerivedC>&,
107 const int, const double,
108 Eigen::DenseBase<DerivedD>&,
109 const int, const int, const std::string);
110
111 // TODO fix the const correctness
112 Fitter &fitter() { return m_fitter; }
113 Solver &solver() { return m_solver; }
114
115 const Fitter &fitter() const { return m_fitter; }
116 const Solver &solver() const { return m_solver; }
117
118 template <typename OStream>
119 friend OStream &operator<<(OStream &os, const KidsDataProc &kidsproc) {
120 return os << fmt::format("KidsDataProc(fitter={}, solver={})",
121 kidsproc.fitter().config.pformat(),
122 kidsproc.solver().config.pformat());
123 }
124
125private:
126 // fitter and solver
129};
130
132 namespace kidsdata = predefs::kidsdata;
133 auto source = data_item.filepath();
134 auto [kind, meta] = kidsdata::get_meta<>(source);
135 return meta;
136}
137
138std::vector<kids::KidsData<>::meta_t> KidsDataProc::get_rawobs_meta(const RawObs &rawobs) {
139 std::vector<kids::KidsData<>::meta_t> result;
140 for (const auto &data_item : rawobs.kidsdata()) {
141 result.push_back(get_data_item_meta(data_item));
142 }
143 return result;
144}
145
147 std::vector<kids::KidsData<>::meta_t> result;
148 for (const auto &data_item : rawobs.kidsdata()) {
149 result.push_back(get_data_item_meta(data_item));
150 }
151 return result;
152}
153
155 const tula::container_utils::Slice<int> &slice) {
156 logger->debug("kids reduce data_item {}", data_item);
157 // read data
158 namespace kidsdata = predefs::kidsdata;
159 auto source = data_item.filepath();
160 auto [kind, meta] = kidsdata::get_meta<>(source);
161 if (!(kind & kids::KidsDataKind::TimeStream)) {
162 throw std::runtime_error(
163 fmt::format("wrong type of kids data {}", kind));
164 }
165 auto rts = kidsdata::read_data_slice<kids::KidsDataKind::RawTimeStream>(
166 source, slice);
167 auto result = this->solver()(rts, Solver::Config{});
168 return result;
169}
170
172 const tula::container_utils::Slice<int> &slice) {
173 logger->debug("kids reduce rawobs {}", rawobs);
174 std::vector<kids::TimeStreamSolverResult> result;
175 for (const auto &data_item : rawobs.kidsdata()) {
176 result.push_back(reduce_data_item(data_item, slice));
177 }
178 return result;
179}
180
182 const tula::container_utils::Slice<int> &slice) {
183 logger->debug("kids reduce data_item {}", data_item);
184 // read data
185 namespace kidsdata = predefs::kidsdata;
186 auto source = data_item.filepath();
187 auto [kind, meta] = kidsdata::get_meta<>(source);
188 if (!(kind & kids::KidsDataKind::TimeStream)) {
189 throw std::runtime_error(
190 fmt::format("wrong type of kids data {}", kind));
191 }
192 auto rts = kidsdata::read_data_slice<kids::KidsDataKind::RawTimeStream>(
193 source, slice);
194 return rts;
195}
196
198 std::vector<Eigen::MatrixXd> kids_models;
199 std::vector<std::string> header;
200
201 for (const auto &data_item : rawobs.kidsdata()) {
202 auto meta = get_data_item_meta(data_item);
203 //auto fitreport = this->solver().loadfitreport(this->config(),meta);
204
205 namespace fs = std::filesystem;
206 auto pattern = meta.get_str("cal_file");
207 std::string filepath{};
208 if (this->solver().config.has("fitreportfile")) {
209 filepath = this->solver().config.get_str("fitreportfile");
210 } else if (this->solver().config.has("fitreportdir")) {
211 auto dir = this->solver().config.get_str("fitreportdir");
212 logger->info("look for fitreport dir {} with pattern {}", dir, pattern);
213 auto candidates = tula::filename_utils::find_regex(dir, pattern);
214 if (!candidates.empty()) {
215 filepath = candidates[0];
216 } else {
217 throw std::runtime_error(fmt::format(
218 "no fit report found in {} that matches {}", dir, pattern));
219 }
220 } else {
221 throw std::runtime_error(
222 fmt::format("no fit report location specified."));
223 }
224 logger->info("use fitreport file {}", filepath);
225 //std::vector<std::string> header;
226 header.clear();
227 Eigen::MatrixXd table;
228 using meta_t = kids::KidsData<>::meta_t;
229 meta_t meta_cal{};
230
231 try {
232 YAML::Node meta_;
233 table = datatable::read<double, datatable::Format::ecsv>(
234 filepath, &header, &meta_);
235 auto meta_map =
236 tula::ecsv::meta_to_map<typename meta_t::storage_t::key_type,
237 typename meta_t::storage_t::mapped_type>(
238 meta_, &meta_);
239 meta_cal = meta_t{std::move(meta_map)};
240
241 kids_models.push_back(std::move(table));
242 if (!meta_.IsNull()) {
243 logger->warn("un recongnized meta:\n{}", YAML::Dump(meta_));
244 }
245 } catch (datatable::ParseError &e) {
246 logger->warn("unable to read fitreport file as ECSV {}: {}", filepath,
247 e.what());
248 try {
249 table = datatable::read<double, datatable::Format::ascii>(filepath,
250 &header);
251 kids_models.push_back(std::move(table));
252
253 } catch (datatable::ParseError &e) {
254 logger->warn("unable to read fitreport file as ASCII {}: {}",
255 filepath, e.what());
256 throw e;
257 }
258 }
259 logger->info("meta_cal: {}", meta_cal.pformat());
260 logger->info("table {}",table);
261 logger->info("header {}",header);
262
263 //return std::tuple{
264 // kids::ToneAxis(std::move(table).transpose(), std::move(header)),
265 // std::move(meta_cal)};
266 }
267
268 return std::tuple{std::move(kids_models), std::move(header)};
269}
270
271template <typename Derived>
272auto KidsDataProc::load_rawobs(const RawObs &rawobs, const Eigen::Index scan,
273 Eigen::DenseBase<Derived> &scan_indices,
274 std::vector<Eigen::Index> &start_indices,
275 std::vector<Eigen::Index> &end_indices) {
276
277 std::vector<kids::KidsData<kids::KidsDataKind::RawTimeStream>> result;
278 Eigen::Index i = 0;
279 for (const auto &data_item : rawobs.kidsdata()) {
280 // get slice of data for current scan
281 auto slice = tula::container_utils::Slice<int>{scan_indices(2,scan) + start_indices[i],
282 scan_indices(3,scan) + 1 + start_indices[i],
283 std::nullopt};
284 result.push_back(load_data_item(data_item, slice));
285
286 i++;
287 }
288
289 return result;
290}
291
292template <typename loaded_t>
293auto KidsDataProc::populate_rtc(loaded_t &loaded,
294 const int n_pts, const int n_det,
295 const std::string data_type) {
296 // resize data
297 Eigen::MatrixXd data(n_pts, n_det);
298
299 Eigen::Index i = 0;
300 // loop through raw timestream objects
301 for (std::vector<kids::KidsData<kids::KidsDataKind::RawTimeStream>>::
302 iterator it = loaded.begin(); it != loaded.end(); ++it) {
303 // run the solver
304 auto result = this->solver()(*it, Solver::Config{});
305 // get number of rows
306 Eigen::Index n_rows = result.data_out.xs.data.rows();
307 // get number of cols
308 Eigen::Index n_cols = result.data_out.xs.data.cols();
309
310 // get xs
311 if (data_type == "xs") {
312 data.block(0, i, n_rows, n_cols) = result.data_out.xs.data;
313 }
314 // get rs
315 else if (data_type == "rs") {
316 data.block(0, i, n_rows, n_cols) = result.data_out.rs.data;
317 }
318 // get is
319 else if (data_type == "is") {
320 data.block(0, i, n_rows, n_cols) = result.data.is.data;
321 }
322 // get qs
323 else if (data_type == "qs") {
324 data.block(0, i, n_rows, n_cols) = result.data.qs.data;
325 }
326 // increment columns
327 i += n_cols;
328 }
329
330 // check for nans
331 if ((data.array().isNaN()).any()) {
332 logger->error("nan found in data! Check that your KIDs data dir is correct.");
333 std::exit(EXIT_FAILURE);
334 }
335 // check for infs
336 if ((data.array().isInf()).any()) {
337 logger->error("inf found in data! Check that your KIDs data dir is correct.");
338 std::exit(EXIT_FAILURE);
339 }
340
341 return data;
342}
343
344template <typename DerivedA, typename DerivedB, typename DerivedC>
345auto KidsDataProc::load_rawobs_gaps(const RawObs &rawobs, const Eigen::Index scan,
346 Eigen::DenseBase<DerivedA>& scan_indices,
347 std::vector<Eigen::Index>& start_indices,
348 Eigen::DenseBase<DerivedB>& t_common,
349 std::vector<DerivedC>& times,
350 const double tol) {
351
352 std::vector<kids::KidsData<kids::KidsDataKind::RawTimeStream>> result;
353
354 double t0 = t_common(scan_indices(2, scan));
355 double t1 = t_common(scan_indices(3, scan));
356
357 int i = 0;
358 for (const auto &data_item : rawobs.kidsdata()) {
359 Eigen::Index i_start = 0;
360 while (i_start < times[i].size()) {
361 double t = times[i](i_start);
362 if (t >= t0 - tol) {
363 if (t > t0 + tol) {
364 i_start--;
365 }
366 break;
367 }
368 ++i_start;
369 }
370
371 Eigen::Index i_end = i_start;
372 while (i_end < times[i].size()) {
373 double t = times[i](i_end);
374 if (t >= t1 - tol) {
375 if (t > t1 + tol) {
376 i_end--;
377 }
378 break;
379 }
380 ++i_end;
381 }
382
383 // get slice of data for current scan
384 auto slice = tula::container_utils::Slice<int>{i_start, i_end + 1,
385 std::nullopt};
386 result.push_back(load_data_item(data_item, slice));
387
388 ++i;
389 }
390
391 return result;
392}
393
394template <typename LoadedType, typename DerivedA, typename DerivedB, typename DerivedC, typename DerivedD>
395auto KidsDataProc::populate_rtc_gaps(LoadedType &loaded, Eigen::DenseBase<DerivedA>& t_common,
396 std::vector<DerivedB>& times,
397 std::vector<DerivedC>& masks,
398 const int scan,
399 const double tol,
400 Eigen::DenseBase<DerivedD>& scan_indices,
401 const int n_pts, const int n_det, const std::string data_type) {
402 // resize data
403 Eigen::MatrixXd data(n_pts, n_det);
404
405 double t0 = t_common(scan_indices(2, scan));
406 double t1 = t_common(scan_indices(3, scan));
407
408 Eigen::Index i = 0, j = 0;
409 // loop through raw timestream objects
410 for (std::vector<kids::KidsData<kids::KidsDataKind::RawTimeStream>>::
411 iterator it = loaded.begin(); it != loaded.end(); ++it) {
412 // run the solver
413 auto result = this->solver()(*it, Solver::Config{});
414 // get number of rows
415 Eigen::Index n_rows = result.data_out.xs.data.rows();
416 // get number of cols
417 Eigen::Index n_cols = result.data_out.xs.data.cols();
418
419 Eigen::MatrixXd block(n_rows, n_cols);
420
421 // get xs
422 if (data_type == "xs") {
423 block = result.data_out.xs.data;
424 } else if (data_type == "rs") {
425 block = result.data_out.rs.data;
426 } else if (data_type == "is") {
427 block = result.data.is.data;
428 } else if (data_type == "qs") {
429 block = result.data.qs.data;
430 }
431
432 Eigen::Index i_start = 0;
433 while (i_start < times[j].size()) {
434 double t = times[j](i_start);
435 if (t >= t0 - tol) {
436 if (t > t0 + tol) {
437 i_start--;
438 }
439 break;
440 }
441 ++i_start;
442 }
443
444 Eigen::Index i_end = i_start;
445 while (i_end < times[j].size()) {
446 double t = times[j](i_end);
447 if (t >= t1 - tol) {
448 if (t > t1 + tol) {
449 i_end--;
450 }
451 break;
452 }
453 ++i_end;
454 }
455
456 block = engine_utils::interp_data(t_common.segment(scan_indices(2,scan), n_pts),
457 masks[j].segment(scan_indices(2,scan), n_pts),
458 times[j].segment(i_start, i_end - i_start + 1),
459 block);
460
461 data.block(0, i, n_pts, n_cols) = block;
462 // increment columns
463 i += n_cols;
464 j++;
465 }
466
467 // check for nans
468 if ((data.array().isNaN()).any()) {
469 logger->error("nan found in data! Check that your KIDs data dir is correct.");
470 std::exit(EXIT_FAILURE);
471 }
472 // check for infs
473 if ((data.array().isInf()).any()) {
474 logger->error("inf found in data! Check that your KIDs data dir is correct.");
475 std::exit(EXIT_FAILURE);
476 }
477
478 return data;
479}
config::Config Config
Definition kids_main.cpp:17
bool extra_output
The KIDs data solver struct This wraps around the kids config.
Definition kidsproc.h:18
config::ConfigValidatorMixin< Derived, config::YamlConfig > ConfigMapper
Definition main_old.cpp:124
static Eigen::MatrixXd interp_data(const Eigen::VectorXd &t_common, const Eigen::VectorXi &mask, const Eigen::VectorXd &t_valid, const Eigen::MatrixXd &data_valid)
Definition utils.h:1218
Definition timestream.h:59
Definition kidsproc.h:19
Solver & solver()
Definition kidsproc.h:113
auto reduce_rawobs(const RawObs &rawobs, const tula::container_utils::Slice< int > &)
Definition kidsproc.h:171
Solver m_solver
Definition kidsproc.h:128
const Solver & solver() const
Definition kidsproc.h:116
auto load_rawobs_gaps(const RawObs &, const Eigen::Index, Eigen::DenseBase< DerivedA > &, std::vector< Eigen::Index > &, Eigen::DenseBase< DerivedB > &, std::vector< DerivedC > &, const double)
Definition kidsproc.h:345
Fitter & fitter()
Definition kidsproc.h:112
static auto check_config(const config_t &config) -> std::optional< std::string >
Definition kidsproc.h:41
auto get_data_item_meta(const RawObs::DataItem &)
Definition kidsproc.h:131
auto load_fit_report(const RawObs &)
Definition kidsproc.h:197
auto populate_rtc_meta(const RawObs &)
Definition kidsproc.h:146
friend OStream & operator<<(OStream &os, const KidsDataProc &kidsproc)
Definition kidsproc.h:119
std::shared_ptr< spdlog::logger > logger
Definition kidsproc.h:25
kids::SweepFitter Fitter
Definition kidsproc.h:21
auto reduce_data_item(const RawObs::DataItem &, const tula::container_utils::Slice< int > &)
Definition kidsproc.h:154
ConfigMapper< KidsDataProc > Base
Definition kidsproc.h:20
std::vector< kids::KidsData<>::meta_t > get_rawobs_meta(const RawObs &)
Definition kidsproc.h:138
auto load_data_item(const RawObs::DataItem &, const tula::container_utils::Slice< int > &)
Definition kidsproc.h:181
auto load_rawobs(const RawObs &, const Eigen::Index, Eigen::DenseBase< Derived > &, std::vector< Eigen::Index > &, std::vector< Eigen::Index > &)
Definition kidsproc.h:272
KidsDataProc(config_t config)
Definition kidsproc.h:27
const Fitter & fitter() const
Definition kidsproc.h:115
auto populate_rtc(loaded_t &, const int, const int, const std::string)
Definition kidsproc.h:293
auto populate_rtc_gaps(LoadedType &, Eigen::DenseBase< DerivedA > &, std::vector< DerivedB > &, std::vector< DerivedC > &, const int, const double, Eigen::DenseBase< DerivedD > &, const int, const int, const std::string)
Definition kidsproc.h:395
kids::TimeStreamSolver Solver
Definition kidsproc.h:22
Fitter m_fitter
Definition kidsproc.h:127
The DataItem struct This represent a single data item that belongs to a particular observation.
Definition io.h:58
const std::string & filepath() const
Definition io.h:81
The raw obs struct This represents a single observation that contains a set of data items and calibra...
Definition io.h:50
auto kidsdata() const -> decltype(auto)
Definition io.h:283