73 if (ImGui::Button(fmt::format(
"Clear header##{}",
size_t(
id)).c_str()))
78 if (ImGui::Button(fmt::format(
"Select all##{}",
size_t(
id)).c_str()))
84 if (ImGui::Button(fmt::format(
"Deselect all##{}",
size_t(
id)).c_str()))
95 if (ImGui::Checkbox(fmt::format(
"Sort headers in GUI##{}",
size_t(
id)).c_str(), &
_headerLoggingSortGui))
101 std::optional<bool> regexSelect;
102 if (ImGui::Button(fmt::format(
"Select regex##{}",
size_t(
id)).c_str()))
107 if (ImGui::Button(fmt::format(
"Deselect regex##{}",
size_t(
id)).c_str()))
111 if (regexSelect.has_value())
113 bool anyChanged =
false;
119 std::regex_constants::ECMAScript | std::regex_constants::icase);
120 if (std::regex_search(desc, self_regex) && checked != *regexSelect)
123 checked = *regexSelect;
127 catch (
const std::regex_error& e)
129 LOG_ERROR(
"Regex could not be parsed: {}", e.what());
139 if (ImGui::InputText(fmt::format(
"##Select Regex {}",
size_t(
id)).c_str(), &
_headerLoggingRegex))
151 std::ranges::sort(sortedHeaderLogging);
152 headerLogging = &sortedHeaderLogging;
154 int nCols = std::min((
static_cast<int>(headerLogging->size()) - 1) / 5 + 1, 3);
155 if (ImGui::BeginChild(fmt::format(
"Headers Scrolling {}",
size_t(
id)).c_str(), ImGui::GetContentRegionAvail(),
false))
157 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)))
159 for (
auto& [desc, checked] : *headerLogging)
161 ImGui::TableNextColumn();
162 if (ImGui::Checkbox(fmt::format(
"{}##{}", desc,
size_t(
id)).c_str(), &checked))
166 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
167 return desc == header.first;
171 iter->second = checked;
185 ImGui::TextUnformatted(
"Please run the flow to collect information about the available data.");
208 if (j.contains(
"header")) { j.at(
"header").get_to(
_headerLogging); }
209 if (j.contains(
"lastConnectedType")) { j.at(
"lastConnectedType").get_to(
_lastConnectedType); }
210 if (j.contains(
"headerLoggingRegex")) { j.at(
"headerLoggingRegex").get_to(
_headerLoggingRegex); }
211 if (j.contains(
"headerLoggingDefault")) { j.at(
"headerLoggingDefault").get_to(
_headerLoggingDefault); }
221 LOG_TRACE(
"{}: called for {} ==> {}",
nameId(),
size_t(startPin.id),
size_t(endPin.id));
225 LOG_DEBUG(
"{}: [{} ==> {}] Dropping headers because last type [{}] and new type [{}]",
nameId(),
size_t(startPin.id),
size_t(endPin.id),
_lastConnectedType, startPin.dataIdentifier.front());
259 _filestream <<
"Time [s],GpsCycle,GpsWeek,GpsToW [s]";
261#if LOG_LEVEL <= LOG_LEVEL_TRACE
262 std::string headers =
"Time [s],GpsCycle,GpsWeek,GpsToW [s]";
268 if (!enabled) {
continue; }
272#if LOG_LEVEL <= LOG_LEVEL_TRACE
273 headers +=
"," + header;
279#if LOG_LEVEL <= LOG_LEVEL_TRACE
288 LOG_TRACE(
"{}: Rewriting header, because {} new elements",
nameId(), newSize - oldSize);
291 std::filesystem::rename(
getFilepath(), tmpFilePath);
295 std::ifstream tmpFilestream(tmpFilePath, std::ios_base::in | std::ios_base::binary);
296 if (tmpFilestream.good())
298 std::string delimiterEnd(newSize - oldSize,
',');
300 std::getline(tmpFilestream, line);
301 while (std::getline(tmpFilestream, line) && !tmpFilestream.eof())
306 if (tmpFilestream.is_open()) { tmpFilestream.close(); }
307 tmpFilestream.clear();
308 std::filesystem::remove(tmpFilePath);
315 auto oldHeaderLength =
static_cast<size_t>(std::ranges::count_if(
_headerLogging, [](
const auto& header) {
return header.second; }));
318 for (
const auto& desc : obs->staticDataDescriptors())
320 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
321 return desc == header.first;
330 for (
const auto& desc : obs->dynamicDataDescriptors())
332 if (std::ranges::none_of(
_dynamicHeader, [&](
const auto& header) {
return header == desc; }))
336 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
337 return desc == header.first;
348 else if (
auto newHeaderLength =
static_cast<size_t>(std::ranges::count_if(
_headerLogging, [](
const auto& header) {
return header.second; }));
349 oldHeaderLength != newHeaderLength)
354 constexpr int gpsCyclePrecision = 3;
355 constexpr int gpsTimePrecision = 12;
356 constexpr int valuePrecision = 15;
358 if (!obs->insTime.empty())
363 if (!obs->insTime.empty())
365 _filestream << std::fixed << std::setprecision(gpsCyclePrecision) << obs->insTime.toGPSweekTow().gpsCycle;
368 if (!obs->insTime.empty())
370 _filestream << std::defaultfloat << std::setprecision(gpsTimePrecision) << obs->insTime.toGPSweekTow().gpsWeek;
373 if (!obs->insTime.empty())
375 _filestream << std::defaultfloat << std::setprecision(gpsTimePrecision) << obs->insTime.toGPSweekTow().tow;
379 size_t dataLogged = 0;
380 const auto staticDataDescriptors = obs->staticDataDescriptors();
381 for (
size_t i = 0; i < obs->staticDescriptorCount(); ++i)
383 const auto& desc = staticDataDescriptors.at(i);
384 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
385 return desc == header.first;
393 if (
auto val = obs->getValueAt(i)) {
_filestream << *val; }
398 if (
auto iter = std::ranges::find_if(
_headerLogging, [&](
const std::pair<std::string, bool>& header) {
399 return desc == header.first;
407 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.
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.
InputPin * CreateInputPin(Node *node, 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.
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.