0.4.1
Loading...
Searching...
No Matches
ConfigManager.cpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#include "ConfigManager.hpp"
10
11#include <string>
12#include <filesystem>
13#include <fstream>
14#include <iostream>
15#include <boost/program_options/parsers.hpp>
16#include <implot.h>
17#include <implot_internal.h>
18#include <fmt/ranges.h>
19
21#include "util/Logger.hpp"
22
23#include <boost/tokenizer.hpp>
24
25#include "util/Json.hpp"
28
29namespace bpo = boost::program_options;
30
31/// Program option description
32bpo::options_description program_options{ "Allowed options" }; // NOLINT
33
34/// Map which stores all options
35boost::program_options::variables_map NAV::ConfigManager::vm; // NOLINT
36
38{
39 LOG_TRACE("called");
40
41 if (program_options.options().empty())
42 {
43 // clang-format off
44 // See https://www.boost.org/doc/libs/1_72_0/doc/html/program_options.html
45 program_options.add_options()
46 ("config", bpo::value<std::vector<std::string>>()->multitoken(), "List of configuration files to read parameters from" )
47 ("version,v", "Display the version number" )
48 ("help,h", "Display this help message" )
49 ("sigterm", bpo::bool_switch()->default_value(false), "Programm waits for -SIGUSR1 / -SIGINT / -SIGTERM" )
50 ("duration", bpo::value<size_t>()->default_value(0), "Program execution duration [sec]" )
51 ("nogui", bpo::bool_switch()->default_value(false), "Launch without the gui" )
52 ("noinit", bpo::bool_switch()->default_value(false), "Do not initialize flows after loading them" )
53 ("load,l", bpo::value<std::string>(), "Flow file to load" )
54 ("rotate-output", bpo::bool_switch()->default_value(false), "Create new folders for output files" )
55 ("output-path,o", bpo::value<std::string>()->default_value("logs"), "Directory path for logs and output files" )
56 ("input-path,i", bpo::value<std::string>()->default_value("data"), "Directory path for searching input files" )
57 ("flow-path,f", bpo::value<std::string>()->default_value("flow"), "Directory path for searching flow files" )
58 ("implot-config", bpo::value<std::string>()->default_value("implot.json"), "Config file to read implot settings from" )
59 ("global-log-level", bpo::value<std::string>()->default_value("trace"), "Global log level of all sinks (possible values: trace/debug/info/warning/error/critical/off" )
60 ("console-log-level", bpo::value<std::string>()->default_value("info"), "Log level on the console (possible values: trace/debug/info/warning/error/critical/off" )
61 ("file-log-level", bpo::value<std::string>()->default_value("debug"), "Log level to the log file (possible values: trace/debug/info/warning/error/critical/off" )
62 ("flush-log-level", bpo::value<std::string>()->default_value("info"), "Log level to flush on (possible values: trace/debug/info/warning/error/critical/off" )
63 ("log-filter", bpo::value<std::string>(), "Filter/Regex for log messages" )
64 ;
65 // clang-format on
66 }
67}
68
70{
71 vm.clear();
72}
73
74const boost::program_options::options_description& NAV::ConfigManager::GetProgramOptions()
75{
76 return program_options;
77}
78
79std::vector<std::string> NAV::ConfigManager::FetchConfigs(const int argc, const char* argv[]) // NOLINT
80{
81 bpo::store(bpo::parse_command_line(argc, argv, program_options), vm);
82
83 std::vector<std::string> failedConfigFiles;
84
85 // if config file is available, the parameters from file will be added
86 if (vm.count("config"))
87 {
88 for (const std::string& configFile : vm["config"].as<std::vector<std::string>>())
89 {
90 std::filesystem::path filepath{ configFile };
91 if (filepath.is_relative())
92 {
94 filepath /= configFile;
95 }
96
97 std::ifstream ifs{ filepath };
98 if (ifs.good())
99 {
100 bpo::store(bpo::parse_config_file(ifs, program_options), vm);
101 }
102 else
103 {
104 failedConfigFiles.push_back(configFile);
105 }
106 }
107 }
108
109 bpo::notify(vm);
110
111 return failedConfigFiles;
112}
113
114void NAV::ConfigManager::CheckOptions(const int argc, [[maybe_unused]] const char* argv[]) // NOLINT
115{
116 LOG_DEBUG("{} arguments were provided over the command line", argc);
117
118 for (const char* logger : { "global-log-level", "console-log-level", "file-log-level", "flush-log-level" })
119 {
120 if (vm[logger].as<std::string>() != "trace"
121 && vm[logger].as<std::string>() != "debug"
122 && vm[logger].as<std::string>() != "info"
123 && vm[logger].as<std::string>() != "warning"
124 && vm[logger].as<std::string>() != "error"
125 && vm[logger].as<std::string>() != "critical"
126 && vm[logger].as<std::string>() != "off")
127 {
128 LOG_CRITICAL("The command line argument '{}' has to be one of 'trace/debug/info/warning/error/critical/off' but the value '{}' was provided", logger, vm[logger].as<std::string>());
129 }
130 }
131
132 for (int i = 0; i < argc; i++)
133 {
134 LOG_DEBUG("\targument[{}] = '{}'", i, argv[i]);
135 }
136
137 LOG_DEBUG("{} arguments are set in the allowed variable map", vm.size());
138
139 for (const auto& value : vm)
140 {
141 if ([[maybe_unused]] const auto* v = boost::any_cast<size_t>(&value.second.value()))
142 {
143 LOG_DEBUG("\tvm[{}] = '{}'", value.first, *v);
144 }
145 else if ([[maybe_unused]] const auto* v = boost::any_cast<bool>(&value.second.value())) // NOLINT(bugprone-bool-pointer-implicit-conversion)
146 {
147 LOG_DEBUG("\tvm[{}] = '{}'", value.first, *v);
148 }
149 else if ([[maybe_unused]] const auto* v = boost::any_cast<std::string>(&value.second.value()))
150 {
151 LOG_DEBUG("\tvm[{}] = '{}'", value.first, *v);
152 }
153 else if ([[maybe_unused]] const auto* v = boost::any_cast<std::vector<std::string>>(&value.second.value()))
154 {
155 LOG_DEBUG("\tvm[{}] = '{}'", value.first, fmt::join(v->begin(), v->end(), ", "));
156 }
157 else
158 {
159 LOG_ERROR("The Log option vm[{}] could not be casted. Please report this to the developers.", value.first);
160 }
161 }
162}
163
164bool NAV::ConfigManager::HasKey(const std::string& key)
165{
166 return vm.count(key);
167}
168
169std::vector<std::string> NAV::ConfigManager::GetKeys()
170{
171 std::vector<std::string> keys;
172
173 for (auto& param : vm)
174 {
175 keys.push_back(param.first);
176 }
177
178 return keys;
179}
180
182{
183 // Save also global settings
184 std::ofstream filestream(flow::GetConfigPath() / "globals.json");
185 json j;
186#ifdef IMGUI_IMPL_OPENGL_LOADER_GL3W
187 j["plotScreenshotImPlotStyleFile"] = gui::windows::plotScreenshotImPlotStyleFile;
188 j["copyScreenshotsToClipboard"] = gui::windows::copyScreenshotsToClipboard;
189#endif
190 j["colormaps"] = ColormapsGlobal;
191
192 ImPlotContext& gp = *ImPlot::GetCurrentContext();
193 j["selectedImPlotColormap"] = gp.Style.Colormap;
194
195 constexpr int CMAP_USER_START = ImPlotColormap_Greys + 2;
196 for (int i = CMAP_USER_START; i < gp.ColormapData.Count; ++i)
197 {
198 j["ImPlotColormaps"][static_cast<size_t>(i - CMAP_USER_START)]["name"] = gp.ColormapData.GetName(i);
199 j["ImPlotColormaps"][static_cast<size_t>(i - CMAP_USER_START)]["qual"] = gp.ColormapData.IsQual(i);
200 for (int c = 0; c < gp.ColormapData.GetKeyCount(i); ++c)
201 {
202 j["ImPlotColormaps"][static_cast<size_t>(i - CMAP_USER_START)]["colors"][static_cast<size_t>(c)] =
203 ImGui::ColorConvertU32ToFloat4(gp.ColormapData.GetKeyColor(i, c));
204 }
205 }
206
207 filestream << std::setw(4) << j << std::endl; // NOLINT(performance-avoid-endl)
208}
209
211{
212 auto filepath = flow::GetConfigPath() / "globals.json";
213 std::ifstream filestream(filepath);
214
215 if (!filestream.good())
216 {
217 LOG_ERROR("Load Flow error: Could not open file: {}", filepath);
218 return;
219 }
220 json j;
221 filestream >> j;
222
223 if (j.contains("colormaps"))
224 {
225 j.at("colormaps").get_to(ColormapsGlobal);
226 }
227#ifdef IMGUI_IMPL_OPENGL_LOADER_GL3W
228 if (j.contains("plotScreenshotImPlotStyleFile"))
229 {
230 j.at("plotScreenshotImPlotStyleFile").get_to(gui::windows::plotScreenshotImPlotStyleFile);
231 }
232 if (j.contains("copyScreenshotsToClipboard"))
233 {
234 j.at("copyScreenshotsToClipboard").get_to(gui::windows::copyScreenshotsToClipboard);
235 }
236#endif
237 if (j.contains("ImPlotColormaps"))
238 {
239 for (size_t i = 0; i < j["ImPlotColormaps"].size(); ++i)
240 {
241 ImVector<ImVec4> custom;
242 for (const auto& c : j.at("ImPlotColormaps").at(i).at("colors"))
243 {
244 custom.push_back(c.get<ImVec4>());
245 }
246
247 ImPlot::AddColormap(j.at("ImPlotColormaps").at(i).at("name").get<std::string>().c_str(),
248 custom.Data, custom.Size, j.at("ImPlotColormaps").at(i).at("qual").get<bool>());
249 ImPlot::BustItemCache();
250 }
251 }
252 if (j.contains("selectedImPlotColormap"))
253 {
254 ImPlotContext& gp = *ImPlot::GetCurrentContext();
255 gp.Style.Colormap = j.at("selectedImPlotColormap").get<int>();
256 ImPlot::BustItemCache();
257 }
258}
Colormap.
bpo::options_description program_options
Program option description.
Config management for the Project.
Save/Load the Nodes.
nlohmann::json json
json namespace
Defines how to save certain datatypes to json.
Utility class for logging to console and file.
#define LOG_CRITICAL(...)
Critical Event, which causes the program to work entirely and throws an exception.
Definition Logger.hpp:75
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
Definition Logger.hpp:67
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
Definition Logger.hpp:73
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Definition Logger.hpp:65
Screenshot utility.
void LoadGlobalSettings()
Loads the global settings.
void initialize()
Initializes the config manager. Call this function before using other functions.
boost::program_options::variables_map vm
Map which stores all options.
void CheckOptions(const int argc, const char *argv[])
Writes all command line options into the log.
bool HasKey(const std::string &key)
Checks if a corresponding key exists in the configuration.
std::vector< std::string > GetKeys()
Returns all keys in the configuration, as a vector.
std::vector< std::string > FetchConfigs(const int argc, const char *argv[])
Fetches the configs from the command line parameters.
const boost::program_options::options_description & GetProgramOptions()
Get the Program Options object.
void deinitialize()
Deinitializes the config manager. Call this if you want to Fetch config again.
void SaveGlobalSettings()
Saves the global settings.
std::filesystem::path GetConfigPath()
Get the path where config files are searched.
std::filesystem::path GetProgramRootPath()
Get the program root path.
std::vector< Colormap > ColormapsGlobal
Global colormaps.
Definition Colormap.cpp:26