dataload_parquet.cpp
Go to the documentation of this file.
1 #include "dataload_parquet.h"
2 #include <QTextStream>
3 #include <QFile>
4 #include <QMessageBox>
5 #include <QDebug>
6 #include <QSettings>
7 #include <QProgressDialog>
8 #include <QDateTime>
9 #include <QInputDialog>
10 #include <QListWidget>
11 
13 {
14  ui = new Ui::DialogParquet();
15  _dialog = new QDialog();
16 
17  ui->setupUi(_dialog);
18 
19  connect(ui->checkBoxDateFormat, &QCheckBox::toggled, this,
20  [=](bool checked) { ui->lineEditDateFormat->setEnabled(checked); });
21 
22  connect(ui->listWidgetSeries, &QListWidget::currentTextChanged, this,
23  [=](QString text) { ui->buttonBox->setEnabled(!text.isEmpty()); });
24 
25  connect(ui->listWidgetSeries, &QListWidget::doubleClicked, this,
26  [=](const QModelIndex&) { _dialog->accept(); });
27 
28  connect(ui->radioButtonIndex, &QRadioButton::toggled, this, [=](bool checked) {
29  ui->buttonBox->setEnabled(checked);
30  ui->listWidgetSeries->setEnabled(!checked);
31  });
32 
33  QSettings settings;
34 
35  bool radio_index_checked =
36  settings.value("DataLoadParquet::radioIndexChecked", false).toBool();
37  ui->radioButtonIndex->setChecked(radio_index_checked);
38 
39  bool parse_date_time = settings.value("DataLoadParquet::parseDateTime", false).toBool();
40  ui->checkBoxDateFormat->setChecked(parse_date_time);
41 
42  QString date_format = settings.value("DataLoadParquet::dateFromat", false).toString();
43  if (date_format.isEmpty() == false)
44  {
45  ui->lineEditDateFormat->setText(date_format);
46  }
47 }
48 
50 {
51  delete ui;
52 }
53 
54 const std::vector<const char*>& DataLoadParquet::compatibleFileExtensions() const
55 {
56  static std::vector<const char*> extensions = { "parquet" };
57  return extensions;
58 }
59 
61 {
62  using parquet::ConvertedType;
63  using parquet::Type;
64 
65  parquet_reader_ = parquet::ParquetFileReader::OpenFile(info->filename.toStdString());
66 
67  if (!parquet_reader_)
68  {
69  return false;
70  }
71 
72  std::shared_ptr<parquet::FileMetaData> file_metadata = parquet_reader_->metadata();
73  const auto schema = file_metadata->schema();
74  const size_t num_columns = file_metadata->num_columns();
75 
76  std::vector<parquet::Type::type> column_type;
77  std::vector<parquet::ConvertedType::type> converted_column_type;
78  std::vector<bool> valid_column(num_columns, true);
79 
80  for (size_t col = 0; col < num_columns; col++)
81  {
82  auto column = schema->Column(col);
83  auto type = column->physical_type();
84  auto converted_type = column->converted_type();
85 
86  column_type.push_back(type);
87  converted_column_type.push_back(converted_type);
88 
89  valid_column[col] =
90  (type == Type::BOOLEAN || type == Type::INT32 || type == Type::INT64 ||
91  type == Type::FLOAT || type == Type::DOUBLE);
92 
93  ui->listWidgetSeries->addItem(QString::fromStdString(column->name()));
94  }
95 
96  {
97  QSettings settings;
98  if (_default_time_axis.isEmpty())
99  {
101  settings.value("DataLoadParquet::prevTimestamp", {}).toString();
102  }
103 
104  if (_default_time_axis.isEmpty() == false)
105  {
106  auto items = ui->listWidgetSeries->findItems(_default_time_axis, Qt::MatchExactly);
107  if (items.size() > 0)
108  {
109  ui->listWidgetSeries->setCurrentItem(items.front());
110  }
111  }
112  }
113 
114  int ret = _dialog->exec();
115  if (ret != QDialog::Accepted)
116  {
117  return false;
118  }
119 
120  QString selected_stamp;
121 
122  if (ui->radioButtonSelect->isChecked())
123  {
124  auto selected = ui->listWidgetSeries->selectedItems();
125  if (selected.size() == 1)
126  {
127  selected_stamp = selected.front()->text();
128  }
129  }
130 
131  QSettings settings;
132  settings.setValue("DataLoadParquet::prevTimestamp", selected_stamp);
133  settings.setValue("DataLoadParquet::radioIndexChecked",
134  ui->radioButtonIndex->isChecked());
135  settings.setValue("DataLoadParquet::parseDateTime",
136  ui->checkBoxDateFormat->isChecked());
137  settings.setValue("DataLoadParquet::dateFromat", ui->lineEditDateFormat->text());
138 
139  //-----------------------------
140  // Time to parse
141  int timestamp_column = -1;
142 
143  std::vector<PlotData*> series(num_columns, nullptr);
144 
145  for (size_t col = 0; col < num_columns; col++)
146  {
147  auto column = schema->Column(col);
148  const std::string& name = column->name();
149  if (name == selected_stamp.toStdString())
150  {
151  timestamp_column = col;
152  }
153  if (valid_column[col])
154  {
155  series[col] = &(plot_data.addNumeric(name)->second);
156  }
157  }
158 
159  parquet::StreamReader os{ std::move(parquet_reader_) };
160 
161  std::vector<double> row_values(num_columns, 0.0);
162 
163  int row = 0;
164  while (!os.eof())
165  {
166  // extract an entire row
167  for (size_t col = 0; col < num_columns; col++)
168  {
169  if (!valid_column[col])
170  {
171  os.SkipColumns(1);
172  continue;
173  }
174  auto type = column_type[col];
175  auto converted_type = converted_column_type[col];
176 
177  switch (type)
178  {
179  case Type::BOOLEAN: {
180  bool tmp;
181  os >> tmp;
182  row_values[col] = static_cast<double>(tmp);
183  break;
184  }
185  case Type::INT32:
186  case Type::INT64: {
187  switch (converted_type)
188  {
189  case ConvertedType::INT_8: {
190  int8_t tmp;
191  os >> tmp;
192  row_values[col] = static_cast<double>(tmp);
193  break;
194  }
195  case ConvertedType::INT_16: {
196  int16_t tmp;
197  os >> tmp;
198  row_values[col] = static_cast<double>(tmp);
199  break;
200  }
201  case ConvertedType::INT_32: {
202  int32_t tmp;
203  os >> tmp;
204  row_values[col] = static_cast<double>(tmp);
205  break;
206  }
207  case ConvertedType::INT_64: {
208  int64_t tmp;
209  os >> tmp;
210  row_values[col] = static_cast<double>(tmp);
211  break;
212  }
213  case ConvertedType::UINT_8: {
214  uint8_t tmp;
215  os >> tmp;
216  row_values[col] = static_cast<double>(tmp);
217  break;
218  }
219  case ConvertedType::UINT_16: {
220  uint16_t tmp;
221  os >> tmp;
222  row_values[col] = static_cast<double>(tmp);
223  break;
224  }
225  case ConvertedType::UINT_32: {
226  uint32_t tmp;
227  os >> tmp;
228  row_values[col] = static_cast<double>(tmp);
229  break;
230  }
231  case ConvertedType::UINT_64: {
232  uint64_t tmp;
233  os >> tmp;
234  row_values[col] = static_cast<double>(tmp);
235  break;
236  }
237  default: {
238  // Fallback in case no converted type is provided
239  switch (type)
240  {
241  case Type::INT32: {
242  int32_t tmp;
243  os >> tmp;
244  row_values[col] = static_cast<double>(tmp);
245  break;
246  }
247  case Type::INT64: {
248  int64_t tmp;
249  os >> tmp;
250  row_values[col] = static_cast<double>(tmp);
251  break;
252  }
253  }
254  }
255  }
256  break;
257  }
258  case Type::FLOAT: {
259  float tmp;
260  os >> tmp;
261  row_values[col] = static_cast<double>(tmp);
262  break;
263  }
264  case Type::DOUBLE: {
265  os >> row_values[col];
266  break;
267  }
268  default: {
269  }
270  } // end switch
271  } // end for column
272 
273  os >> parquet::EndRow;
274 
275  double timestamp = timestamp_column >= 0 ? row_values[timestamp_column] : row;
276  row++;
277 
278  for (size_t col = 0; col < num_columns; col++)
279  {
280  if (!valid_column[col])
281  {
282  continue;
283  }
284 
285  if (valid_column[col])
286  {
287  series[col]->pushBack({ timestamp, row_values[col] });
288  }
289  }
290  }
291  return true;
292 }
293 
294 bool DataLoadParquet::xmlSaveState(QDomDocument& doc, QDomElement& parent_element) const
295 {
296  QDomElement elem = doc.createElement("default");
297  elem.setAttribute("prevTimestamp", _default_time_axis);
298  elem.setAttribute("radioIndexChecked", ui->radioButtonIndex->isChecked());
299  elem.setAttribute("parseDateTime", ui->checkBoxDateFormat->isChecked());
300  elem.setAttribute("dateFromat", ui->lineEditDateFormat->text());
301 
302  parent_element.appendChild(elem);
303  return true;
304 }
305 
306 bool DataLoadParquet::xmlLoadState(const QDomElement& parent_element)
307 {
308  QDomElement elem = parent_element.firstChildElement("default");
309  if (!elem.isNull())
310  {
311  if (elem.hasAttribute("prevTimestamp"))
312  {
313  _default_time_axis = elem.attribute("prevTimestamp");
314  }
315  if (elem.hasAttribute("radioIndexChecked"))
316  {
317  bool checked = elem.attribute("radioIndexChecked").toInt();
318  ui->radioButtonIndex->setChecked(checked);
319  }
320  if (elem.hasAttribute("parseDateTime"))
321  {
322  bool checked = elem.attribute("parseDateTime").toInt();
323  ui->checkBoxDateFormat->setChecked(checked);
324  }
325  if (elem.hasAttribute("dateFromat"))
326  {
327  ui->lineEditDateFormat->setText(elem.attribute("dateFromat"));
328  }
329  }
330 
331  return true;
332 }
DataLoadParquet::parquet_reader_
std::unique_ptr< parquet::ParquetFileReader > parquet_reader_
Definition: dataload_parquet.h:48
DataLoadParquet::name
virtual const char * name() const override
Name of the plugin type, NOT the particular instance.
Definition: dataload_parquet.h:29
DataLoadParquet::xmlSaveState
virtual bool xmlSaveState(QDomDocument &doc, QDomElement &parent_element) const override
Override this method to save the status of the plugin to XML.
Definition: dataload_parquet.cpp:294
PJ::FileLoadInfo
Definition: dataloader_base.h:18
DataLoadParquet::xmlLoadState
virtual bool xmlLoadState(const QDomElement &parent_element) override
Override this method to load the status of the plugin from XML.
Definition: dataload_parquet.cpp:306
backward::ColorMode::type
type
Definition: backward.hpp:3600
PJ::PlotDataMapRef::addNumeric
TimeseriesMap::iterator addNumeric(const std::string &name, PlotGroup::Ptr group={})
Definition: plotdata.cpp:51
DataLoadParquet::_default_time_axis
QString _default_time_axis
Definition: dataload_parquet.h:46
DataLoadParquet::DataLoadParquet
DataLoadParquet()
Definition: dataload_parquet.cpp:12
QwtTriangle::Type
Type
Definition: qwt_symbol.cpp:32
DataLoadParquet::compatibleFileExtensions
virtual const std::vector< const char * > & compatibleFileExtensions() const override
Provide a list of file extensions that this plugin can open.
Definition: dataload_parquet.cpp:54
backward::details::move
const T & move(const T &v)
Definition: backward.hpp:394
DataLoadParquet::readDataFromFile
virtual bool readDataFromFile(PJ::FileLoadInfo *fileload_info, PlotDataMapRef &destination) override
Definition: dataload_parquet.cpp:60
dataload_parquet.h
DataLoadParquet::~DataLoadParquet
~DataLoadParquet() override
Definition: dataload_parquet.cpp:49
DataLoadParquet::ui
Ui::DialogParquet * ui
Definition: dataload_parquet.h:42
DataLoadParquet::_dialog
QDialog * _dialog
Definition: dataload_parquet.h:50
PJ::PlotDataMapRef
Definition: plotdata.h:34
mqtt_test.ret
ret
Definition: mqtt_test.py:30
RosMsgParser::INT32
@ INT32
Definition: builtin_types.hpp:54
PJ::FileLoadInfo::filename
QString filename
name of the file to open
Definition: dataloader_base.h:21
RosMsgParser::INT64
@ INT64
Definition: builtin_types.hpp:55


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Jan 26 2025 03:23:23