71 if (ImGui::Button(fmt::format(
"Clear header##{}",
size_t(
id)).c_str()))
76 if (ImGui::Button(fmt::format(
"Select all##{}",
size_t(
id)).c_str()))
82 if (ImGui::Button(fmt::format(
"Deselect all##{}",
size_t(
id)).c_str()))
93 if (ImGui::Checkbox(fmt::format(
"Sort headers in GUI##{}",
size_t(
id)).c_str(), &
_headerLoggingSortGui))
99 std::optional<bool> regexSelect;
100 if (ImGui::Button(fmt::format(
"Select regex##{}",
size_t(
id)).c_str()))
105 if (ImGui::Button(fmt::format(
"Deselect regex##{}",
size_t(
id)).c_str()))
109 if (regexSelect.has_value())
111 bool anyChanged =
false;
117 std::regex_constants::ECMAScript | std::regex_constants::icase);
118 if (std::regex_search(desc, self_regex) && checked != *regexSelect)
121 checked = *regexSelect;
125 catch (
const std::regex_error& e)
127 LOG_ERROR(
"Regex could not be parsed: {}", e.what());
137 if (ImGui::InputText(fmt::format(
"##Select Regex {}",
size_t(
id)).c_str(), &
_headerLoggingRegex))
149 std::ranges::sort(sortedHeaderLogging);
150 headerLogging = &sortedHeaderLogging;
152 int nCols = std::min((
static_cast<int>(headerLogging->size()) - 1) / 5 + 1, 3);
153 if (ImGui::BeginChild(fmt::format(
"Headers Scrolling {}",
size_t(
id)).c_str(), ImGui::GetContentRegionAvail(),
false))
155 if (ImGui::BeginTable(fmt::format(
"Logging headers##{}",
size_t(
id)).c_str(), nCols, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
157 for (
auto& [desc, checked] : *headerLogging)
159 ImGui::TableNextColumn();
160 if (ImGui::Checkbox(fmt::format(
"{}##{}", desc,
size_t(
id)).c_str(), &checked))
164 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
165 return desc == header.first;
169 iter->second = checked;
183 ImGui::TextUnformatted(
"Please run the flow to collect information about the available data.");
206 if (j.contains(
"header")) { j.at(
"header").get_to(
_headerLogging); }
207 if (j.contains(
"lastConnectedType")) { j.at(
"lastConnectedType").get_to(
_lastConnectedType); }
208 if (j.contains(
"headerLoggingRegex")) { j.at(
"headerLoggingRegex").get_to(
_headerLoggingRegex); }
209 if (j.contains(
"headerLoggingDefault")) { j.at(
"headerLoggingDefault").get_to(
_headerLoggingDefault); }
219 LOG_TRACE(
"{}: called for {} ==> {}",
nameId(),
size_t(startPin.id),
size_t(endPin.id));
223 LOG_DEBUG(
"{}: [{} ==> {}] Dropping headers because last type [{}] and new type [{}]",
nameId(),
size_t(startPin.id),
size_t(endPin.id),
_lastConnectedType, startPin.dataIdentifier.front());
257 _filestream <<
"Time [s],GpsCycle,GpsWeek,GpsToW [s]";
259#if LOG_LEVEL <= LOG_LEVEL_TRACE
260 std::string headers =
"Time [s],GpsCycle,GpsWeek,GpsToW [s]";
266 if (!enabled) {
continue; }
270#if LOG_LEVEL <= LOG_LEVEL_TRACE
271 headers +=
"," + header;
277#if LOG_LEVEL <= LOG_LEVEL_TRACE
286 LOG_TRACE(
"{}: Rewriting header, because {} new elements",
nameId(), newSize - oldSize);
289 std::filesystem::rename(
getFilepath(), tmpFilePath);
293 std::ifstream tmpFilestream(tmpFilePath, std::ios_base::in | std::ios_base::binary);
294 if (tmpFilestream.good())
296 std::string delimiterEnd(newSize - oldSize,
',');
298 std::getline(tmpFilestream, line);
299 while (std::getline(tmpFilestream, line) && !tmpFilestream.eof())
304 if (tmpFilestream.is_open()) { tmpFilestream.close(); }
305 tmpFilestream.clear();
306 std::filesystem::remove(tmpFilePath);
313 auto oldHeaderLength =
static_cast<size_t>(std::ranges::count_if(
_headerLogging, [](
const auto& header) {
return header.second; }));
316 for (
const auto& desc : obs->staticDataDescriptors())
318 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
319 return desc == header.first;
328 for (
const auto& desc : obs->dynamicDataDescriptors())
330 if (std::ranges::none_of(
_dynamicHeader, [&](
const auto& header) {
return header == desc; }))
334 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
335 return desc == header.first;
346 else if (
auto newHeaderLength =
static_cast<size_t>(std::ranges::count_if(
_headerLogging, [](
const auto& header) {
return header.second; }));
347 oldHeaderLength != newHeaderLength)
352 constexpr int gpsCyclePrecision = 3;
353 constexpr int gpsTimePrecision = 12;
354 constexpr int valuePrecision = 15;
356 if (!obs->insTime.empty())
361 if (!obs->insTime.empty())
363 _filestream << std::fixed << std::setprecision(gpsCyclePrecision) << obs->insTime.toGPSweekTow().gpsCycle;
366 if (!obs->insTime.empty())
368 _filestream << std::defaultfloat << std::setprecision(gpsTimePrecision) << obs->insTime.toGPSweekTow().gpsWeek;
371 if (!obs->insTime.empty())
373 _filestream << std::defaultfloat << std::setprecision(gpsTimePrecision) << obs->insTime.toGPSweekTow().tow;
377 size_t dataLogged = 0;
378 const auto staticDataDescriptors = obs->staticDataDescriptors();
379 for (
size_t i = 0; i < obs->staticDescriptorCount(); ++i)
381 const auto& desc = staticDataDescriptors.at(i);
382 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
383 return desc == header.first;
391 if (
auto val = obs->getValueAt(i)) {
_filestream << *val; }
396 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
397 return desc == header.first;
405 if (
auto val = obs->getDynamicDataAt(desc)) {
_filestream << *val; }
Data Logger for CSV files.
nlohmann::json json
json namespace
Utility class for logging to console and file.
#define LOG_DEBUG
Debug information. Should not be called on functions which receive observations (spamming)
#define LOG_DATA
All output which occurs repeatedly every time observations are received.
#define LOG_ERROR
Error occurred, which stops part of the program to work, but not everything.
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Utility class which specifies available nodes.
Utility functions for working with std::strings.
static bool ShowOriginInput(const char *id)
Shows a GUI to input a origin location.
void initialize() const
Initialize the common log variables.
static double calcTimeIntoRun(const InsTime &insTime)
Calculates the relative time into he run.
void guiConfig() override
ImGui config window which is shown on double click.
bool _headerLoggingSortGui
Sort headers in the GUI.
static std::string typeStatic()
String representation of the Class Type.
std::vector< std::pair< std::string, bool > > _headerLogging
Header which should be logged.
bool initialize() override
Initialize the node.
void rewriteData(size_t oldSize, size_t newSize)
Rewrites the data file with a new size.
std::vector< std::string > _dynamicHeader
Dynamic Header.
bool _headerWritten
Flag whether the header was written already.
void restore(const json &j) override
Restores the node from a json object.
json save() const override
Saves the node into a json object.
void writeObservation(InputPin::NodeDataQueue &queue, size_t pinIdx)
Write Observation to the file.
std::string _lastConnectedType
Type last connected.
bool onCreateLink(OutputPin &startPin, InputPin &endPin) override
Called when a new link is to be established.
std::string type() const override
String representation of the Class Type.
void writeHeader()
Writes the header.
bool _headerLoggingDefault
Default for new headers.
void flush() override
Function called by the flow executer after finishing to flush out remaining data.
~CsvLogger() override
Destructor.
static std::string category()
String representation of the Class Category.
std::string _headerLoggingRegex
Regex to search for when selecting.
size_t _headerLoggingCount
Amount of headers which are logged.
CsvLogger()
Default constructor.
void deinitialize() override
Deinitialize the node.
FileType _fileType
File Type.
void deinitialize()
Deinitialize the file reader.
bool guiConfig(const char *vFilters, const std::vector< std::string > &extensions, size_t id, const std::string &nameId)
ImGui config.
std::filesystem::path getFilepath()
Returns the path of the file.
void restore(const json &j)
Restores the node from a json object.
json save() const
Saves the node into a json object.
bool initialize()
Initialize the file reader.
std::ofstream _filestream
File stream to write the file.
static std::string type()
Returns the type of the data class.
bool doDeinitialize(bool wait=false)
Asks the node worker to deinitialize the node.
ImVec2 _guiConfigDefaultWindowSize
Node(std::string name)
Constructor.
std::string nameId() const
Node name and id.
std::string name
Name of the Node.
InputPin * CreateInputPin(const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier={}, InputPin::Callback callback=static_cast< InputPin::FlowFirableCallbackFunc >(nullptr), InputPin::FlowFirableCheckFunc firable=nullptr, int priority=0, int idx=-1)
Create an Input Pin object.
bool _hasConfig
Flag if the config window should be shown.
auto extract_front()
Returns a copy of the first element in the container and removes it from the container.
static float windowFontRatio()
Ratio to multiply for GUI window elements.
void ApplyChanges()
Signals that there have been changes to the flow.
static std::string replaceAll_copy(std::string str, const std::string &from, const std::string &to, CaseSensitivity cs)
Replaces all occurrence of a search pattern with another sequence.