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

Logic for importing intensity data from csv files. More...

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

Public Member Functions

 CsvImportAssistant (const QString &file, const bool useGUI=false, QWidget *parent=nullptr)
 
size_t columnCount ()
 
ImportDataInfo getData ()
 
char separator ()
 
void setCoordinateColumn (int iCol, Axes::Units units, double multiplier=1.0)
 
void setFirstRow (int iRow)
 
void setIntensityColumn (int iCol, double multiplier=1.0)
 
void setLastRow (int iRow)
 

Static Public Member Functions

static void showErrorMessage (std::string message)
 

Private Member Functions

ImportDataInfo fillData ()
 
void getValuesFromColumns (std::vector< double > &intensityVals, std::vector< double > &coordVals)
 
char guessSeparator () const
 
bool hasEqualLengthLines (csv::DataArray &dataArray)
 
bool loadCsvFile ()
 
void removeBlankColumns ()
 
void removeMultipleWhiteSpaces ()
 
void resetAssistant ()
 
void resetSelection ()
 
void runDataSelector (QWidget *parent)
 

Private Attributes

int m_coordinateColNum
 
double m_coordinateMultiplier
 
csv::DataArray m_csvArray
 
std::unique_ptr< CSVFilem_csvFile
 
bool m_dataAvailable
 
QString m_fileName
 
int m_firstRow
 
int m_intensityColNum
 
double m_intensityMultiplier
 
int m_lastRow
 
std::set< int > m_rowsToDiscard
 
char m_separator
 
Axes::Units m_units
 

Detailed Description

Logic for importing intensity data from csv files.

Definition at line 52 of file CsvImportAssistant.h.

Constructor & Destructor Documentation

◆ CsvImportAssistant()

CsvImportAssistant::CsvImportAssistant ( const QString &  file,
const bool  useGUI = false,
QWidget *  parent = nullptr 
)

Definition at line 30 of file CsvImportAssistant.cpp.

31  : m_fileName(file)
32  , m_csvFile(nullptr)
33  , m_csvArray()
34  , m_separator('\0')
35  , m_intensityColNum(-1)
37  , m_coordinateColNum(-1)
39  , m_firstRow(-1)
40  , m_lastRow(-1)
41  , m_units(Axes::Units::NBINS)
42  , m_dataAvailable(false)
43 {
44  if (!loadCsvFile()) {
45  return;
46  }
47 
48  if (useGUI) {
49  runDataSelector(parent);
50  } else {
52  m_coordinateColNum = -1;
53  m_units = Axes::Units::NBINS;
54  m_firstRow = 0;
55  m_lastRow = int(m_csvFile->NumberOfRows() - 1);
56  m_dataAvailable = true;
57  }
58 }
csv::DataArray m_csvArray
std::unique_ptr< CSVFile > m_csvFile
void runDataSelector(QWidget *parent)

References loadCsvFile(), m_coordinateColNum, m_csvFile, m_dataAvailable, m_firstRow, m_intensityColNum, m_lastRow, m_units, and runDataSelector().

Here is the call graph for this function:

Member Function Documentation

◆ columnCount()

size_t CsvImportAssistant::columnCount ( )
inline

Definition at line 62 of file CsvImportAssistant.h.

62 { return m_csvArray[0].size(); }

References m_csvArray.

◆ fillData()

ImportDataInfo CsvImportAssistant::fillData ( )
private

Definition at line 165 of file CsvImportAssistant.cpp.

166 {
167  // In case a 2d import is needed in the future
168  // Use ArrayUtils::Create2dData(vector<vector<double>>)
169  // ArrayUtils::Create2d
170  std::unique_ptr<OutputData<double>> resultOutputData;
171  resultOutputData = std::make_unique<OutputData<double>>();
172  std::vector<double> intensityValues;
173  std::vector<double> coordinateValues;
174 
175  getValuesFromColumns(intensityValues, coordinateValues);
176 
177  const auto axisName = axisUnitLabel.at(m_units);
178  PointwiseAxis coordAxis(axisName, coordinateValues);
179  resultOutputData->addAxis(coordAxis);
180  resultOutputData->setRawDataVector(intensityValues);
181 
182  ImportDataInfo result(std::move(resultOutputData), m_units);
183  return result;
184 }
const std::map< Axes::Units, const char * > axisUnitLabel
void getValuesFromColumns(std::vector< double > &intensityVals, std::vector< double > &coordVals)
Carries information about loaded data.
Axis containing arbitrary (non-equidistant) coordinate values.
Definition: PointwiseAxis.h:37

References axisUnitLabel, getValuesFromColumns(), and m_units.

Referenced by getData().

Here is the call graph for this function:

◆ getData()

ImportDataInfo CsvImportAssistant::getData ( )
inline

Definition at line 56 of file CsvImportAssistant.h.

56 { return m_dataAvailable ? fillData() : ImportDataInfo(); }
ImportDataInfo fillData()

References fillData(), and m_dataAvailable.

Here is the call graph for this function:

◆ getValuesFromColumns()

void CsvImportAssistant::getValuesFromColumns ( std::vector< double > &  intensityVals,
std::vector< double > &  coordVals 
)
private

Definition at line 186 of file CsvImportAssistant.cpp.

188 {
189  bool intensityOk = true;
190  bool coordinateOk = true;
191  auto firstRow = size_t(m_firstRow);
192  auto lastRow = size_t(m_lastRow) + 1;
193  bool isCoordinateNeeded = m_coordinateColNum > -1;
194  double intensityValue = 0.;
195  double coordinateValue = 0.;
196 
197  for (size_t row = firstRow; row < lastRow; row++) {
198  if (std::find(m_rowsToDiscard.begin(), m_rowsToDiscard.end(), int(row))
199  == m_rowsToDiscard.end()) {
200  // Intensity Values:
201  QString intensityText =
202  QString::fromStdString(m_csvArray[row][size_t(m_intensityColNum)]);
203  intensityValue = intensityText.toDouble(&intensityOk);
204 
205  // Coordinate Values:
206  if (isCoordinateNeeded) {
207  QString coordinateText =
208  QString::fromStdString(m_csvArray[row][size_t(m_coordinateColNum)]);
209  coordinateValue = coordinateText.toDouble(&coordinateOk);
210  } else {
211  coordinateValue = row - firstRow;
212  }
213 
214  // Add them if they are both ok:
215  if (intensityOk && coordinateOk) {
216  intensityValues.push_back(m_intensityMultiplier * intensityValue);
217  coordinateValues.push_back(m_coordinateMultiplier * coordinateValue);
218  }
219  }
220  }
221 }
std::set< int > m_rowsToDiscard

References m_coordinateColNum, m_coordinateMultiplier, m_csvArray, m_firstRow, m_intensityColNum, m_intensityMultiplier, m_lastRow, and m_rowsToDiscard.

Referenced by fillData().

◆ guessSeparator()

char CsvImportAssistant::guessSeparator ( ) const
private

Definition at line 312 of file CsvImportAssistant.cpp.

313 {
314  int frequencies[127] = {0};
315 
316  // The actual characters that may be realistically
317  // used as separators are only a handfull...
318  // And this list seems already exagerated.
319  std::vector<char> preferredSeparators;
320  preferredSeparators.push_back(' ');
321  preferredSeparators.push_back(',');
322  preferredSeparators.push_back(';');
323  preferredSeparators.push_back('|');
324  preferredSeparators.push_back(':');
325  preferredSeparators.push_back('\t');
326  // preferredSeparators.push_back('/');
327  // preferredSeparators.push_back('\\');
328  // preferredSeparators.push_back('_');
329  preferredSeparators.push_back('\'');
330  preferredSeparators.push_back('\"');
331 
332  // count number of occurences of each char in the file:
333  char c;
334  std::ifstream is(m_fileName.toStdString());
335  while (is.get(c)) {
336  if (size_t(c) < 127)
337  frequencies[size_t(c)]++;
338  }
339  is.close();
340 
341  // set the guessed separator as the most frequent among the
342  // preferred separators. -- Some unavoidable hieararchy is
343  // present: characters with lower ascii code are preferred.
344  char guessedSep = ' ';
345  int freq = 0;
346  for (char i = 0; i < 127; i++) {
347  if (std::find(preferredSeparators.begin(), preferredSeparators.end(), i)
348  != preferredSeparators.end())
349  if (frequencies[int(i)] > freq) {
350  freq = frequencies[int(i)];
351  guessedSep = i;
352  }
353  }
354 
355  // We don't like tabs, as we cannot write them in the GUI.
356  // The rest of the CsvImportAssistant and CsvReader should be already aware of this.
357  if (guessedSep == '\t')
358  guessedSep = ' ';
359 
360  return guessedSep;
361 }

References m_fileName.

Referenced by loadCsvFile(), and runDataSelector().

◆ hasEqualLengthLines()

bool CsvImportAssistant::hasEqualLengthLines ( csv::DataArray dataArray)
private

Definition at line 363 of file CsvImportAssistant.cpp.

364 {
365  auto tf = all_of(begin(dataArray), end(dataArray), [dataArray](const csv::DataRow& x) {
366  return x.size() == dataArray.front().size();
367  });
368  return tf;
369 }
std::vector< std::string > DataRow
Definition: CsvNamespace.h:27

Referenced by removeBlankColumns().

◆ loadCsvFile()

bool CsvImportAssistant::loadCsvFile ( )
private

Definition at line 112 of file CsvImportAssistant.cpp.

113 {
114 
115  try {
116  if (m_separator == '\0')
118  m_csvFile = std::make_unique<CSVFile>(m_fileName.toStdString(), m_separator);
119  } catch (...) {
120  showErrorMessage("There was a problem opening the file \"" + m_fileName.toStdString()
121  + "\"");
122  return false;
123  }
124 
125  size_t lastRow = m_csvFile->NumberOfRows();
126 
127  if (lastRow < 1) {
128  CsvImportAssistant::showErrorMessage("The file exist but it seems to be empty");
129  return false;
130  }
131 
132  auto csvArray = m_csvFile->asArray();
133 
134  // Automatically ignore empty lines at the end:
135  while (QString::fromStdString(accumulate(csvArray[lastRow - 1].begin(),
136  csvArray[lastRow - 1].end(), std::string("")))
137  .trimmed()
138  == "") {
139  lastRow--;
140  if (lastRow < 1) {
141  CsvImportAssistant::showErrorMessage("The file exist but it seems to be empty");
142  return false;
143  }
144  }
145 
146  // TODO: If separator is white space, ignore consecutive spaces...
147  // {
148  // }
149 
150  csv::DataArray tmp(csvArray.begin(), csvArray.begin() + int(lastRow));
151  m_csvArray.swap(tmp);
153  if (m_separator == ' ')
155 
156  return true;
157 }
static void showErrorMessage(std::string message)
std::vector< std::vector< std::string > > DataArray
Definition: CsvNamespace.h:26

References guessSeparator(), m_csvArray, m_csvFile, m_fileName, m_separator, removeBlankColumns(), removeMultipleWhiteSpaces(), and showErrorMessage().

Referenced by CsvImportAssistant(), resetAssistant(), and runDataSelector().

Here is the call graph for this function:

◆ removeBlankColumns()

void CsvImportAssistant::removeBlankColumns ( )
private

Definition at line 261 of file CsvImportAssistant.cpp.

262 {
263 
264  if (m_csvArray.empty())
265  return;
266 
267  csv::DataArray buffer2d;
268  csv::DataRow buffer1d;
269  std::vector<int> to_be_removed;
270 
271  size_t nRows = m_csvArray.size();
272  size_t nCols = m_csvArray[0].size();
273 
275  throw std::runtime_error("All inner vectors should have the same length already.");
276  }
277 
278  // traverse the array columnwise -- this may be inneficient.
279  for (size_t j = 0; j < nCols; j++) {
280  buffer1d.clear();
281  for (size_t i = 0; i < nRows; i++) {
282  buffer1d.push_back(m_csvArray[i][j]);
283  }
284  if (QString::fromStdString(accumulate(buffer1d.begin(), buffer1d.end(), std::string("")))
285  .trimmed()
286  == "")
287  continue;
288 
289  buffer2d.push_back(buffer1d);
290  }
291 
292  if (buffer2d.empty()) {
293  m_csvArray.clear();
294  return;
295  }
296 
297  // now buffer2d has the original array, without blank columns, transposed.
298  nCols = buffer2d.size();
299  nRows = buffer2d[0].size();
300 
301  // Save the modified array --i.e. transpose buffer2d
302  m_csvArray.clear();
303  for (size_t i = 0; i < nRows; i++) {
304  buffer1d.clear();
305  for (size_t j = 0; j < nCols; j++) {
306  buffer1d.push_back(buffer2d[j][i]);
307  }
308  m_csvArray.push_back(buffer1d);
309  }
310 }
bool hasEqualLengthLines(csv::DataArray &dataArray)

References hasEqualLengthLines(), and m_csvArray.

Referenced by loadCsvFile().

Here is the call graph for this function:

◆ removeMultipleWhiteSpaces()

void CsvImportAssistant::removeMultipleWhiteSpaces ( )
private

Definition at line 223 of file CsvImportAssistant.cpp.

224 {
225  if (m_csvArray.empty())
226  return;
227 
228  csv::DataArray buffer2d;
229  csv::DataRow buffer1d;
230  size_t nRows = m_csvArray.size();
231  size_t nCols = m_csvArray[0].size();
232  size_t newNcols = 0;
233 
234  for (size_t i = 0; i < nRows; i++) {
235  buffer1d.clear();
236  for (size_t j = 0; j < nCols; j++) {
237  QString text = QString::fromStdString(m_csvArray[i][j]).trimmed();
238  if (text != "")
239  buffer1d.push_back(text.toStdString());
240  }
241  newNcols = std::max(buffer1d.size(), newNcols);
242  buffer2d.push_back(buffer1d);
243  }
244 
245  if (buffer2d.empty()) {
246  m_csvArray.clear();
247  return;
248  }
249 
250  for (size_t i = 0; i < nRows; i++)
251  while (buffer2d[i].size() < newNcols)
252  buffer2d[i].push_back("");
253 
254  // now buffer2d has the original array, without empty cells
255  nRows = buffer2d.size();
256  nCols = buffer2d[0].size();
257 
258  m_csvArray.swap(buffer2d);
259 }

References m_csvArray.

Referenced by loadCsvFile().

◆ resetAssistant()

void CsvImportAssistant::resetAssistant ( )
private

Definition at line 159 of file CsvImportAssistant.cpp.

160 {
161  resetSelection();
162  loadCsvFile();
163 }

References loadCsvFile(), and resetSelection().

Here is the call graph for this function:

◆ resetSelection()

void CsvImportAssistant::resetSelection ( )
private

Definition at line 379 of file CsvImportAssistant.cpp.

380 {
381  m_csvArray.clear();
382  m_intensityColNum = -1;
383  m_coordinateColNum = -1;
384  m_firstRow = -1;
385  m_lastRow = -1;
386  m_units = Axes::Units::NBINS;
387  m_dataAvailable = false;
388 }

References m_coordinateColNum, m_csvArray, m_dataAvailable, m_firstRow, m_intensityColNum, m_lastRow, and m_units.

Referenced by resetAssistant().

◆ runDataSelector()

void CsvImportAssistant::runDataSelector ( QWidget *  parent)
private

Definition at line 60 of file CsvImportAssistant.cpp.

61 {
62  DataSelector selector(m_csvArray, parent);
64  selector.setSeparator(guessSeparator());
65  connect(&selector, &DataSelector::separatorChanged, this, [this, &selector](char newSep) {
66  if (newSep != m_separator) {
67  m_separator = newSep;
68  loadCsvFile();
69  selector.setDataArray(m_csvArray);
70  selector.setSeparator(newSep);
71  }
72  });
73 
74  int res = selector.exec();
75 
76  if (res == selector.Accepted) {
77  m_intensityColNum = selector.intensityColumn();
78  m_intensityMultiplier = selector.intensityMultiplier();
79  m_coordinateColNum = selector.coordinateColumn();
80  m_coordinateMultiplier = selector.coordinateMultiplier();
81  m_units = selector.units();
82  m_firstRow = int(selector.firstLine() - 1);
83  m_lastRow = int(selector.lastLine() - 1);
84  m_rowsToDiscard = selector.rowsToDiscard();
85  m_dataAvailable = true;
86  } else if (res == selector.Rejected) {
87  m_dataAvailable = false;
88  return;
89  }
90 }
Dialog to hold DataSelector.
Definition: DataSelector.h:32
void separatorChanged(char newSeparator)

References DataSelector::coordinateColumn(), DataSelector::coordinateMultiplier(), DataSelector::firstLine(), guessSeparator(), DataSelector::intensityColumn(), DataSelector::intensityMultiplier(), DataSelector::lastLine(), loadCsvFile(), m_coordinateColNum, m_coordinateMultiplier, m_csvArray, m_dataAvailable, m_firstRow, m_intensityColNum, m_intensityMultiplier, m_lastRow, m_rowsToDiscard, m_separator, m_units, DataSelector::rowsToDiscard(), DataSelector::separatorChanged(), DataSelector::setDataArray(), DataSelector::setSeparator(), and DataSelector::units().

Referenced by CsvImportAssistant().

Here is the call graph for this function:

◆ separator()

char CsvImportAssistant::separator ( )
inline

Definition at line 63 of file CsvImportAssistant.h.

63 { return m_separator; }

References m_separator.

◆ setCoordinateColumn()

void CsvImportAssistant::setCoordinateColumn ( int  iCol,
Axes::Units  units,
double  multiplier = 1.0 
)

Definition at line 97 of file CsvImportAssistant.cpp.

98 {
99  m_coordinateColNum = iCol - 1;
100  m_units = units;
101  m_coordinateMultiplier = multiplier;
102 }

References m_coordinateColNum, m_coordinateMultiplier, and m_units.

◆ setFirstRow()

void CsvImportAssistant::setFirstRow ( int  iRow)

Definition at line 103 of file CsvImportAssistant.cpp.

104 {
105  m_firstRow = iRow - 1;
106 }

References m_firstRow.

◆ setIntensityColumn()

void CsvImportAssistant::setIntensityColumn ( int  iCol,
double  multiplier = 1.0 
)

Definition at line 92 of file CsvImportAssistant.cpp.

93 {
94  m_intensityColNum = iCol - 1;
95  m_intensityMultiplier = multiplier;
96 }

References m_intensityColNum, and m_intensityMultiplier.

◆ setLastRow()

void CsvImportAssistant::setLastRow ( int  iRow)

Definition at line 107 of file CsvImportAssistant.cpp.

108 {
109  m_lastRow = iRow - 1;
110 }

References m_lastRow.

◆ showErrorMessage()

void CsvImportAssistant::showErrorMessage ( std::string  message)
static

Definition at line 371 of file CsvImportAssistant.cpp.

372 {
373  QMessageBox msgBox;
374  msgBox.setText(QString::fromStdString(message));
375  msgBox.setIcon(msgBox.Critical);
376  msgBox.exec();
377 }

Referenced by loadCsvFile(), and DataSelector::updateData().

Member Data Documentation

◆ m_coordinateColNum

int CsvImportAssistant::m_coordinateColNum
private

◆ m_coordinateMultiplier

double CsvImportAssistant::m_coordinateMultiplier
private

Definition at line 84 of file CsvImportAssistant.h.

Referenced by getValuesFromColumns(), runDataSelector(), and setCoordinateColumn().

◆ m_csvArray

◆ m_csvFile

std::unique_ptr<CSVFile> CsvImportAssistant::m_csvFile
private

Definition at line 78 of file CsvImportAssistant.h.

Referenced by CsvImportAssistant(), and loadCsvFile().

◆ m_dataAvailable

bool CsvImportAssistant::m_dataAvailable
private

Definition at line 89 of file CsvImportAssistant.h.

Referenced by CsvImportAssistant(), getData(), resetSelection(), and runDataSelector().

◆ m_fileName

QString CsvImportAssistant::m_fileName
private

Definition at line 77 of file CsvImportAssistant.h.

Referenced by guessSeparator(), and loadCsvFile().

◆ m_firstRow

int CsvImportAssistant::m_firstRow
private

◆ m_intensityColNum

int CsvImportAssistant::m_intensityColNum
private

◆ m_intensityMultiplier

double CsvImportAssistant::m_intensityMultiplier
private

Definition at line 82 of file CsvImportAssistant.h.

Referenced by getValuesFromColumns(), runDataSelector(), and setIntensityColumn().

◆ m_lastRow

int CsvImportAssistant::m_lastRow
private

◆ m_rowsToDiscard

std::set<int> CsvImportAssistant::m_rowsToDiscard
private

Definition at line 87 of file CsvImportAssistant.h.

Referenced by getValuesFromColumns(), and runDataSelector().

◆ m_separator

char CsvImportAssistant::m_separator
private

Definition at line 80 of file CsvImportAssistant.h.

Referenced by loadCsvFile(), runDataSelector(), and separator().

◆ m_units

Axes::Units CsvImportAssistant::m_units
private

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