BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
QREDataLoader.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/DataLoaders/QREDataLoader.cpp
6 //! @brief Implements class QREDataLoader
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2021
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
19 #include "Device/Unit/AxisNames.h"
28 #include "qcustomplot.h"
29 #include "ui_QREDataLoaderProperties.h"
30 #include <QFile>
31 #include <QString>
32 #include <QTextStream>
33 
34 namespace {
35 
36 //! For emitting a signal on method exit
37 class AutoEmit {
38 public:
39  AutoEmit(std::function<void()> fn) : m_fn(fn) {}
40  ~AutoEmit() { m_fn(); }
41 
42 private:
43  std::function<void()> m_fn;
44 };
45 
46 QVector<QPair<int, int>> expandLineNumberPattern(const QString& pattern, bool* ok = nullptr)
47 {
48  QVector<QPair<int, int>> result;
49 
50  // splitting "1, 2-3" first on comma-separated tokens
51  for (const auto& token : pattern.split(",")) {
52  const auto parts = token.split("-");
53  // splitting on dash-separated tokens
54  if (!parts.empty()) {
55  // if no "-" is present, make from "1" a pair {1, 1}
56  // if "-" is present, make from "1-2" a pair {1,2}
57  bool ok2 = true;
58  const auto conv0 = parts[0].toInt(&ok2);
59  if (ok2) {
60  const auto conv1 = parts.size() > 1 ? parts[1].toInt(&ok2) : conv0;
61  if (ok2) {
62  result.push_back({conv0, conv1});
63  } else {
64  if (ok != nullptr) {
65  *ok = false;
66  }
67  return {};
68  }
69  }
70  }
71  }
72 
73  return result;
74 }
75 
76 } // namespace
77 
78 QREDataLoader::QREDataLoader() : m_propertiesWidget(nullptr)
79 {
81 }
82 
83 QString QREDataLoader::name() const
84 {
85  return "CSV file (Reflectometry - Q/R/sigma_R)";
86 }
87 
89 {
90  return "QREDataLoader";
91 }
92 
94 {
95  if (m_propertiesWidget == nullptr)
97 
98  QHBoxLayout* l = new QHBoxLayout(parent);
99  l->setContentsMargins(0, 0, 0, 0);
100  parent->setLayout(l);
101  l->addWidget(m_propertiesWidget);
102 
103  if (m_importSettings.separator == " ")
104  m_propertiesWidget->m_ui->separatorCombo->setCurrentText("<SPACE>");
105  else if (m_importSettings.separator == "\t")
106  m_propertiesWidget->m_ui->separatorCombo->setCurrentText("<TAB>");
107  else
108  m_propertiesWidget->m_ui->separatorCombo->setCurrentText(m_importSettings.separator);
109 
110  m_propertiesWidget->m_ui->headerPrefixEdit->setText(m_importSettings.headerPrefix);
111  m_propertiesWidget->m_ui->linesToSkipEdit->setText(m_importSettings.linesToSkip);
112 
113  for (const auto dataType : {DataType::Q, DataType::R, DataType::dR}) {
114  m_propertiesWidget->columnSpinBox((int)dataType)
115  ->setValue(m_importSettings.columnDefinitions[dataType].column + 1); // view is 1-based
116 
117  m_propertiesWidget->factorSpinBox((int)dataType)
118  ->setValue(m_importSettings.columnDefinitions[dataType].factor);
119  }
120 
121  m_propertiesWidget->m_ui->enableErrorCheckBox->setChecked(
123 
125  m_propertiesWidget->m_ui->qUnitCombo->setCurrentIndex(1);
126  else
127  m_propertiesWidget->m_ui->qUnitCombo->setCurrentIndex(0); // 1/nm
128 
132  });
133 }
134 
136 {
140 
141  for (const auto dataType : {DataType::Q, DataType::R, DataType::dR}) {
142  m_importSettings.columnDefinitions[dataType].enabled = true;
143  m_importSettings.columnDefinitions[dataType].column = (int)dataType;
145  m_importSettings.columnDefinitions[dataType].factor = 1.0;
146  }
147 
149 }
150 
151 QByteArray QREDataLoader::serialize() const
152 {
153  // changed in version 2: no file hash anymore (1 was only a developer version)
154  // changed in version 3: refactored lists/vectors (2 was only a developer version)
155  // changed in version 4: refactored lists/vectors (3 was only a developer version)
156 
157  QByteArray a;
158  QDataStream s(&a, QIODevice::WriteOnly);
159  s.setVersion(QDataStream::Qt_5_12);
160 
161  s << (quint8)4; // version
162  s << m_fileContent;
163  s << m_importSettings;
164  s << m_importResult.lines;
166  s << m_importResult.qValues;
167  s << m_importResult.rValues;
168  s << m_importResult.eValues;
172  s << m_importResult.error;
174 
175  return a;
176 }
177 
178 void QREDataLoader::deserialize(const QByteArray& data)
179 {
180  m_importSettings.columnDefinitions.clear(); // sufficient
182 
183  QDataStream s(data);
184  s.setVersion(QDataStream::Qt_5_12);
185 
186  quint8 version;
187  s >> version;
188 
189  if (version < 4) // anything smaller 4 was internal developer version => no backwards
190  // compatibility necessary
192 
193  if (version == 4) {
194  s >> m_fileContent;
195  s >> m_importSettings;
196  s >> m_importResult.lines;
198  s >> m_importResult.qValues;
199  s >> m_importResult.rValues;
200  s >> m_importResult.eValues;
204  s >> m_importResult.error;
206  } else
208 
209  if (s.status() != QDataStream::Ok)
211 }
212 
214 {
215  auto loader = new QREDataLoader();
216  loader->deserialize(serialize());
217  return loader;
218 }
219 
221 {
222  AutoEmit emitter([this] { contentsProcessed(); }); // automatic signal calling in any return
223 
224  // Important: If the current options match the ones in m_parsingResult, then nothing should be
225  // performed. Otherwise e.g. a linked instrument may have to be re-linked
226 
227  m_importResult.error.clear();
228 
229  ASSERT(m_item != nullptr);
231 
232  const auto invalidateItemData = [this]() {
235  };
236 
237  const bool parsingSettingsChanged =
241  const bool calculationSettingsChanged =
243  const bool calculationIsNecessary = (parsingSettingsChanged || calculationSettingsChanged);
244  const bool creationOfOutputDataIsNecessary = calculationIsNecessary;
245 
246  if (parsingSettingsChanged)
247  // everything has to be re-parsed
249 
250  if (calculationIsNecessary)
252 
254 
255  // -- make a few checks (mainly for fulfilling PointwiseAxis::sanityCheck())
257  m_importResult.error = "At least two full rows must exist";
258 
259  if (!m_importResult.error.isEmpty()) {
260  invalidateItemData();
261  return;
262  }
263 
264  if (creationOfOutputDataIsNecessary) {
265 
266  try {
268  } catch (...) {
269  m_importResult.error = "Import not successful - caught an exception.";
270  invalidateItemData();
271  }
272  }
273 }
274 
276 {
277  return (m_importResult.error.isEmpty() ? 0 : 1) + m_importResult.calculationErrors.size();
278 }
279 
281 {
282  return m_importResult.calculationErrors.size();
283 }
284 
286 {
287  if (!m_importResult.error.isEmpty())
288  return {m_importResult.error};
289 
290  return {};
291 }
292 
294 {
296 }
297 
298 QByteArray QREDataLoader::fileContent() const
299 {
300  return m_fileContent;
301 }
302 
304 {
305  // #baimport - move to utils; create unit test
306  // search for lines which start with a number, then try the separators
307 
308  const auto isFirstNumberChar = [](const QChar& c) {
309  return c.isNumber() || c == '.' || c == '+' || c == '-';
310  };
311 
312  const auto belongsToNumber = [](const QChar& c) {
313  return c.isNumber() || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-';
314  };
315 
316  QTextStream in(m_fileContent);
317  int lineNr = 0;
318  const int maxLinesToExamine = 100;
319  while (!in.atEnd() && lineNr < maxLinesToExamine) {
320  lineNr++;
321  QString line = in.readLine().trimmed();
322  if (line.isEmpty())
323  continue;
324  if (!isFirstNumberChar(line[0]))
325  continue;
326 
327  // line starts with a number => search gap after it
328  int startOfGap = 1;
329  while (startOfGap < line.size() && belongsToNumber(line[startOfGap]))
330  startOfGap++;
331 
332  if (startOfGap == line.size())
333  continue;
334 
335  int endOfGap = startOfGap;
336  while (endOfGap < line.size() && !belongsToNumber(line[endOfGap])) {
337  endOfGap++;
338  }
339 
340  QStringRef gapContent(&line, startOfGap, endOfGap - startOfGap);
341  if (gapContent.isEmpty())
342  continue;
343 
344  if (gapContent.contains("\t")) {
346  return;
347  }
348 
349  gapContent = gapContent.trimmed();
350  if (gapContent.isEmpty()) {
352  return;
353  }
354 
355  if (gapContent.contains(";")) {
357  return;
358  }
359 
360  if (gapContent.contains(",")) {
362  return;
363  }
364  }
365 }
366 
367 void QREDataLoader::setFileContents(const QByteArray& fileContent)
368 {
370 }
371 
373 {
375 
376  const QStringList headerPrefixes = (m_importSettings.headerPrefix.trimmed().isEmpty())
377  ? QStringList()
378  : m_importSettings.headerPrefix.split(",");
379 
380  const auto lineIsHeader = [headerPrefixes](const QString& line) {
381  for (const auto& prefix : headerPrefixes) {
382  if (line.startsWith(prefix.trimmed()))
383  return true;
384  }
385 
386  return false;
387  };
388 
389  const auto skippedLines = expandLineNumberPattern(m_importSettings.linesToSkip);
390  const auto lineShouldBeSkipped = [skippedLines](int lineNr) {
391  for (const auto pair : skippedLines) {
392  if (lineNr >= pair.first && lineNr <= pair.second)
393  return true;
394  }
395  return false;
396  };
397 
398  QTextStream in(m_fileContent);
399  int lineNr = 0;
400  // if separator is SPACE: e.g. three consecutive SPACEs do not represent 3 columns => delete
401  // empty parts
402  QString::SplitBehavior splitBehavior =
403  m_importSettings.separator == " " ? QString::SkipEmptyParts : QString::KeepEmptyParts;
404 
405  while (!in.atEnd()) {
406  lineNr++;
407 
408  QString line = in.readLine();
409 
410  const bool skip =
411  lineIsHeader(line) || lineShouldBeSkipped(lineNr) || line.trimmed().isEmpty();
412 
413  m_importResult.lines << qMakePair(skip, line);
414  }
415 
417 
418  for (int lineNr = 0; lineNr < m_importResult.lines.size(); lineNr++) {
419 
420  const bool skip = m_importResult.lines[lineNr].first;
421  if (skip)
422  continue;
423 
424  const QStringList lineEntries =
425  m_importResult.lines[lineNr].second.split(m_importSettings.separator, splitBehavior);
426 
428  std::max(m_importResult.maxColumnCount, lineEntries.count());
429 
430  QVector<double> rowEntriesAsDouble;
431 
432  for (int col = 0; col < lineEntries.count(); col++) {
433  bool ok = false;
434  double val = lineEntries[col].toDouble(&ok);
435  if (!ok)
436  val = std::numeric_limits<double>::quiet_NaN();
437 
438  rowEntriesAsDouble << val;
439  }
440 
441  m_importResult.rawValues[lineNr] = rowEntriesAsDouble;
442  }
443 }
444 
446 {
451 
452  // -- calculate the Q/R/E values (take from specified column, use factor)
453  const auto& c = m_importSettings.columnDefinitions; // easier access
454  const bool errorColumnIsEnabled = c[DataType::dR].enabled;
455  const double unitFac = (c[DataType::Q].unit == UnitInFile::perAngstrom) ? 10.0 : 1.0;
456  const double qFactor = c[DataType::Q].factor * unitFac;
457  const double rFactor = c[DataType::R].factor;
458  const double eFactor = c[DataType::dR].factor;
459 
460  const int qCol = c[DataType::Q].column;
461  const int rCol = c[DataType::R].column;
462  const int eCol = c[DataType::dR].column;
463 
464  QSet<double> foundQValues;
465  double lastFoundQ = std::numeric_limits<double>::quiet_NaN();
466 
467  for (int lineNr = 0; lineNr < m_importResult.lines.size(); lineNr++) {
468  const bool skipLine = m_importResult.lines[lineNr].first;
469  if (skipLine)
470  continue;
471 
472  const auto& rawValues = m_importResult.rawValues[lineNr];
473 
474  const bool qColIsValid = qCol >= 0 && qCol < rawValues.size();
475  const bool rColIsValid = rCol >= 0 && rCol < rawValues.size();
476  const bool eColIsValid = eCol >= 0 && eCol < rawValues.size();
477 
478  const double q =
479  qColIsValid ? rawValues[qCol] * qFactor : std::numeric_limits<double>::quiet_NaN();
480  const double r =
481  rColIsValid ? rawValues[rCol] * rFactor : std::numeric_limits<double>::quiet_NaN();
482  const double e =
483  eColIsValid ? rawValues[eCol] * eFactor : std::numeric_limits<double>::quiet_NaN();
484 
485  if (std::isnan(q)) {
487  qCol + 1);
488  continue;
489  }
490 
491  if (std::isnan(r)) {
493  rCol + 1);
494  continue;
495  }
496 
497  if (std::isnan(e) && errorColumnIsEnabled) {
499  eCol + 1);
500  continue;
501  }
502 
503  if (foundQValues.contains(q)) {
505  continue;
506  }
507 
508  if (!std::isnan(lastFoundQ) && q <= lastFoundQ) {
510  continue;
511  }
512 
513  if (r > 1.0) {
515  continue;
516  }
517 
518  if (r < 0.0) {
520  continue;
521  }
522 
523  m_importResult.qValues[lineNr] = q;
524  m_importResult.rValues[lineNr] = r;
525  m_importResult.eValues[lineNr] = e;
527  foundQValues << q;
528  lastFoundQ = q;
529  }
530 }
531 
533 {
534  // -- create OutputData
535  std::vector<double> qVec;
536  std::vector<double> rVec;
537 
538  for (int lineNr = 0; lineNr < m_importResult.lines.size(); lineNr++) {
539  const bool skipLine = m_importResult.lines[lineNr].first;
540  const bool lineHasError = m_importResult.calculationErrors.contains(lineNr);
541  if (skipLine || lineHasError)
542  continue;
543 
544  qVec.push_back(m_importResult.qValues[lineNr]);
545  rVec.push_back(m_importResult.rValues[lineNr]);
546  }
547 
548  OutputData<double>* oData = new OutputData<double>();
549  oData->addAxis(PointwiseAxis("qVector", qVec));
550  oData->setRawDataVector(rVec);
551 
552  // -- Replacement of item->setImportData(std::move(data));
553  item->initNativeData();
554 
555  QString units_name = JobItemUtils::nameFromAxesUnits(Axes::Units::QSPACE);
556 
557  // -- Replacement of specularItem->reset(std::move(data));
558  SpecularDataItem* specularItem = item->specularDataItem();
559  ComboProperty combo = ComboProperty() << units_name;
560 
561  specularItem->setItemValue(SpecularDataItem::P_AXES_UNITS, combo.variant());
562  specularItem->getItem(SpecularDataItem::P_AXES_UNITS)->setVisible(true);
563 
564  auto label_map = AxisNames::InitSpecAxis();
565  const auto xAxisTitle = QString::fromStdString(label_map[Axes::Units::QSPACE]);
566  const auto yAxisTitle = "Signal [a.u.]"; // taken from ImportDataInfo::axisLabel
567 
568  specularItem->setXaxisTitle(xAxisTitle);
569  specularItem->setYaxisTitle(yAxisTitle);
570  specularItem->setOutputData(oData); // takes ownership of odata
571  specularItem->setAxesRangeToData();
572 
573  item->setNativeDataUnits(units_name);
574  item->setNativeOutputData(oData->clone()); // takes ownership of odata
575 }
576 
577 QDataStream& operator<<(QDataStream& stream, const QREDataLoader::ImportSettings& s)
578 {
579  stream << s.serialize();
580  return stream;
581 }
582 
583 QDataStream& operator>>(QDataStream& stream, QREDataLoader::ImportSettings& s)
584 {
585  QByteArray b;
586  stream >> b;
587  s.deserialize(b);
588  return stream;
589 }
590 
592 {
593  if (!m_propertiesWidget)
594  return;
595 
596  const auto ui = m_propertiesWidget->m_ui;
597 
598  m_importSettings.separator = ui->separatorCombo->currentText();
599  if (m_importSettings.separator == "<TAB>")
601  if (m_importSettings.separator == "<SPACE>")
603 
604  m_importSettings.headerPrefix = ui->headerPrefixEdit->text();
605  m_importSettings.linesToSkip = ui->linesToSkipEdit->text();
606 
607  for (const auto dataType : m_importSettings.columnDefinitions.keys()) {
608  auto& colDef = m_importSettings.columnDefinitions[dataType];
609 
610  colDef.column = m_propertiesWidget->columnSpinBox((int)dataType)->value() - 1;
611  colDef.factor = m_propertiesWidget->factor((int)dataType);
612  }
613 
615  m_propertiesWidget->m_ui->qUnitCombo->currentIndex() == 0 ? UnitInFile::perNanoMeter
617 
619  m_propertiesWidget->m_ui->enableErrorCheckBox->isChecked();
620 }
621 
623 {
624  lines.clear();
625  rawValues.clear();
626  qValues.clear();
627  rValues.clear();
628  eValues.clear();
630  maxColumnCount = 0;
631  calculationErrors.clear();
632  error.clear();
633  importSettings.columnDefinitions.clear(); // sufficient
634 }
635 
637 {
638  qValues.clear();
639  rValues.clear();
640  eValues.clear();
641  calculationErrors.clear();
642  validCalculatedLines = 0;
643 }
644 
646 {
647  calculationErrors[line] = ErrorDefinition(type, data);
648 }
649 
651 {
652  calculationErrors[line] = ErrorDefinition(type, data);
653 }
654 
656 {
657  auto error = calculationErrors.value(line, ErrorDefinition());
658  return error.type == ErrorDefinition::none ? QString() : error.toString();
659 }
660 
662 {
663  return serialize() != other.serialize();
664 }
665 
667 {
668  QByteArray a;
669  QDataStream s(&a, QIODevice::WriteOnly);
670  s.setVersion(QDataStream::Qt_5_12);
671 
672  s << (quint8)1; // version
673  s << separator;
674  s << headerPrefix;
675  s << linesToSkip;
676 
677  s << (quint8)columnDefinitions.count();
678  for (const auto dataType : columnDefinitions.keys()) {
679  s << (quint8)dataType;
680  s << columnDefinitions[dataType].enabled;
681  s << columnDefinitions[dataType].column;
682  s << (quint8)columnDefinitions[dataType].unit;
683  s << columnDefinitions[dataType].factor;
684  }
685 
686  return a;
687 }
688 
689 void QREDataLoader::ImportSettings::deserialize(const QByteArray& data)
690 {
691  columnDefinitions.clear();
692 
693  QDataStream s(data);
694  s.setVersion(QDataStream::Qt_5_12);
695 
696  quint8 version;
697  s >> version;
698 
699  if (version == 1) {
700  s >> separator;
701  s >> headerPrefix;
702  s >> linesToSkip;
703 
704  quint8 nDefs;
705  s >> nDefs;
706  for (int i = 0; i < nDefs; i++) {
707  quint8 dataType;
708  s >> dataType;
709  auto& colDef = columnDefinitions[(DataType)dataType];
710  s >> colDef.enabled;
711  s >> colDef.column;
712  quint8 unit;
713  s >> unit;
714  colDef.unit = UnitInFile(unit);
715  s >> colDef.factor;
716  }
717  } else
719 
720  if (s.status() != QDataStream::Ok)
722 }
723 
725 {
726  return enabled == other.enabled && column == other.column && unit == other.unit
727  && factor == other.factor;
728 }
729 
731 QREDataLoader::ErrorDefinition::ErrorDefinition(Type t, double d) : type(t), data(d) {}
732 
734 {
735  switch (type) {
736  case columnDoesNotContainValidNumber:
737  return QString("Raw column %1 does not contain a valid number - line is discarded")
738  .arg(std::get<int>(data));
739 
740  case duplicateQ:
741  return QString("The value %1 for Q is duplicate - line is discarded")
742  .arg(std::get<double>(data));
743 
744  case wrongQOrder:
745  return QString("Q coordinates must be sorted in ascending order - line is discarded");
746 
747  case RGreaterOne:
748  return QString("The value %1 for R is greater than 1.0 - line is discarded")
749  .arg(std::get<double>(data));
750 
751  case RLessZero:
752  return QString("The value %1 for R is less than 0 - line is discarded")
753  .arg(std::get<double>(data));
754  }
755 
756  return "Unspecified error";
757 }
758 
759 QDataStream& operator<<(QDataStream& stream, const QREDataLoader::ErrorDefinition& s)
760 {
761  stream << (quint8)s.type;
762  if (std::holds_alternative<int>(s.data)) {
763  stream << true;
764  stream << quint32(std::get<int>(s.data));
765  } else {
766  stream << false;
767  stream << qreal(std::get<double>(s.data));
768  }
769 
770  return stream;
771 }
772 
773 QDataStream& operator>>(QDataStream& stream, QREDataLoader::ErrorDefinition& s)
774 {
775  quint8 t;
776  stream >> t;
778  bool isInt = false;
779  stream >> isInt;
780  if (isInt) {
781  quint32 d;
782  stream >> d;
783  s.data = int(d);
784  } else {
785  qreal d;
786  stream >> d;
787  s.data = double(d);
788  }
789 
790  return stream;
791 }
#define ASSERT(condition)
Definition: Assert.h:31
Defines namespace AxisNames.
Defines class OutputDataIOFactory.
Declares class DataItem.
Defines class DeserializationException.
Defines ImportDataInfo helper struct.
Defines class IntensityDataIOFactory.
Defines class JobItemUtils.
Defines class PointwiseAxis.
Defines class QREDataLoaderResultModel.
QDataStream & operator>>(QDataStream &stream, QREDataLoader::ImportSettings &s)
Defines class QREDataLoader.
Defines class RealDataItem.
Defines class SpecularDataItem.
Base class for result tables of data loaders.
Base class for all data loaders (classes which can import real data)
void contentsProcessed()
Emitted whenever contents have been processed.
void importSettingsChanged()
Emitted whenever an import setting changed.
std::ostream & operator<<(std::ostream &os, const BasicVector3D< T > &a)
Output to stream.
Custom property to define list of string values with multiple selections.
Definition: ComboProperty.h:25
QVariant variant() const
Constructs variant enclosing given ComboProperty.
static const QString P_AXES_UNITS
Definition: DataItem.h:34
static DeserializationException streamError()
static DeserializationException tooOld()
static DeserializationException tooNew()
void addAxis(const IAxis &new_axis)
Definition: OutputData.h:295
void setRawDataVector(const std::vector< T > &data_vector)
Sets new values to raw data vector.
Definition: OutputData.h:556
OutputData * clone() const
Definition: OutputData.h:259
Axis containing arbitrary (non-equidistant) coordinate values.
Definition: PointwiseAxis.h:37
Properties widget for the QREDataLoader.
virtual QByteArray fileContent() const override
Returns the original file content.
virtual QString persistentClassName() const override
A name which can be used for save/load purposes (which will not change ever more)
friend QDataStream & operator<<(QDataStream &stream, const QREDataLoader::ImportSettings &s)
virtual void guessSettings() override
Guess appropriate settings (for example the separator in a CSV file).
virtual int numLineRelatedErrors() const override
Number of errors related to a specific line.
virtual int numErrors() const override
Number of errors found while processing the content.
virtual void initWithDefaultImportSettings() override
Set import settings to defaults.
virtual void setFileContents(const QByteArray &fileContent) override
Sets the file contents to be imported.
virtual QByteArray serialize() const override
Returns every internal setting so it can be restored completely.
void calculateFromParseResult() const
virtual void deserialize(const QByteArray &data) override
Initialize from serialization data.
virtual void applyImportSettings() override
Read all values from the properties UI into the internal variables.
QByteArray m_fileContent
virtual AbstractDataLoader * clone() const override
Create a complete clone, including all internal states.
virtual AbstractDataLoaderResultModel * createResultModel() const override
Create a table model which contains the import information like original file content,...
virtual void populateImportSettingsWidget(QWidget *parent) override
Fills the widget on the import dialog pane.
virtual QStringList lineUnrelatedErrors() const override
Errors not related to a particular line.
virtual QString name() const override
The name shown in the format selection combo.
QPointer< QREDataLoaderProperties > m_propertiesWidget
struct QREDataLoader::ImportSettings m_importSettings
ImportResult m_importResult
void createOutputDataFromParsingResult(RealDataItem *item) const
void parseFileContent() const
virtual void processContents() override
Process the file contents.
friend class QREDataLoaderResultModel
friend QDataStream & operator>>(QDataStream &stream, QREDataLoader::ImportSettings &s)
The RealDataItem class represents intensity data imported from file and intended for fitting.
Definition: RealDataItem.h:35
void removeNativeData()
void initNativeData()
bool isSpecularData() const
void setNativeOutputData(OutputData< double > *data)
takes ownership of data
void setNativeDataUnits(const QString &units)
SpecularDataItem * specularDataItem()
void setVisible(bool enabled)
Flags accessors.
void setItemValue(const QString &tag, const QVariant &variant)
Directly set value of item under given tag.
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
void setYaxisTitle(const QString &title) override
void setXaxisTitle(const QString &title) override
void setOutputData(OutputData< double > *data) override
The given pointer becomes owned by this class!!
void setAxesRangeToData() override
set zoom range of x,y axes to axes of input data
std::map< Axes::Units, std::string > InitSpecAxis()
Definition: AxisNames.cpp:82
QString nameFromAxesUnits(Axes::Units units)
returns axes units names from their domain counterpart
bool operator==(const ColumnDefinition &other) const
Contains a line related error (stored in the import result).
Definition: QREDataLoader.h:80
std::variant< int, double > data
Additional data; meaning depends on the error type (see implementation of toString() for more informa...
Definition: QREDataLoader.h:98
ErrorDefinition(Type t=none, int d=0)
QString toString() const
Human readable error text.
QVector< double > rValues
index is 0-based line number
int maxColumnCount
max found columns in raw data
QString error
error unrelated to lines
void addError(int line, ErrorDefinition::Type type, int data=0)
int validCalculatedLines
number of valid resulting data rows
QVector< QVector< double > > rawValues
index is 0-based line number
QMap< int, ErrorDefinition > calculationErrors
calculation error per line; line is 0-based
QVector< double > eValues
index is 0-based line number
QString errorText(int line) const
ImportSettings importSettings
Settings used for the import.
QVector< double > qValues
index is 0-based line number
QVector< QPair< bool, QString > > lines
bool describes whether line is skipped index is 0-based line number
Settings for importing the file.
Definition: QREDataLoader.h:67
QString separator
column separator
Definition: QREDataLoader.h:68
void deserialize(const QByteArray &data)
QMap< DataType, ColumnDefinition > columnDefinitions
Definition: QREDataLoader.h:71
QString headerPrefix
prefix denoting header line
Definition: QREDataLoader.h:69
bool operator!=(const ImportSettings &other) const
QString linesToSkip
pattern denoting line to skip (i.e. '1,10-12,42')
Definition: QREDataLoader.h:70