BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
QREDataLoader Class Reference

Description

Loader for experimental reflectometry CSV files that contain three columns with Q,R,E, namely Q = wavenumber, R = reflectivity, E = error of R.

Definition at line 29 of file QREDataLoader.h.

Inheritance diagram for QREDataLoader:
[legend]
Collaboration diagram for QREDataLoader:
[legend]

Classes

struct  ColumnDefinition
 
struct  ErrorDefinition
 Contains a line related error (stored in the import result). Used for showing line related errors in the import data table. More...
 
struct  ImportResult
 Result of the file import. Some of the contained data is only relevant for showing the results in the result table. The usage of vectors which cover also invalid or skipped lines has its reason also in this result showing (to improve presentation performance). More...
 
struct  ImportSettings
 Settings for importing the file. More...
 

Signals

void contentsProcessed ()
 Emitted whenever contents have been processed. More...
 
void importSettingsChanged ()
 Emitted whenever an import setting changed. More...
 

Public Member Functions

 QREDataLoader ()
 
void applyImportSettings () override
 Read all values from the properties UI into the internal variables. More...
 
AbstractDataLoaderclone () const override
 Create a complete clone, including all internal states. More...
 
AbstractDataLoaderResultModelcreateResultModel () const override
 Create a table model which contains the import information like original file content, raw content, processed content. The returned pointer will be owned by the caller. This base class' implementation does nothing (return nullptr). More...
 
virtual QByteArray defaultImportSettings () const
 Return the default import settings. More...
 
void deserialize (const QByteArray &data) override
 Initialize from serialization data. If any error occurred, then a DeserializationException has to be thrown. The complete state has to be restored. Therefore if e.g. errors occurred in the former serialization, but errors are not serialized, then they have to be regenerated/ recalculated in here. More...
 
QByteArray fileContent () const override
 Returns the original file content. If not available any more (like for legacy project file import), then an empty array will be returned. More...
 
void guessSettings () override
 Guess appropriate settings (for example the separator in a CSV file). Is called only once, directly after setting the file content. More...
 
void initWithDefaultImportSettings () override
 Set import settings to defaults. More...
 
QStringList lineUnrelatedErrors () const override
 Errors not related to a particular line. More...
 
QString name () const override
 The name shown in the format selection combo. More...
 
int numErrors () const override
 Number of errors found while processing the content. An error means that either a particular content (line) can't be used or may be suspicious (line related error), or that the whole content can't be used (e.g. only 1 line present). More...
 
int numLineRelatedErrors () const override
 Number of errors related to a specific line. Such an error means that a particular content (line) can't be used or may be suspicious. More...
 
QString persistentClassName () const override
 A name which can be used for save/load purposes (which will not change ever more) More...
 
void populateImportSettingsWidget (QWidget *parent) override
 Fills the widget on the import dialog pane. The implementation here in the base class does nothing (meaning "no editable properties"). More...
 
void processContents () override
 Process the file contents. Can be called more than once, e.g. if the import settings have changed. Any error has to be stored in the loader (see numErrors()). More...
 
RealDataItemrealDataItem ()
 The real data item on which the import shall work. More...
 
const RealDataItemrealDataItem () const
 The real data item on which the import shall work. More...
 
QByteArray serialize () const override
 Returns every internal setting so it can be restored completely. More...
 
void setFileContents (const QByteArray &fileContent) override
 Sets the file contents to be imported. If the file was a compressed file, then the decompressed content will be handed over already here. More...
 
void setRealDataItem (RealDataItem *item)
 Define the real data item on which the import shall work. More...
 

Protected Attributes

RealDataItemm_item
 The real-data-item which owns this loader. Never delete this! More...
 

Private Types

enum class  DataType { Q , R , dR }
 
enum class  UnitInFile { none , perNanoMeter , perAngstrom , other }
 

Private Member Functions

void calculateFromParseResult () const
 
void datafieldFromParsingResult (RealDataItem *item) const
 
void parseFileContent () const
 

Private Attributes

QByteArray m_fileContent
 
ImportResult m_importResult
 
struct QREDataLoader::ImportSettings m_importSettings
 
QPointer< QREDataLoaderPropertiesm_propertiesWidget
 

Friends

QDataStream & operator<< (QDataStream &stream, const QREDataLoader::ErrorDefinition &s)
 
QDataStream & operator<< (QDataStream &stream, const QREDataLoader::ImportSettings &s)
 
QDataStream & operator>> (QDataStream &stream, QREDataLoader::ErrorDefinition &s)
 
QDataStream & operator>> (QDataStream &stream, QREDataLoader::ImportSettings &s)
 
class QREDataLoaderResultModel
 

Member Enumeration Documentation

◆ DataType

enum QREDataLoader::DataType
strongprivate
Enumerator
dR 

Definition at line 66 of file QREDataLoader.h.

66 { Q, R, dR };

◆ UnitInFile

enum QREDataLoader::UnitInFile
strongprivate
Enumerator
none 
perNanoMeter 
perAngstrom 
other 

Definition at line 55 of file QREDataLoader.h.

55 { none, perNanoMeter, perAngstrom, other };
@ other
The unit has no enum value defined in here (e.g. when defined as an explicit string)

Constructor & Destructor Documentation

◆ QREDataLoader()

QREDataLoader::QREDataLoader ( )

Definition at line 76 of file QREDataLoader.cpp.

77  : m_propertiesWidget(nullptr)
78 {
80 }
void initWithDefaultImportSettings() override
Set import settings to defaults.
QPointer< QREDataLoaderProperties > m_propertiesWidget

References initWithDefaultImportSettings().

Referenced by clone().

Here is the call graph for this function:

Member Function Documentation

◆ applyImportSettings()

void QREDataLoader::applyImportSettings ( )
overridevirtual

Read all values from the properties UI into the internal variables.

Reimplemented from AbstractDataLoader.

Definition at line 586 of file QREDataLoader.cpp.

587 {
588  if (!m_propertiesWidget)
589  return;
590 
591  auto* const ui = m_propertiesWidget->m_ui;
592 
593  m_importSettings.separator = ui->separatorCombo->currentText();
594  if (m_importSettings.separator == "<TAB>")
596  if (m_importSettings.separator == "<SPACE>")
598 
599  m_importSettings.headerPrefix = ui->headerPrefixEdit->text();
600  m_importSettings.linesToSkip = ui->linesToSkipEdit->text();
601 
602  for (const auto dataType : m_importSettings.columnDefinitions.keys()) {
603  auto& colDef = m_importSettings.columnDefinitions[dataType];
604 
605  colDef.column = m_propertiesWidget->columnSpinBox((int)dataType)->value() - 1;
606  colDef.factor = m_propertiesWidget->factor((int)dataType);
607  }
608 
610  m_propertiesWidget->m_ui->qUnitCombo->currentIndex() == 0 ? UnitInFile::perNanoMeter
612 
614  m_propertiesWidget->m_ui->enableErrorCheckBox->isChecked();
615 }
struct QREDataLoader::ImportSettings m_importSettings
QString separator
column separator
Definition: QREDataLoader.h:70
QMap< DataType, ColumnDefinition > columnDefinitions
Definition: QREDataLoader.h:75
QString headerPrefix
prefix denoting header line
Definition: QREDataLoader.h:71
QString linesToSkip
pattern denoting line to skip (i.e. '1,10-12,42')
Definition: QREDataLoader.h:72

References QREDataLoader::ImportSettings::columnDefinitions, dR, QREDataLoader::ImportSettings::headerPrefix, QREDataLoader::ImportSettings::linesToSkip, m_importSettings, m_propertiesWidget, perAngstrom, perNanoMeter, Q, and QREDataLoader::ImportSettings::separator.

Referenced by populateImportSettingsWidget().

◆ calculateFromParseResult()

void QREDataLoader::calculateFromParseResult ( ) const
private

Definition at line 441 of file QREDataLoader.cpp.

442 {
447 
448  // -- calculate the Q/R/E values (take from specified column, use factor)
449  const auto& c = m_importSettings.columnDefinitions; // easier access
450  const bool errorColumnIsEnabled = c[DataType::dR].enabled;
451  const double unitFac = (c[DataType::Q].unit == UnitInFile::perAngstrom) ? 10.0 : 1.0;
452  const double qFactor = c[DataType::Q].factor * unitFac;
453  const double rFactor = c[DataType::R].factor;
454  const double eFactor = c[DataType::dR].factor;
455 
456  const int qCol = c[DataType::Q].column;
457  const int rCol = c[DataType::R].column;
458  const int eCol = c[DataType::dR].column;
459 
460  QSet<double> foundQValues;
461 
462  for (int lineNr = 0; lineNr < m_importResult.lines.size(); lineNr++) {
463  const bool skipLine = m_importResult.lines[lineNr].first;
464  if (skipLine)
465  continue;
466 
467  const auto& rawValues = m_importResult.rawValues[lineNr];
468 
469  const bool qColIsValid = qCol >= 0 && qCol < rawValues.size();
470  const bool rColIsValid = rCol >= 0 && rCol < rawValues.size();
471  const bool eColIsValid = eCol >= 0 && eCol < rawValues.size();
472 
473  const double q =
474  qColIsValid ? rawValues[qCol] * qFactor : std::numeric_limits<double>::quiet_NaN();
475  const double r =
476  rColIsValid ? rawValues[rCol] * rFactor : std::numeric_limits<double>::quiet_NaN();
477  const double e =
478  eColIsValid ? rawValues[eCol] * eFactor : std::numeric_limits<double>::quiet_NaN();
479 
480  if (std::isnan(q)) {
482  qCol + 1);
483  continue;
484  }
485 
486  if (std::isnan(r)) {
488  rCol + 1);
489  continue;
490  }
491 
492  if (std::isnan(e) && errorColumnIsEnabled) {
494  eCol + 1);
495  continue;
496  }
497 
498  if (foundQValues.contains(q)) {
500  continue;
501  }
502 
503  if (r > 1.0 && !m_importSettings.allowValuesGreaterOne) {
505  continue;
506  }
507 
508  if (r < 0.0) {
510  continue;
511  }
512 
513  m_importResult.qValues[lineNr] = q;
514  m_importResult.rValues[lineNr] = r;
515  m_importResult.eValues[lineNr] = e;
517  foundQValues << q;
518  }
519 }
ImportResult m_importResult
QVector< double > rValues
index is 0-based line number
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
QVector< double > eValues
index is 0-based line number
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
bool allowValuesGreaterOne
always true for now (see ##94); could be made configurable later on
Definition: QREDataLoader.h:73

References QREDataLoader::ImportResult::addError(), QREDataLoader::ImportSettings::allowValuesGreaterOne, QREDataLoader::ImportResult::clearCalculatedValues(), QREDataLoader::ImportSettings::columnDefinitions, QREDataLoader::ErrorDefinition::columnDoesNotContainValidNumber, dR, QREDataLoader::ErrorDefinition::duplicateQ, QREDataLoader::ImportResult::eValues, QREDataLoader::ImportResult::lines, m_importResult, m_importSettings, perAngstrom, Q, QREDataLoader::ImportResult::qValues, R, QREDataLoader::ImportResult::rawValues, QREDataLoader::ErrorDefinition::RGreaterOne, QREDataLoader::ErrorDefinition::RLessZero, QREDataLoader::ImportResult::rValues, and QREDataLoader::ImportResult::validCalculatedLines.

Referenced by processContents().

Here is the call graph for this function:

◆ clone()

AbstractDataLoader * QREDataLoader::clone ( ) const
overridevirtual

Create a complete clone, including all internal states.

Implements AbstractDataLoader.

Definition at line 212 of file QREDataLoader.cpp.

213 {
214  auto* loader = new QREDataLoader();
215  loader->deserialize(serialize());
216  return loader;
217 }
QByteArray serialize() const override
Returns every internal setting so it can be restored completely.

References QREDataLoader(), and serialize().

Here is the call graph for this function:

◆ contentsProcessed

void AbstractDataLoader::contentsProcessed ( )
signalinherited

Emitted whenever contents have been processed.

Referenced by AutomaticDataLoader1D::processContents(), processContents(), and RealDataItem::setDataLoader().

◆ createResultModel()

AbstractDataLoaderResultModel * QREDataLoader::createResultModel ( ) const
overridevirtual

Create a table model which contains the import information like original file content, raw content, processed content. The returned pointer will be owned by the caller. This base class' implementation does nothing (return nullptr).

Reimplemented from AbstractDataLoader.

Definition at line 291 of file QREDataLoader.cpp.

292 {
294 }
friend class QREDataLoaderResultModel

References m_importResult, and QREDataLoaderResultModel.

◆ datafieldFromParsingResult()

void QREDataLoader::datafieldFromParsingResult ( RealDataItem item) const
private

Definition at line 521 of file QREDataLoader.cpp.

522 {
523  // create data sorted by ascending Q values.
524  // For this, the line numbers are sorted by Q
525  QVector<int> lineNumbers;
526  for (int lineNr = 0; lineNr < m_importResult.lines.size(); lineNr++) {
527  const bool skipLine = m_importResult.lines[lineNr].first;
528  const bool lineHasError = m_importResult.calculationErrors.contains(lineNr);
529  if (skipLine || lineHasError)
530  continue;
531 
532  lineNumbers.push_back(lineNr);
533  }
534 
535  std::sort(lineNumbers.begin(), lineNumbers.end(),
536  [&](int a, int b) { return m_importResult.qValues[a] < m_importResult.qValues[b]; });
537 
538  // -- create Datafield
539  std::vector<double> qVec;
540  std::vector<double> rVec;
541 
542  for (auto lineNr : lineNumbers) {
543  qVec.push_back(m_importResult.qValues[lineNr]);
544  rVec.push_back(m_importResult.rValues[lineNr]);
545  }
546  auto* oData = new Datafield({new PointwiseAxis("qVector", qVec)}, rVec);
547 
548  // -- Replacement of item->setImportData(std::move(data));
549  item->initNativeData();
550 
551  QString units_name = GUI::Util::CoordName::nameFromCoord(Coords::QSPACE);
552 
553  // -- Replacement of specularItem->reset(std::move(data));
554  SpecularDataItem* specularItem = item->specularDataItem();
555  ComboProperty combo = ComboProperty() << units_name;
556 
557  specularItem->setAxesUnits(combo);
558 
559  auto label_map = DataUtils::AxisNames::specAxis;
560  const auto xAxisTitle = QString::fromStdString(label_map[Coords::QSPACE]);
561  const auto* const yAxisTitle = "Signal [a.u.]"; // taken from ImportDataInfo::axisLabel
562 
563  specularItem->setXaxisTitle(xAxisTitle);
564  specularItem->setYaxisTitle(yAxisTitle);
565  specularItem->setDatafield(oData); // takes ownership of odata
566  specularItem->setAxesRangeToData();
567 
568  item->setNativeDataUnits(units_name);
569  item->setNativeDatafield(oData->clone()); // also takes ownership
570 }
Custom property to define list of string values with multiple selections. Intended for QVariant.
Definition: ComboProperty.h:25
void setAxesUnits(const ComboProperty &units)
Definition: DataItem.cpp:96
void setNativeDatafield(Datafield *data)
takes ownership of data
void initNativeData()
void setNativeDataUnits(const QString &units)
SpecularDataItem * specularDataItem()
void setYaxisTitle(const QString &title) override
void setDatafield(Datafield *data) override
The given pointer becomes owned by this class!!
void setXaxisTitle(const QString &title) override
void setAxesRangeToData() override
set zoom range of x,y axes to axes of input data
QString nameFromCoord(Coords units)
Returns axes units names from their domain counterpart.
Definition: CoordName.cpp:36
QMap< int, ErrorDefinition > calculationErrors
calculation error per line; line is 0-based

References QREDataLoader::ImportResult::calculationErrors, RealDataItem::initNativeData(), QREDataLoader::ImportResult::lines, m_importResult, GUI::Util::CoordName::nameFromCoord(), QREDataLoader::ImportResult::qValues, QREDataLoader::ImportResult::rValues, SpecularDataItem::setAxesRangeToData(), DataItem::setAxesUnits(), SpecularDataItem::setDatafield(), RealDataItem::setNativeDatafield(), RealDataItem::setNativeDataUnits(), SpecularDataItem::setXaxisTitle(), SpecularDataItem::setYaxisTitle(), and RealDataItem::specularDataItem().

Referenced by processContents().

Here is the call graph for this function:

◆ defaultImportSettings()

QByteArray AbstractDataLoader::defaultImportSettings ( ) const
virtualinherited

Return the default import settings.

Definition at line 31 of file AbstractDataLoader.cpp.

32 {
33  std::unique_ptr<AbstractDataLoader> cloned(clone());
34  cloned->initWithDefaultImportSettings();
35  return cloned->serialize();
36 }
virtual AbstractDataLoader * clone() const =0
Create a complete clone, including all internal states.

References AbstractDataLoader::clone().

Here is the call graph for this function:

◆ deserialize()

void QREDataLoader::deserialize ( const QByteArray &  data)
overridevirtual

Initialize from serialization data. If any error occurred, then a DeserializationException has to be thrown. The complete state has to be restored. Therefore if e.g. errors occurred in the former serialization, but errors are not serialized, then they have to be regenerated/ recalculated in here.

Reimplemented from AbstractDataLoader.

Definition at line 177 of file QREDataLoader.cpp.

178 {
179  m_importSettings.columnDefinitions.clear(); // sufficient
181 
182  QDataStream s(data);
183  s.setVersion(QDataStream::Qt_5_12);
184 
185  quint8 version;
186  s >> version;
187 
188  if (version < 4) // anything smaller 4 was internal developer version => no backwards
189  // compatibility necessary
191 
192  if (version == 4) {
193  s >> m_fileContent;
194  s >> m_importSettings;
195  s >> m_importResult.lines;
197  s >> m_importResult.qValues;
198  s >> m_importResult.rValues;
199  s >> m_importResult.eValues;
203  s >> m_importResult.error;
205  } else
207 
208  if (s.status() != QDataStream::Ok)
210 }
static DeserializationException streamError()
static DeserializationException tooOld()
static DeserializationException tooNew()
QByteArray m_fileContent
int maxColumnCount
max found columns in raw data
QString error
error unrelated to lines
ImportSettings importSettings
Settings used for the import.

References QREDataLoader::ImportResult::calculationErrors, QREDataLoader::ImportResult::clear(), QREDataLoader::ImportSettings::columnDefinitions, QREDataLoader::ImportResult::error, QREDataLoader::ImportResult::eValues, QREDataLoader::ImportResult::importSettings, QREDataLoader::ImportResult::lines, m_fileContent, m_importResult, m_importSettings, QREDataLoader::ImportResult::maxColumnCount, QREDataLoader::ImportResult::qValues, QREDataLoader::ImportResult::rawValues, QREDataLoader::ImportResult::rValues, DeserializationException::streamError(), DeserializationException::tooNew(), DeserializationException::tooOld(), and QREDataLoader::ImportResult::validCalculatedLines.

Here is the call graph for this function:

◆ fileContent()

QByteArray QREDataLoader::fileContent ( ) const
overridevirtual

Returns the original file content. If not available any more (like for legacy project file import), then an empty array will be returned.

Reimplemented from AbstractDataLoader.

Definition at line 296 of file QREDataLoader.cpp.

297 {
298  return m_fileContent;
299 }

References m_fileContent.

Referenced by setFileContents().

◆ guessSettings()

void QREDataLoader::guessSettings ( )
overridevirtual

Guess appropriate settings (for example the separator in a CSV file). Is called only once, directly after setting the file content.

Reimplemented from AbstractDataLoader.

Definition at line 301 of file QREDataLoader.cpp.

302 {
303  // #baimport - move to utils; create unit test
304  // search for lines which start with a number, then try the separators
305 
306  const auto isFirstNumberChar = [](const QChar& c) {
307  return c.isNumber() || c == '.' || c == '+' || c == '-';
308  };
309 
310  const auto belongsToNumber = [](const QChar& c) {
311  return c.isNumber() || c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-';
312  };
313 
314  QTextStream in(m_fileContent);
315  int lineNr = 0;
316  const int maxLinesToExamine = 100;
317  while (!in.atEnd() && lineNr < maxLinesToExamine) {
318  lineNr++;
319  QString line = in.readLine().trimmed();
320  if (line.isEmpty())
321  continue;
322  if (!isFirstNumberChar(line[0]))
323  continue;
324 
325  // line starts with a number => search gap after it
326  int startOfGap = 1;
327  while (startOfGap < line.size() && belongsToNumber(line[startOfGap]))
328  startOfGap++;
329 
330  if (startOfGap == line.size())
331  continue;
332 
333  int endOfGap = startOfGap;
334  while (endOfGap < line.size() && !belongsToNumber(line[endOfGap]))
335  endOfGap++;
336 
337  QStringRef gapContent(&line, startOfGap, endOfGap - startOfGap);
338  if (gapContent.isEmpty())
339  continue;
340 
341  if (gapContent.contains("\t")) {
343  return;
344  }
345 
346  gapContent = gapContent.trimmed();
347  if (gapContent.isEmpty()) {
349  return;
350  }
351 
352  if (gapContent.contains(";")) {
354  return;
355  }
356 
357  if (gapContent.contains(",")) {
359  return;
360  }
361  }
362 }

References m_fileContent, m_importSettings, and QREDataLoader::ImportSettings::separator.

◆ importSettingsChanged

void AbstractDataLoader::importSettingsChanged ( )
signalinherited

◆ initWithDefaultImportSettings()

void QREDataLoader::initWithDefaultImportSettings ( )
overridevirtual

Set import settings to defaults.

Reimplemented from AbstractDataLoader.

Definition at line 134 of file QREDataLoader.cpp.

135 {
139 
140  for (const auto dataType : {DataType::Q, DataType::R, DataType::dR}) {
141  m_importSettings.columnDefinitions[dataType].enabled = true;
142  m_importSettings.columnDefinitions[dataType].column = (int)dataType;
144  m_importSettings.columnDefinitions[dataType].factor = 1.0;
145  }
146 
148 }

References QREDataLoader::ImportSettings::columnDefinitions, dR, QREDataLoader::ImportSettings::headerPrefix, QREDataLoader::ImportSettings::linesToSkip, m_importSettings, none, perNanoMeter, Q, R, and QREDataLoader::ImportSettings::separator.

Referenced by QREDataLoader().

◆ lineUnrelatedErrors()

QStringList QREDataLoader::lineUnrelatedErrors ( ) const
overridevirtual

Errors not related to a particular line.

Reimplemented from AbstractDataLoader.

Definition at line 283 of file QREDataLoader.cpp.

284 {
285  if (!m_importResult.error.isEmpty())
286  return {m_importResult.error};
287 
288  return {};
289 }

References QREDataLoader::ImportResult::error, and m_importResult.

◆ name()

QString QREDataLoader::name ( ) const
overridevirtual

The name shown in the format selection combo.

Implements AbstractDataLoader.

Definition at line 82 of file QREDataLoader.cpp.

83 {
84  return "CSV file (Reflectometry - Q/R/sigma_R)";
85 }

◆ numErrors()

int QREDataLoader::numErrors ( ) const
overridevirtual

Number of errors found while processing the content. An error means that either a particular content (line) can't be used or may be suspicious (line related error), or that the whole content can't be used (e.g. only 1 line present).

Reimplemented from AbstractDataLoader.

Definition at line 273 of file QREDataLoader.cpp.

274 {
275  return (m_importResult.error.isEmpty() ? 0 : 1) + m_importResult.calculationErrors.size();
276 }

References QREDataLoader::ImportResult::calculationErrors, QREDataLoader::ImportResult::error, and m_importResult.

◆ numLineRelatedErrors()

int QREDataLoader::numLineRelatedErrors ( ) const
overridevirtual

Number of errors related to a specific line. Such an error means that a particular content (line) can't be used or may be suspicious.

Reimplemented from AbstractDataLoader.

Definition at line 278 of file QREDataLoader.cpp.

279 {
280  return m_importResult.calculationErrors.size();
281 }

References QREDataLoader::ImportResult::calculationErrors, and m_importResult.

◆ parseFileContent()

void QREDataLoader::parseFileContent ( ) const
private

Definition at line 369 of file QREDataLoader.cpp.

370 {
372 
373  const QStringList headerPrefixes = (m_importSettings.headerPrefix.trimmed().isEmpty())
374  ? QStringList()
375  : m_importSettings.headerPrefix.split(",");
376 
377  const auto lineIsHeader = [headerPrefixes](const QString& line) {
378  for (const auto& prefix : headerPrefixes) {
379  if (line.startsWith(prefix.trimmed()))
380  return true;
381  }
382 
383  return false;
384  };
385 
386  const auto skippedLines = expandLineNumberPattern(m_importSettings.linesToSkip);
387  const auto lineShouldBeSkipped = [skippedLines](int lineNr) {
388  for (const auto& pair : skippedLines) {
389  if (lineNr >= pair.first && lineNr <= pair.second)
390  return true;
391  }
392  return false;
393  };
394 
395  QTextStream in(m_fileContent);
396  int lineNr = 0;
397  // if separator is SPACE: e.g. three consecutive SPACEs do not represent 3 columns => delete
398  // empty parts
399  QString::SplitBehavior splitBehavior =
400  m_importSettings.separator == " " ? QString::SkipEmptyParts : QString::KeepEmptyParts;
401 
402  while (!in.atEnd()) {
403  lineNr++;
404 
405  QString line = in.readLine();
406 
407  const bool skip =
408  lineIsHeader(line) || lineShouldBeSkipped(lineNr) || line.trimmed().isEmpty();
409 
410  m_importResult.lines << qMakePair(skip, line);
411  }
412 
414 
415  for (int lineNr = 0; lineNr < m_importResult.lines.size(); lineNr++) {
416  const bool skip = m_importResult.lines[lineNr].first;
417  if (skip)
418  continue;
419 
420  const QStringList lineEntries =
421  m_importResult.lines[lineNr].second.split(m_importSettings.separator, splitBehavior);
422 
424  std::max(m_importResult.maxColumnCount, lineEntries.count());
425 
426  QVector<double> rowEntriesAsDouble;
427 
428  for (int col = 0; col < lineEntries.count(); col++) {
429  bool ok = false;
430  double val = lineEntries[col].toDouble(&ok);
431  if (!ok)
432  val = std::numeric_limits<double>::quiet_NaN();
433 
434  rowEntriesAsDouble << val;
435  }
436 
437  m_importResult.rawValues[lineNr] = rowEntriesAsDouble;
438  }
439 }

References QREDataLoader::ImportResult::clear(), QREDataLoader::ImportSettings::headerPrefix, QREDataLoader::ImportResult::lines, QREDataLoader::ImportSettings::linesToSkip, m_fileContent, m_importResult, m_importSettings, QREDataLoader::ImportResult::maxColumnCount, QREDataLoader::ImportResult::rawValues, and QREDataLoader::ImportSettings::separator.

Referenced by processContents().

Here is the call graph for this function:

◆ persistentClassName()

QString QREDataLoader::persistentClassName ( ) const
overridevirtual

A name which can be used for save/load purposes (which will not change ever more)

Implements AbstractDataLoader.

Definition at line 87 of file QREDataLoader.cpp.

88 {
89  return "QREDataLoader";
90 }

◆ populateImportSettingsWidget()

void QREDataLoader::populateImportSettingsWidget ( QWidget *  parent)
overridevirtual

Fills the widget on the import dialog pane. The implementation here in the base class does nothing (meaning "no editable properties").

Reimplemented from AbstractDataLoader.

Definition at line 92 of file QREDataLoader.cpp.

93 {
94  if (m_propertiesWidget == nullptr)
96 
97  auto* l = new QHBoxLayout(parent);
98  l->setContentsMargins(0, 0, 0, 0);
99  parent->setLayout(l);
100  l->addWidget(m_propertiesWidget);
101 
102  if (m_importSettings.separator == " ")
103  m_propertiesWidget->m_ui->separatorCombo->setCurrentText("<SPACE>");
104  else if (m_importSettings.separator == "\t")
105  m_propertiesWidget->m_ui->separatorCombo->setCurrentText("<TAB>");
106  else
107  m_propertiesWidget->m_ui->separatorCombo->setCurrentText(m_importSettings.separator);
108 
109  m_propertiesWidget->m_ui->headerPrefixEdit->setText(m_importSettings.headerPrefix);
110  m_propertiesWidget->m_ui->linesToSkipEdit->setText(m_importSettings.linesToSkip);
111 
112  for (const auto dataType : {DataType::Q, DataType::R, DataType::dR}) {
113  m_propertiesWidget->columnSpinBox((int)dataType)
114  ->setValue(m_importSettings.columnDefinitions[dataType].column + 1); // view is 1-based
115 
116  m_propertiesWidget->factorSpinBox((int)dataType)
117  ->setValue(m_importSettings.columnDefinitions[dataType].factor);
118  }
119 
120  m_propertiesWidget->m_ui->enableErrorCheckBox->setChecked(
122 
124  m_propertiesWidget->m_ui->qUnitCombo->setCurrentIndex(1);
125  else
126  m_propertiesWidget->m_ui->qUnitCombo->setCurrentIndex(0); // 1/nm
127 
130  emit importSettingsChanged();
131  });
132 }
void importSettingsChanged()
Emitted whenever an import setting changed.
Properties widget for the QREDataLoader.
void applyImportSettings() override
Read all values from the properties UI into the internal variables.

References applyImportSettings(), QREDataLoader::ImportSettings::columnDefinitions, dR, QREDataLoader::ImportSettings::headerPrefix, AbstractDataLoader::importSettingsChanged(), QREDataLoader::ImportSettings::linesToSkip, m_importSettings, m_propertiesWidget, perAngstrom, QREDataLoaderProperties::propertiesChanged(), Q, R, and QREDataLoader::ImportSettings::separator.

Here is the call graph for this function:

◆ processContents()

void QREDataLoader::processContents ( )
overridevirtual

Process the file contents. Can be called more than once, e.g. if the import settings have changed. Any error has to be stored in the loader (see numErrors()).

Implements AbstractDataLoader.

Definition at line 219 of file QREDataLoader.cpp.

220 {
221  AutoEmit emitter([this] { contentsProcessed(); }); // automatic signal calling in any return
222 
223  // Important: If the current options match the ones in m_parsingResult, then nothing should be
224  // performed. Otherwise e.g. a linked instrument may have to be re-linked
225 
226  m_importResult.error.clear();
227 
228  ASSERT(m_item != nullptr);
229  ASSERT(m_item->isSpecularData());
230 
231  const auto invalidateItemData = [this]() {
233  m_item->specularDataItem()->setDatafield(nullptr);
234  };
235 
236  const bool parsingSettingsChanged =
240  const bool calculationSettingsChanged =
242  const bool calculationIsNecessary = (parsingSettingsChanged || calculationSettingsChanged);
243  const bool creationOfDatafieldIsNecessary = calculationIsNecessary;
244 
245  if (parsingSettingsChanged)
246  // everything has to be re-parsed
248 
249  if (calculationIsNecessary)
251 
253 
254  // -- make a few checks (mainly for fulfilling PointwiseAxis::sanityCheck())
256  m_importResult.error = "At least two full rows must exist";
257 
258  if (!m_importResult.error.isEmpty()) {
259  invalidateItemData();
260  return;
261  }
262 
263  if (creationOfDatafieldIsNecessary) {
264  try {
266  } catch (...) {
267  m_importResult.error = "Import not successful - caught an exception.";
268  invalidateItemData();
269  }
270  }
271 }
void contentsProcessed()
Emitted whenever contents have been processed.
RealDataItem * m_item
The real-data-item which owns this loader. Never delete this!
void calculateFromParseResult() const
void datafieldFromParsingResult(RealDataItem *item) const
void parseFileContent() const
void removeNativeData()
bool isSpecularData() const

References calculateFromParseResult(), QREDataLoader::ImportSettings::columnDefinitions, AbstractDataLoader::contentsProcessed(), datafieldFromParsingResult(), QREDataLoader::ImportResult::error, QREDataLoader::ImportSettings::headerPrefix, QREDataLoader::ImportResult::importSettings, RealDataItem::isSpecularData(), QREDataLoader::ImportSettings::linesToSkip, m_importResult, m_importSettings, AbstractDataLoader::m_item, parseFileContent(), RealDataItem::removeNativeData(), QREDataLoader::ImportSettings::separator, SpecularDataItem::setDatafield(), RealDataItem::specularDataItem(), and QREDataLoader::ImportResult::validCalculatedLines.

Here is the call graph for this function:

◆ realDataItem() [1/2]

RealDataItem * AbstractDataLoader::realDataItem ( )
inherited

The real data item on which the import shall work.

Definition at line 70 of file AbstractDataLoader.cpp.

71 {
72  return m_item;
73 }

References AbstractDataLoader::m_item.

◆ realDataItem() [2/2]

const RealDataItem * AbstractDataLoader::realDataItem ( ) const
inherited

The real data item on which the import shall work.

Definition at line 75 of file AbstractDataLoader.cpp.

76 {
77  return m_item;
78 }

References AbstractDataLoader::m_item.

◆ serialize()

QByteArray QREDataLoader::serialize ( ) const
overridevirtual

Returns every internal setting so it can be restored completely.

Reimplemented from AbstractDataLoader.

Definition at line 150 of file QREDataLoader.cpp.

151 {
152  // changed in version 2: no file hash anymore (1 was only a developer version)
153  // changed in version 3: refactored lists/vectors (2 was only a developer version)
154  // changed in version 4: refactored lists/vectors (3 was only a developer version)
155 
156  QByteArray a;
157  QDataStream s(&a, QIODevice::WriteOnly);
158  s.setVersion(QDataStream::Qt_5_12);
159 
160  s << (quint8)4; // version
161  s << m_fileContent;
162  s << m_importSettings;
163  s << m_importResult.lines;
165  s << m_importResult.qValues;
166  s << m_importResult.rValues;
167  s << m_importResult.eValues;
171  s << m_importResult.error;
173 
174  return a;
175 }

References QREDataLoader::ImportResult::calculationErrors, QREDataLoader::ImportResult::error, QREDataLoader::ImportResult::eValues, QREDataLoader::ImportResult::importSettings, QREDataLoader::ImportResult::lines, m_fileContent, m_importResult, m_importSettings, QREDataLoader::ImportResult::maxColumnCount, QREDataLoader::ImportResult::qValues, QREDataLoader::ImportResult::rawValues, QREDataLoader::ImportResult::rValues, and QREDataLoader::ImportResult::validCalculatedLines.

Referenced by clone(), and QREDataLoader::ImportSettings::operator!=().

◆ setFileContents()

void QREDataLoader::setFileContents ( const QByteArray &  fileContent)
overridevirtual

Sets the file contents to be imported. If the file was a compressed file, then the decompressed content will be handed over already here.

Implements AbstractDataLoader.

Definition at line 364 of file QREDataLoader.cpp.

365 {
367 }
QByteArray fileContent() const override
Returns the original file content. If not available any more (like for legacy project file import),...

References fileContent(), and m_fileContent.

Here is the call graph for this function:

◆ setRealDataItem()

void AbstractDataLoader::setRealDataItem ( RealDataItem item)
inherited

Define the real data item on which the import shall work.

Definition at line 65 of file AbstractDataLoader.cpp.

66 {
67  m_item = item;
68 }

References AbstractDataLoader::m_item.

Referenced by GUI::View::ImportDataUtils::Import1dData(), and SpecularDataImportWidget::onFormatSelectionChanged().

Friends And Related Function Documentation

◆ operator<< [1/2]

QDataStream& operator<< ( QDataStream &  stream,
const QREDataLoader::ErrorDefinition s 
)
friend

Definition at line 760 of file QREDataLoader.cpp.

761 {
762  stream << (quint8)s.type;
763  if (std::holds_alternative<int>(s.data)) {
764  stream << true;
765  stream << quint32(std::get<int>(s.data));
766  } else {
767  stream << false;
768  stream << qreal(std::get<double>(s.data));
769  }
770 
771  return stream;
772 }
std::variant< int, double > data
Additional data; meaning depends on the error type (see implementation of toString() for more informa...

◆ operator<< [2/2]

QDataStream& operator<< ( QDataStream &  stream,
const QREDataLoader::ImportSettings s 
)
friend

Definition at line 572 of file QREDataLoader.cpp.

573 {
574  stream << s.serialize();
575  return stream;
576 }

◆ operator>> [1/2]

QDataStream& operator>> ( QDataStream &  stream,
QREDataLoader::ErrorDefinition s 
)
friend

Definition at line 774 of file QREDataLoader.cpp.

775 {
776  quint8 t;
777  stream >> t;
779  bool isInt = false;
780  stream >> isInt;
781  if (isInt) {
782  quint32 d;
783  stream >> d;
784  s.data = int(d);
785  } else {
786  qreal d;
787  stream >> d;
788  s.data = double(d);
789  }
790 
791  return stream;
792 }

◆ operator>> [2/2]

QDataStream& operator>> ( QDataStream &  stream,
QREDataLoader::ImportSettings s 
)
friend

Definition at line 578 of file QREDataLoader.cpp.

579 {
580  QByteArray b;
581  stream >> b;
582  s.deserialize(b);
583  return stream;
584 }
void deserialize(const QByteArray &data)

◆ QREDataLoaderResultModel

friend class QREDataLoaderResultModel
friend

Definition at line 137 of file QREDataLoader.h.

Referenced by createResultModel().

Member Data Documentation

◆ m_fileContent

QByteArray QREDataLoader::m_fileContent
private

◆ m_importResult

◆ m_importSettings

◆ m_item

RealDataItem* AbstractDataLoader::m_item
protectedinherited

◆ m_propertiesWidget

QPointer<QREDataLoaderProperties> QREDataLoader::m_propertiesWidget
private

Definition at line 131 of file QREDataLoader.h.

Referenced by applyImportSettings(), and populateImportSettingsWidget().


The documentation for this class was generated from the following files: