0.4.1
Loading...
Searching...
No Matches
CsvFile.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 "CsvFile.hpp"
10#include <algorithm>
11#include <string>
12#include <vector>
13
14#include "util/Logger.hpp"
15#include "util/StringUtil.hpp"
16
18namespace nm = NAV::NodeManager;
21
23 : Node(typeStatic())
24{
25 LOG_TRACE("{}: called", name);
26
27 _hasConfig = true;
28 _guiConfigDefaultWindowSize = { 530, 271 };
29
31}
32
34{
35 LOG_TRACE("{}: called", nameId());
36}
37
39{
40 return "CsvFile";
41}
42
43std::string NAV::CsvFile::type() const
44{
45 return typeStatic();
46}
47
49{
50 return "Data Provider";
51}
52
54{
55 if (auto res = FileReader::guiConfig(".csv,.*", { ".csv" }, size_t(id), nameId()))
56 {
57 LOG_DEBUG("{}: Path changed to {}", nameId(), _path);
59 if (res == FileReader::PATH_CHANGED)
60 {
62 }
63 else
64 {
66 }
67 }
68
69 struct TextFilters
70 {
71 // Cuts off characters if the length exceeds 1
72 static int FilterSingleCharacter(ImGuiInputTextCallbackData* data)
73 {
74 while (data->BufTextLen > 1)
75 {
76 data->BufDirty = true;
77 data->DeleteChars(1, 1);
78 }
79 return 0;
80 }
81 };
82
83 std::string tmpStr(1, _delimiter);
84 if (ImGui::InputText(fmt::format("Delimiter character##{}", size_t(id)).c_str(), &tmpStr, ImGuiInputTextFlags_CallbackEdit, TextFilters::FilterSingleCharacter))
85 {
86 _delimiter = tmpStr.empty() ? '\0' : tmpStr.at(0);
87 LOG_DEBUG("{}: Delimiter character changed to {}", nameId(), _delimiter);
89 if (_delimiter)
90 {
92 }
93 }
94
95 tmpStr = std::string(1, _comment);
96 if (ImGui::InputText(fmt::format("Comment character##{}", size_t(id)).c_str(), &tmpStr, ImGuiInputTextFlags_CallbackEdit, TextFilters::FilterSingleCharacter))
97 {
98 _comment = tmpStr.empty() ? '\0' : tmpStr.at(0);
99 LOG_DEBUG("{}: Comment character changed to {}", nameId(), _comment);
101 doInitialize();
102 }
103
104 if (ImGui::InputIntL(fmt::format("Skip lines##{}", size_t(id)).c_str(), &_skipLines, 0, std::numeric_limits<int>::max()))
105 {
106 LOG_DEBUG("{}: Skip lines changed to {}", nameId(), _skipLines);
108 doInitialize();
109 }
110
111 if (ImGui::Checkbox(fmt::format("Header line##{}", size_t(id)).c_str(), &_hasHeaderLine))
112 {
113 LOG_DEBUG("{}: HasHeaderLine changed to {}", nameId(), _hasHeaderLine);
115 doInitialize();
116 }
117
118 ImGui::Separator();
119
120 ImGui::Text("Amount of data lines in file: %zu", _data.lines.size());
121
122 // Header info
123 if (ImGui::BeginTable(fmt::format("##CSVHeaders ({})", size_t(id)).c_str(), 2,
124 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
125 {
126 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
127 ImGui::TableSetupColumn("Description", ImGuiTableColumnFlags_WidthFixed);
128 ImGui::TableHeadersRow();
129
130 for (size_t i = 0; i < _data.description.size(); i++)
131 {
132 ImGui::TableNextRow();
133 ImGui::TableNextColumn();
134 ImGui::Text("%zu", i);
135 ImGui::TableNextColumn();
136 ImGui::TextUnformatted(_data.description[i].c_str());
137 }
138
139 ImGui::EndTable();
140 }
141}
142
143[[nodiscard]] json NAV::CsvFile::save() const
144{
145 LOG_TRACE("{}: called", nameId());
146
147 json j;
148
149 j["FileReader"] = FileReader::save();
150 j["delimiter"] = _delimiter;
151 j["comment"] = _comment;
152 j["skipLines"] = _skipLines;
153 j["hasHeaderLine"] = _hasHeaderLine;
154
155 return j;
156}
157
159{
160 LOG_TRACE("{}: called", nameId());
161
162 if (j.contains("FileReader"))
163 {
164 FileReader::restore(j.at("FileReader"));
165 }
166 if (j.contains("delimiter"))
167 {
168 j.at("delimiter").get_to(_delimiter);
169 }
170 if (j.contains("comment"))
171 {
172 j.at("comment").get_to(_comment);
173 }
174 if (j.contains("skipLines"))
175 {
176 j.at("skipLines").get_to(_skipLines);
177 }
178 if (j.contains("hasHeaderLine"))
179 {
180 j.at("hasHeaderLine").get_to(_hasHeaderLine);
181 }
182}
183
185{
186 LOG_TRACE("{}: called", nameId());
187
188 _data.description.clear();
189 _data.lines.clear();
190
192 {
193 return false;
194 }
195
196 std::string line;
197 std::vector<size_t> emptyCols{};
198 while (!eof())
199 {
200 getline(line);
201 if (line.empty() || line.at(0) == _comment) { continue; } // Skip empty and comment lines
202
203 auto splittedData = str::split(line, _delimiter);
204 if (!splittedData.empty()) { _data.lines.emplace_back(); }
205
206 for (size_t i = 0; i < splittedData.size(); i++)
207 {
208 const auto& cell = splittedData.at(i);
209
210 if (cell.empty() && std::ranges::find(emptyCols, i) == emptyCols.end())
211 {
212 emptyCols.push_back(i);
213 LOG_WARN("{}: Data missing in column: '{}' at: {} s and possibly afterwards, too.", nameId(), _data.description.at(i), splittedData.front());
214 }
215
217 try
218 {
219 value = std::stod(cell);
220 }
221 catch (...)
222 {
223 value = cell;
224 }
225 _data.lines.back().push_back(value);
226 }
227 }
228
229 LOG_TRACE("{}: initialize() finished. Read {} columns over {} lines.", nameId(), _data.description.size(), _data.lines.size());
230
231 return true;
232}
233
235{
236 LOG_TRACE("{}: called", nameId());
237 return true;
238}
239
241{
242 LOG_TRACE("{}: called", nameId());
243
244 _data.description.clear();
245 _data.lines.clear();
246
248}
249
254
256{
257 for (int i = 0; i < _skipLines; i++) { ignore(std::numeric_limits<std::streamsize>::max(), '\n'); } // Skip lines at the start of the file
258
259 std::string line;
260 if (_hasHeaderLine)
261 {
262 getline(line);
263 _data.description = str::split(line, _delimiter);
264 for (auto& desc : _data.description)
265 {
266 desc.erase(std::ranges::find_if(desc, [](int ch) { return std::iscntrl(ch); }), desc.end());
267 }
268 }
269}
CSV File reader.
Save/Load the Nodes.
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)
Definition Logger.hpp:67
#define LOG_WARN
Error occurred, but a fallback option exists and program continues to work normally.
Definition Logger.hpp:71
#define LOG_TRACE
Detailled info to trace the execution of the program. Should not be called on functions which receive...
Definition Logger.hpp:65
Manages all Nodes.
Utility functions for working with std::strings.
static std::string type()
Returns the type of the data class.
Definition CsvData.hpp:28
std::variant< double, std::string > CsvElement
CSV Elements (number or if not convertible to number as std::string)
Definition CsvData.hpp:31
void guiConfig() override
ImGui config window which is shown on double click.
Definition CsvFile.cpp:53
FileType determineFileType() override
Determines the type of the file.
Definition CsvFile.cpp:250
bool initialize() override
Initialize the node.
Definition CsvFile.cpp:184
int _skipLines
Amount of lines to skip at the start.
Definition CsvFile.hpp:86
void deinitialize() override
Deinitialize the node.
Definition CsvFile.cpp:240
static std::string category()
String representation of the Class Category.
Definition CsvFile.cpp:48
CsvFile()
Default constructor.
Definition CsvFile.cpp:22
char _comment
Comment character.
Definition CsvFile.hpp:83
void readHeader() override
Read the Header of the file.
Definition CsvFile.cpp:255
std::string type() const override
String representation of the Class Type.
Definition CsvFile.cpp:43
void restore(const json &j) override
Restores the node from a json object.
Definition CsvFile.cpp:158
~CsvFile() override
Destructor.
Definition CsvFile.cpp:33
char _delimiter
Delimiter character.
Definition CsvFile.hpp:80
CsvData _data
Data container.
Definition CsvFile.hpp:77
bool _hasHeaderLine
Flag whether there is a header line at the start.
Definition CsvFile.hpp:89
bool resetNode() override
Resets the node. It is guaranteed that the node is initialized when this is called.
Definition CsvFile.cpp:234
static std::string typeStatic()
String representation of the Class Type.
Definition CsvFile.cpp:38
json save() const override
Saves the node into a json object.
Definition CsvFile.cpp:143
bool initialize()
Initialize the file reader.
void restore(const json &j)
Restores the node from a json object.
std::string _path
Path to the file.
FileType
File Type Enumeration.
@ ASCII
Ascii text data.
auto & ignore(std::streamsize count, int delim)
Extracts and discards characters from the input stream until and including delim.
auto eof() const
Check whether the end of file is reached.
@ PATH_CHANGED
The path changed and exists.
GuiResult guiConfig(const char *vFilters, const std::vector< std::string > &extensions, size_t id, const std::string &nameId)
ImGui config.
auto & getline(std::string &str)
Reads a line from the filestream.
json save() const
Saves the node into a json object.
void deinitialize()
Deinitialize the file reader.
bool doDeinitialize(bool wait=false)
Asks the node worker to deinitialize the node.
Definition Node.cpp:395
ImVec2 _guiConfigDefaultWindowSize
Definition Node.hpp:410
Node(std::string name)
Constructor.
Definition Node.cpp:30
bool doInitialize(bool wait=false)
Asks the node worker to initialize the node.
Definition Node.cpp:300
std::string nameId() const
Node name and id.
Definition Node.cpp:253
std::string name
Name of the Node.
Definition Node.hpp:395
bool doReinitialize(bool wait=false)
Asks the node worker to reinitialize the node.
Definition Node.cpp:350
bool _hasConfig
Flag if the config window should be shown.
Definition Node.hpp:413
ImGui extensions.
bool InputIntL(const char *label, int *v, int v_min, int v_max, int step, int step_fast, ImGuiInputTextFlags flags)
Shows a value limited InputText GUI element for 'int'.
Definition imgui_ex.cpp:242
OutputPin * CreateOutputPin(Node *node, const char *name, Pin::Type pinType, const std::vector< std::string > &dataIdentifier, OutputPin::PinData data=static_cast< void * >(nullptr), int idx=-1)
Create an Output Pin object.
void ApplyChanges()
Signals that there have been changes to the flow.
static std::vector< std::string > split(const std::string &str, const std::string &delimiter)
Splits a string into parts at a delimiter.
@ Object
Generic Object.
Definition Pin.hpp:57