diff --git a/asibfm700_configfile.h b/asibfm700_configfile.h index 16b9c3c..381f99e 100644 --- a/asibfm700_configfile.h +++ b/asibfm700_configfile.h @@ -852,16 +852,19 @@ public: } } else if constexpr (std::ranges::range && std::formattable, char>) { size_t sz = std::ranges::size(v); - if (!sz) { - return; - } - --sz; + // if (!sz) { + // return; + // } - auto it = v.begin(); - for (size_t j = 0; j < sz; ++j, ++it) { - fst << std::format("{}", *it) << base_t::VALUE_ARRAY_DELIM; + if (sz) { + --sz; + + auto it = v.begin(); + for (size_t j = 0; j < sz; ++j, ++it) { + fst << std::format("{}", *it) << base_t::VALUE_ARRAY_DELIM; + } + fst << std::format("{}", *it); } - fst << std::format("{}", *it); } else if constexpr (std::formattable) { fst << std::format("{}", v); } else { diff --git a/asibfm700_pcm_fit.cpp b/asibfm700_pcm_fit.cpp index 75a54c8..bb674d4 100644 --- a/asibfm700_pcm_fit.cpp +++ b/asibfm700_pcm_fit.cpp @@ -235,8 +235,9 @@ int main(int argc, char* argv[]) std::println("{}", str); auto fmt = std::format("*{{:^{}}}*", fmt_head.size() - 2); - std::println("{}", std::vformat(std::string_view(fmt.begin(), fmt.end()), - std::make_format_args(" FITTED HARDWARE-CELESTIAL COORDINATE PAIRS "))); + std::println("{}", + std::vformat(std::string_view(fmt.begin(), fmt.end()), + std::make_format_args(" HARDWARE-CELESTIAL COORDINATE PAIRS TO BE FITTED "))); std::println("{}", str); @@ -256,10 +257,13 @@ int main(int argc, char* argv[]) } } - return 0; + // return 0; - if (pcm_data.type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY || - pcm_data.type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE) { + if (pcm_data.type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY +#ifdef USE_BSPLINE_PCM + || pcm_data.type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE +#endif + ) { if (opt_result["niter"].count()) { comp_pars.max_iter = opt_result["niter"].as() ? opt_result["niter"].as() : 100; } @@ -269,10 +273,130 @@ int main(int argc, char* argv[]) if (comp_result.error) { std::println("An error occured while fit PCM data: {}", comp_result.error.message()); +#ifdef USE_BSPLINE_PCM + if (comp_result.pcm_type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE || + comp_result.pcm_type == mcc::impl::MccDefaultPCMType::PCM_TYPE_BSPLINE) { + std::println("\tB-spline fitting error codes: {}", comp_result.bspline_fit_err); + } +#endif return 200; } + auto tab = pcm_fitter.getPCMTable(); + std::ofstream ofst; + + ofst.open(result_fname, std::ios_base::trunc); + if (!ofst.is_open()) { + std::println("<<< CANNOT OPEN RESULT FILE: {}! >>>", result_fname); + verbose = true; // print result to the console + } + + + fmt_head = std::format("{:^12}{}{:^11}{}{:^12}{}{:^11}{}{:^12}{}{:^12}{}{:^12}{}{:^12}{}{:^7}{}{:^8}", + "ENC_HA(degs)", delim, "ENC_DEC(degs)", delim, "OBS_HA(degs)", delim, "OBS_DEC(degs)", + delim, "dHA(OBS-ENC, degs)", delim, "dDEC(OBS-ENC, degs)", delim, "dHA_FIT(degs)", delim, + "dDEC_FIT(degs)", delim, "EPS_dHA", delim, "EPS_dDEC"); + + if (comp_result.pcm_type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY +#ifdef USE_BSPLINE_PCM + || pcm_data.type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE +#endif + ) { // Tukey's weights of the points computed during fitting + std::format_to(std::back_inserter(fmt_head), "{}{:^7}{}{:^8}", delim, "dHA_WEI", delim, "dDEC_WEI"); + } +#ifdef USE_BSPLINE_PCM + else if (comp_result.pcm_type == mcc::impl::MccDefaultPCMType::PCM_TYPE_BSPLINE) { // inverse PCM fitting + std::format_to(std::back_inserter(fmt_head), "{}{:^17}{}{:^18}{}{:^12}{}{:^12}", delim, "dHA_FIT_INV(degs)", + delim, "dDEC_FIT_INV(degs)", delim, "EPS_dHA_INV", delim, "EPS_dDEC_INV"); + } +#endif + + sv = "POINTING CORRECTION MODEL FITTING RESULTS"; + std::vector info{ + std::format("{} {}", " SITE LAT:", mount_cfg.siteLatitude().sexagesimal()), + std::format("{} {}", " SITE LON:", mount_cfg.siteLongitude().sexagesimal()), + std::format("{} {} meters", " SITE ELEV:", mount_cfg.siteElevation()), + std::format("{} {} ", " PCM TYPE:", mcc::impl::mccDefaultPCMTypeString(pcm_data.type))}; + + + if (ofst.is_open()) { + ofst << "#\n"; + ofst << std::format("# {} ({} UTC)\n", sv, std::chrono::system_clock::now()); + ofst << "#\n"; + for (auto const& s : info) { + ofst << std::format("# {}\n", s); + } + + ofst << "#\n# Format:\n"; + ofst << std::format("# {}\n", fmt_head); + ofst << "#\n"; + } + + if (verbose) { + std::println("\n"); + + str = std::string(fmt_head.size(), '*'); + std::println("{}", str); + + auto fmt = std::format("*{{:^{}}}*", fmt_head.size() - 2); + auto fmt_sv = std::string_view(fmt.begin(), fmt.end()); + + std::println("{}", std::vformat(fmt_sv, std::make_format_args(sv))); + + std::println("{}", std::vformat(fmt_sv, std::make_format_args(""))); + + for (auto const& s : info) { + std::println("{}", std::vformat(fmt_sv, std::make_format_args(s))); + } + + std::println("{}", str); + + std::println("{}", fmt_head); + std::println("{}", std::string(fmt_head.size(), '-')); + } + + size_t i = 0; + double dha_eps, ddec_eps; + for (auto const& el : tab) { + dha_eps = std::abs(comp_result.colon_err[i] / comp_result.model_colonRES[i]); + ddec_eps = std::abs(comp_result.colat_err[i] / comp_result.model_colatRES[i]); + + str = std::format( + "{:>12.7f}{}{:>11.7f}{}{:>12.7f}{}{:>11.7f}{}{:>12.7f}{}{:>12.7f}{}{:>12.7f}{}{:>12.7f}{}{:>7.3f}", + el.hw.x().degrees(), delim, el.hw.y().degrees(), delim, el.target.x().degrees(), delim, + el.target.y().degrees(), delim, el.res.x().degrees(), delim, el.res.y().degrees(), delim, + comp_result.model_colonRES[i] * mcc::MCC_RADS_TO_DEGRESS, delim, + comp_result.model_colatRES[i] * mcc::MCC_RADS_TO_DEGRESS, delim, dha_eps, delim, ddec_eps); + + if (comp_result.pcm_type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY +#ifdef USE_BSPLINE_PCM + || pcm_data.type == mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY_BSPLINE +#endif + ) { + std::format_to(std::back_inserter(str), "{}{:>7.3f}{}{:>8.3f}", delim, comp_result.colon_weight[i], + delim, comp_result.colat_weight[i]); + } +#ifdef USE_BSPLINE_PCM + else if (comp_result.pcm_type == mcc::impl::MccDefaultPCMType::PCM_TYPE_BSPLINE) { // inverse PCM fitting + std::format_to(std::back_inserter(str), "{}{:^17.7}{}{:^18.7}{}{:^12.7}{}{:^12.7}", delim, + comp_result.inv_model_colonRES[i], delim, comp_result.inv_model_colatRES[i], delim, + comp_result.inv_colon_err[i], delim, comp_result.inv_colat_err[i]); + } +#endif + + ++i; + + if (ofst.is_open()) { + ofst << std::format(" {}\n", str); + } + + if (verbose) { + std::println("{}", str); + } + } + + ofst.close(); } catch (cxxopts::exceptions::parsing& ex) { std::println("An error occured while parsing input options: {}", ex.what());