add asibfm700_pcm_fit.cpp: PCM data fitter
This commit is contained in:
182
asibfm700_pcm_fit.cpp
Normal file
182
asibfm700_pcm_fit.cpp
Normal file
@@ -0,0 +1,182 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <print>
|
||||
#include <ranges>
|
||||
|
||||
#include <cxxopts.hpp>
|
||||
|
||||
#include <mcc/mcc_coordinate.h>
|
||||
#include <mcc/mcc_pcm_fit.h>
|
||||
|
||||
static constexpr mcc::MccMountType MOUNT_TYPE{mcc::MccMountType::CROSSAXIS_TYPE};
|
||||
|
||||
// #include "asibfm700_configfile.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
/* COMMANDLINE OPTS */
|
||||
cxxopts::Options options(argv[0], "Astrosib (c) FM700 mount PCM fitter\n");
|
||||
|
||||
options.allow_unrecognised_options();
|
||||
|
||||
options.add_options()("h,help", "Print usage");
|
||||
|
||||
options.add_options()("v,verbose", "Verbose output");
|
||||
|
||||
options.add_options()("input_file", "Input encoder-celestial coordinate pairs file",
|
||||
cxxopts::value<std::string>()->default_value("pcm_coords.dat"));
|
||||
|
||||
options.add_options()("c,config", "Mount configuration filename (by default use of hardcoded one)",
|
||||
cxxopts::value<std::string>()->default_value(""));
|
||||
|
||||
options.positional_help("[input_encoder-celestial_pair_filename]");
|
||||
options.parse_positional({"input_file"});
|
||||
|
||||
mcc::impl::MccPCMFitter<MOUNT_TYPE> pcm_fitter;
|
||||
|
||||
try {
|
||||
auto opt_result = options.parse(argc, argv);
|
||||
|
||||
if (opt_result["help"].count() || argc == 1) {
|
||||
std::println("{}", options.help());
|
||||
|
||||
std::println(
|
||||
"[input_encoder-celestial_pair_filename] - Input encoder-celestial coordinate pairs filename. "
|
||||
"It must be in the format: ENCODER_HA ENCODER_DEC ENCODER_EPOCH RA_ICRS DEC_ICRS TEMP(C) PRESSURE(hPa) "
|
||||
"HUMIDITY([0-1])",
|
||||
options.help());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool verbose = false;
|
||||
if (opt_result["verbose"].count()) {
|
||||
verbose = true;
|
||||
}
|
||||
|
||||
std::ifstream fst;
|
||||
|
||||
auto fname = opt_result["input_file"].as<std::string>();
|
||||
fst.open(fname);
|
||||
if (!fst.is_open()) {
|
||||
std::println("Cannot open input file {}", fname);
|
||||
return 2;
|
||||
}
|
||||
|
||||
size_t sz;
|
||||
double temp, press, humi;
|
||||
std::optional<double> num;
|
||||
std::string str;
|
||||
std::string_view sv;
|
||||
std::array<std::string_view, 8> tokens;
|
||||
|
||||
mcc::impl::MccCelestialCoordEpoch ep;
|
||||
mcc::impl::MccAngleX enc_ha;
|
||||
mcc::impl::MccAngleY enc_dec;
|
||||
mcc::impl::MccAngleRA_ICRS ra;
|
||||
mcc::impl::MccAngleDEC_ICRS dec;
|
||||
|
||||
mcc::impl::MccSkyPoint sp;
|
||||
mcc::impl::MccError err;
|
||||
|
||||
while (!fst.eof()) {
|
||||
std::getline(fst, str);
|
||||
|
||||
sv = mcc::utils::trimSpaces(str);
|
||||
if (!sv.size()) { // an empty string
|
||||
continue;
|
||||
}
|
||||
if (sv[0] == '#') { // comment
|
||||
continue;
|
||||
}
|
||||
|
||||
auto toks = std::views::split(sv, std::string_view(" ")) |
|
||||
std::views::filter([](auto const& r) { return std::ranges::size(r); });
|
||||
|
||||
sz = std::ranges::distance(toks.begin(), toks.end());
|
||||
if (sz < 8) {
|
||||
std::println("Invalid input file format! Number of tokens must be at least 8: {}", str);
|
||||
return 3;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
for (auto const& t : toks) {
|
||||
tokens[i++] = {t.begin(), t.end()};
|
||||
}
|
||||
|
||||
// degrees or sexagesimal hours representations
|
||||
enc_ha = {tokens[0], mcc::impl::mcc_hms};
|
||||
|
||||
// degrees or sexagesimal degrees representations
|
||||
enc_dec = {tokens[1]};
|
||||
|
||||
if (!ep.fromCharRange(tokens[2])) {
|
||||
std::println("Invalid input file format! Invalid encoder coordinates epoch representation: {}",
|
||||
tokens[2]);
|
||||
return 4;
|
||||
}
|
||||
|
||||
// degrees or sexagesimal hours representations
|
||||
ra = {tokens[3], mcc::impl::mcc_hms};
|
||||
|
||||
// degrees or sexagesimal degrees representations
|
||||
dec = {tokens[4]};
|
||||
|
||||
num = mcc::utils::numFromStr<double>(tokens[5]);
|
||||
if (!num) {
|
||||
std::println("Invalid input file format! Non-numeric representation of temperature: {}", tokens[5]);
|
||||
return 5;
|
||||
}
|
||||
temp = num.value();
|
||||
|
||||
num = mcc::utils::numFromStr<double>(tokens[6]);
|
||||
if (!num) {
|
||||
std::println("Invalid input file format! Non-numeric representation of pressure: {}", tokens[6]);
|
||||
return 6;
|
||||
}
|
||||
press = num.value();
|
||||
|
||||
num = mcc::utils::numFromStr<double>(tokens[7]);
|
||||
if (!num) {
|
||||
std::println("Invalid input file format! Non-numeric representation of humidity: {}", tokens[7]);
|
||||
return 7;
|
||||
}
|
||||
humi = num.value();
|
||||
|
||||
mcc::impl::MccSkyPoint::cctEngine.updateMeteoERFA(
|
||||
{.temperature = temp, .humidity = humi, .pressure = press});
|
||||
|
||||
sp.from(mcc::impl::MccSkyRADEC_ICRS{ra, dec});
|
||||
|
||||
err = pcm_fitter.addPoint(sp, mcc::impl::MccGenXY{enc_ha, enc_dec, ep});
|
||||
if (err) {
|
||||
std::println("An error occured: {}", err.message());
|
||||
return 8;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
std::println("{} {} {:.5f} {} {} {:.1f} {:.2f} {:.2f}", enc_ha.sexagesimal(true),
|
||||
enc_dec.sexagesimal(), ep.MJD(), ra.sexagesimal(true), dec.sexagesimal(), temp, press,
|
||||
humi);
|
||||
}
|
||||
}
|
||||
|
||||
fst.close();
|
||||
|
||||
} catch (cxxopts::exceptions::parsing& ex) {
|
||||
std::println("An error occured while parsing input options: {}", ex.what());
|
||||
|
||||
return 1;
|
||||
} catch (std::exception& ex) {
|
||||
std::println("An exception occured: {}", ex.what());
|
||||
|
||||
return 10;
|
||||
|
||||
} catch (...) {
|
||||
std::println("An unhandled exception occured!");
|
||||
|
||||
return 100;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user