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

Real data loader for Q/R/E reflectometry CSV files. More...

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). More...
 
struct  ImportResult
 Result of the file import. 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 ()
 
virtual void applyImportSettings () override
 Read all values from the properties UI into the internal variables. More...
 
virtual AbstractDataLoaderclone () const override
 Create a complete clone, including all internal states. More...
 
virtual 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. More...
 
virtual QByteArray defaultImportSettings () const
 Return the default import settings. More...
 
virtual void deserialize (const QByteArray &data) override
 Initialize from serialization data. More...
 
virtual QByteArray fileContent () const override
 Returns the original file content. More...
 
virtual void guessSettings () override
 Guess appropriate settings (for example the separator in a CSV file). More...
 
virtual void initWithDefaultImportSettings () override
 Set import settings to defaults. More...
 
virtual QStringList lineUnrelatedErrors () const override
 Errors not related to a particular line. More...
 
virtual QString name () const override
 The name shown in the format selection combo. More...
 
virtual int numErrors () const override
 Number of errors found while processing the content. More...
 
virtual int numLineRelatedErrors () const override
 Number of errors related to a specific line. More...
 
virtual QString persistentClassName () const override
 A name which can be used for save/load purposes (which will not change ever more) More...
 
virtual void populateImportSettingsWidget (QWidget *parent) override
 Fills the widget on the import dialog pane. More...
 
virtual void processContents () override
 Process the file contents. 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...
 
virtual QByteArray serialize () const override
 Returns every internal setting so it can be restored completely. More...
 
virtual void setFileContents (const QByteArray &fileContent) override
 Sets the file contents to be imported. More...
 
void setRealDataItem (RealDataItem *item)
 Define the real data item on which the import shall work. More...
 

Protected Types

enum class  Error { DifferendNumberOfColumns }
 

Protected Attributes

RealDataItemm_item
 

Private Types

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

Private Member Functions

void calculateFromParseResult () const
 
void createOutputDataFromParsingResult (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
 

Detailed Description

Real data loader for Q/R/E reflectometry CSV files.

Definition at line 27 of file QREDataLoader.h.

Member Enumeration Documentation

◆ DataType

enum QREDataLoader::DataType
strongprivate
Enumerator
dR 

Definition at line 64 of file QREDataLoader.h.

64 { Q, R, dR };

◆ Error

enum AbstractDataLoader::Error
strongprotectedinherited
Enumerator
DifferendNumberOfColumns 

Definition at line 119 of file AbstractDataLoader.h.

119 { DifferendNumberOfColumns };

◆ UnitInFile

enum QREDataLoader::UnitInFile
strongprivate
Enumerator
none 
perNanoMeter 
perAngstrom 
other 

Definition at line 53 of file QREDataLoader.h.

53 { none, perNanoMeter, perAngstrom, other };
@ none
undefined converter mode

Constructor & Destructor Documentation

◆ QREDataLoader()

QREDataLoader::QREDataLoader ( )

Definition at line 78 of file QREDataLoader.cpp.

78  : m_propertiesWidget(nullptr)
79 {
81 }
virtual 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 591 of file QREDataLoader.cpp.

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 }
struct QREDataLoader::ImportSettings m_importSettings
QString separator
column separator
Definition: QREDataLoader.h:68
QMap< DataType, ColumnDefinition > columnDefinitions
Definition: QREDataLoader.h:71
QString headerPrefix
prefix denoting header line
Definition: QREDataLoader.h:69
QString linesToSkip
pattern denoting line to skip (i.e. '1,10-12,42')
Definition: QREDataLoader.h:70

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

◆ calculateFromParseResult()

void QREDataLoader::calculateFromParseResult ( ) const
private

Definition at line 445 of file QREDataLoader.cpp.

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 }
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

References QREDataLoader::ImportResult::addError(), 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, QREDataLoader::ImportResult::validCalculatedLines, and QREDataLoader::ErrorDefinition::wrongQOrder.

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 213 of file QREDataLoader.cpp.

214 {
215  auto loader = new QREDataLoader();
216  loader->deserialize(serialize());
217  return loader;
218 }
virtual 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().

◆ createOutputDataFromParsingResult()

void QREDataLoader::createOutputDataFromParsingResult ( RealDataItem item) const
private

Definition at line 532 of file QREDataLoader.cpp.

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 }
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
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
void initNativeData()
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
QMap< int, ErrorDefinition > calculationErrors
calculation error per line; line is 0-based

References OutputData< T >::addAxis(), QREDataLoader::ImportResult::calculationErrors, OutputData< T >::clone(), SessionItem::getItem(), RealDataItem::initNativeData(), AxisNames::InitSpecAxis(), QREDataLoader::ImportResult::lines, m_importResult, JobItemUtils::nameFromAxesUnits(), DataItem::P_AXES_UNITS, QREDataLoader::ImportResult::qValues, QREDataLoader::ImportResult::rValues, SpecularDataItem::setAxesRangeToData(), SessionItem::setItemValue(), RealDataItem::setNativeDataUnits(), RealDataItem::setNativeOutputData(), SpecularDataItem::setOutputData(), OutputData< T >::setRawDataVector(), SessionItem::setVisible(), SpecularDataItem::setXaxisTitle(), SpecularDataItem::setYaxisTitle(), RealDataItem::specularDataItem(), and ComboProperty::variant().

Referenced by processContents().

Here is the call graph for this function:

◆ 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 293 of file QREDataLoader.cpp.

294 {
296 }
friend class QREDataLoaderResultModel

References m_importResult, and QREDataLoaderResultModel.

◆ 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 178 of file QREDataLoader.cpp.

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 }
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 298 of file QREDataLoader.cpp.

299 {
300  return m_fileContent;
301 }

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 303 of file QREDataLoader.cpp.

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 }

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 135 of file QREDataLoader.cpp.

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 }

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 285 of file QREDataLoader.cpp.

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

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 83 of file QREDataLoader.cpp.

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

◆ 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 275 of file QREDataLoader.cpp.

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

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 280 of file QREDataLoader.cpp.

281 {
282  return m_importResult.calculationErrors.size();
283 }

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

◆ parseFileContent()

void QREDataLoader::parseFileContent ( ) const
private

Definition at line 372 of file QREDataLoader.cpp.

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 }

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 88 of file QREDataLoader.cpp.

89 {
90  return "QREDataLoader";
91 }

◆ populateImportSettingsWidget()

void QREDataLoader::populateImportSettingsWidget ( QWidget *  parent)
overridevirtual

Fills the widget on the import dialog pane.

This base class' implementation does nothing (meaning "no editable properties")

Reimplemented from AbstractDataLoader.

Definition at line 93 of file QREDataLoader.cpp.

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 
131  emit importSettingsChanged();
132  });
133 }
void importSettingsChanged()
Emitted whenever an import setting changed.
Properties widget for the QREDataLoader.
virtual void applyImportSettings() override
Read all values from the properties UI into the internal variables.

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

◆ 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 220 of file QREDataLoader.cpp.

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 }
#define ASSERT(condition)
Definition: Assert.h:31
void contentsProcessed()
Emitted whenever contents have been processed.
void calculateFromParseResult() const
void createOutputDataFromParsingResult(RealDataItem *item) const
void parseFileContent() const
void removeNativeData()
bool isSpecularData() const

References ASSERT, calculateFromParseResult(), QREDataLoader::ImportSettings::columnDefinitions, AbstractDataLoader::contentsProcessed(), createOutputDataFromParsingResult(), 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::setOutputData(), 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 151 of file QREDataLoader.cpp.

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 }

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, here already the decompressed content will be overhanded.

Implements AbstractDataLoader.

Definition at line 367 of file QREDataLoader.cpp.

368 {
370 }
virtual QByteArray fileContent() const override
Returns the original file content.

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 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 759 of file QREDataLoader.cpp.

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 }
std::variant< int, double > data
Additional data; meaning depends on the error type (see implementation of toString() for more informa...
Definition: QREDataLoader.h:98

◆ operator<< [2/2]

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

Definition at line 577 of file QREDataLoader.cpp.

578 {
579  stream << s.serialize();
580  return stream;
581 }

◆ operator>> [1/2]

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

Definition at line 773 of file QREDataLoader.cpp.

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 }

◆ operator>> [2/2]

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

Definition at line 583 of file QREDataLoader.cpp.

584 {
585  QByteArray b;
586  stream >> b;
587  s.deserialize(b);
588  return stream;
589 }
void deserialize(const QByteArray &data)

◆ QREDataLoaderResultModel

friend class QREDataLoaderResultModel
friend

Definition at line 134 of file QREDataLoader.h.

Referenced by createResultModel().

Member Data Documentation

◆ m_fileContent

QByteArray QREDataLoader::m_fileContent
private

◆ m_importResult

◆ m_importSettings

◆ m_item

◆ m_propertiesWidget

QPointer<QREDataLoaderProperties> QREDataLoader::m_propertiesWidget
private

Definition at line 128 of file QREDataLoader.h.

Referenced by applyImportSettings(), and populateImportSettingsWidget().


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