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


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Jun 19 2023 03:01:01