From 9da2194ccd3ef3ac982d9975d05b48bb1c7dbd7f Mon Sep 17 00:00:00 2001 From: "Joachim Wuttke (o)" <j.wuttke@fz-juelich.de> Date: Tue, 23 May 2023 15:17:02 +0200 Subject: [PATCH] importing legacy tables with 2-3 columns works --- Base/Util/StringUtil.cpp | 2 ++ Device/IO/IOFactory.cpp | 23 ++++++++++++++++++---- Device/IO/IOFactory.h | 2 +- Device/IO/ImportSettings.cpp | 18 +++-------------- Device/IO/ImportSettings.h | 7 ++++++- Device/IO/ReadReflectometry.cpp | 2 +- GUI/View/Import/RealDataSelectorWidget.cpp | 12 +++++++---- auto/Wrap/libBornAgainDevice.py | 8 ++++++++ auto/Wrap/libBornAgainDevice_wrap.cpp | 4 ++++ 9 files changed, 52 insertions(+), 26 deletions(-) diff --git a/Base/Util/StringUtil.cpp b/Base/Util/StringUtil.cpp index 67e417e775a..acd760fe29e 100644 --- a/Base/Util/StringUtil.cpp +++ b/Base/Util/StringUtil.cpp @@ -31,6 +31,8 @@ std::string Base::String::padRight(const std::string& name, size_t length) //! Returns token vector obtained by splitting string at delimiters. std::vector<std::string> Base::String::split(const std::string& text, const std::string& delimiter) { + if (text.empty()) + return {}; std::vector<std::string> result; boost::split(result, text, boost::is_any_of(delimiter)); return result; diff --git a/Device/IO/IOFactory.cpp b/Device/IO/IOFactory.cpp index 4fa9e74d0d5..28e431bce11 100644 --- a/Device/IO/IOFactory.cpp +++ b/Device/IO/IOFactory.cpp @@ -19,6 +19,7 @@ #include "Device/Data/Datafield.h" #include "Device/Histo/DiffUtil.h" #include "Device/Histo/SimulationResult.h" +#include "Device/IO/ImportSettings.h" #include "Device/IO/ParseUtil.h" #include "Device/IO/ReadReflectometry.h" #include "Device/IO/ReadWriteINT.h" @@ -180,17 +181,31 @@ Datafield* IO::readData1D(const std::string& file_name, Filetype1D ftype, std::stringstream s = ::file2stream(file_name); + if (ftype == csv1D) { + if (!importSettings) + throw std::runtime_error("No import settings given for 'other legacy' data"); + return Util::RW::readReflectometryTable(s, *importSettings); + } + + if (importSettings) + throw std::runtime_error("Import settings given in spite of fully specified data format"); + if (ftype == mft) return Util::RW::readMotofit(s); if (ftype == bornagain1D) return Util::RW::readBAInt(s); - ASSERT(ftype == csv1D); - if (!importSettings) - throw std::runtime_error("No import settings given for csv data"); + if (ftype == csv1D_2cols) + return Util::RW::readReflectometryTable(s, legacy1D_2cols); + if (ftype == csv1D_3cols) + return Util::RW::readReflectometryTable(s, legacy1D_3cols); + if (ftype == csv1D_4cols) + return Util::RW::readReflectometryTable(s, legacy1D_4cols); + if (ftype == csv1D_5cols) + return Util::RW::readReflectometryTable(s, legacy1D_5cols); - return Util::RW::readReflectometryTable(s, *importSettings); + ASSERT(false); } Datafield* IO::readData2D(const std::string& file_name, Filetype2D ftype) diff --git a/Device/IO/IOFactory.h b/Device/IO/IOFactory.h index 769ef630491..7bd1f478921 100644 --- a/Device/IO/IOFactory.h +++ b/Device/IO/IOFactory.h @@ -22,7 +22,7 @@ struct ImportSettings1D; namespace IO { -enum Filetype1D { unknown1D, csv1D, bornagain1D, mft }; +enum Filetype1D { unknown1D, csv1D, csv1D_2cols, csv1D_3cols, csv1D_4cols, csv1D_5cols, bornagain1D, mft }; enum Filetype2D { unknown2D, csv2D, bornagain2D, tiff, nicos2D }; #ifndef SWIG diff --git a/Device/IO/ImportSettings.cpp b/Device/IO/ImportSettings.cpp index fa683ca0671..2d04b63e79a 100644 --- a/Device/IO/ImportSettings.cpp +++ b/Device/IO/ImportSettings.cpp @@ -14,19 +14,7 @@ #include "Device/IO/ImportSettings.h" -struct ImportSettings1D { - std::string headerPrefix; //!< prefix of header lines (usually a single character like "#") - std::string linesToSkip; //!< pattern denoting line to skip (i.e. '1,10-12,42') - std::string separator; //!< column separator - size_t col_Q; //!< column number of Q (counting from 1!) - size_t col_R; //!< column number of R - size_t col_sR; //!< column number of sigma R, or 0 - size_t col_dQ; //!< column number of delta Q, or 0 - size_t col_lambda; //!< column number of wavelength, or 0 - - // bool operator!=(const ImportSettings& other) const; - // QByteArray serialize() const; - // void deserialize(const QByteArray& data); -}; - +const ImportSettings1D legacy1D_2cols { "#", "", "SPACE", 1, 2, 0, 0, 0 }; +const ImportSettings1D legacy1D_3cols { "#", "", "SPACE", 1, 2, 3, 0, 0 }; const ImportSettings1D legacy1D_4cols { "#", "", "SPACE", 1, 2, 3, 4, 0 }; +const ImportSettings1D legacy1D_5cols { "#", "", "SPACE", 1, 2, 3, 4, 5 }; diff --git a/Device/IO/ImportSettings.h b/Device/IO/ImportSettings.h index 4a5187aa8fc..33ae5a14c76 100644 --- a/Device/IO/ImportSettings.h +++ b/Device/IO/ImportSettings.h @@ -15,6 +15,8 @@ #ifndef BORNAGAIN_DEVICE_IO_IMPORTSETTINGS_H #define BORNAGAIN_DEVICE_IO_IMPORTSETTINGS_H +#include <string> + //! This parameterization can be set interactively by GUI users. //! Therefore, exceptionally, indices are counting from 1, not from 0. @@ -24,8 +26,8 @@ struct ImportSettings1D { std::string separator; //!< column separator size_t col_Q; //!< column number of Q (counting from 1!) size_t col_R; //!< column number of R - size_t col_dQ; //!< column number of delta Q, or 0 size_t col_sR; //!< column number of sigma R, or 0 + size_t col_dQ; //!< column number of delta Q, or 0 size_t col_lambda; //!< column number of wavelength, or 0 // bool operator!=(const ImportSettings& other) const; @@ -33,6 +35,9 @@ struct ImportSettings1D { // void deserialize(const QByteArray& data); }; +extern const ImportSettings1D legacy1D_2cols; +extern const ImportSettings1D legacy1D_3cols; extern const ImportSettings1D legacy1D_4cols; +extern const ImportSettings1D legacy1D_5cols; #endif // BORNAGAIN_DEVICE_IO_IMPORTSETTINGS_H diff --git a/Device/IO/ReadReflectometry.cpp b/Device/IO/ReadReflectometry.cpp index d07a3ed0674..2ccb4c4a8a4 100644 --- a/Device/IO/ReadReflectometry.cpp +++ b/Device/IO/ReadReflectometry.cpp @@ -57,7 +57,7 @@ Datafield* Util::RW::readReflectometryTable(std::istream& s, const ImportSetting sRVec.push_back(rowVec[p.col_sR - 1]); } - return new Datafield(std::vector<const Scale*>{newListScan("qVector", QVec)}, QVec, sRVec); + return new Datafield(std::vector<const Scale*>{newListScan("qVector", QVec)}, RVec, sRVec); } Datafield* Util::RW::readMotofit(std::istream& s) diff --git a/GUI/View/Import/RealDataSelectorWidget.cpp b/GUI/View/Import/RealDataSelectorWidget.cpp index 001d8b68163..d04c4bea68f 100644 --- a/GUI/View/Import/RealDataSelectorWidget.cpp +++ b/GUI/View/Import/RealDataSelectorWidget.cpp @@ -251,8 +251,12 @@ void RealDataSelectorWidget::importData1D() static const std::map<const QString, IO::Filetype1D> filters1D{ {"Motofit (*.mft)", IO::mft}, {"BornAgain (*.int.gz)", IO::bornagain1D}, - {"CSV (*.txt *.csv *.dat)", IO::csv1D}, - {"All (*.*)", IO::unknown1D}}; + {"legacy 2 columns: Q R (*.csv *.dat *.tab *.txt)", IO::csv1D_2cols}, + {"legacy 3 columns: Q R σR (*.csv *.dat *.tab *.txt)", IO::csv1D_3cols}, + {"legacy 4 columns: Q R σR δQ (*.csv *.dat *.tab *.txt)", IO::csv1D_4cols}, + {"legacy 5 columns: Q R σR δQ λ (*.csv *.dat *.tab *.txt)", IO::csv1D_5cols}, + {"any other CSV: interactive configuration (*.csv *.dat *.tab *.txt)", IO::csv1D}, + {"all (*.*)", IO::unknown1D}}; QString filters = ::join_mapkeys(filters1D, ";;"); @@ -301,8 +305,8 @@ void RealDataSelectorWidget::importData2D() {"TIFF (*.tif *.tiff *.tif.gz)", IO::tiff}, {"Nicos/SANSDRaw (*.001)", IO::nicos2D}, {"BornAgain (*.int.gz)", IO::bornagain2D}, - {"CSV (*.txt *.csv *.dat)", IO::csv2D}, - {"All (*.*)", IO::unknown2D}}; + {"CSV (*.csv *.dat *.tab *.txt)", IO::csv2D}, + {"all (*.*)", IO::unknown2D}}; QString filters = ::join_mapkeys(filters2D, ";;"); diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py index 94f49d5408f..78fe2afd11e 100644 --- a/auto/Wrap/libBornAgainDevice.py +++ b/auto/Wrap/libBornAgainDevice.py @@ -2993,6 +2993,14 @@ unknown1D = _libBornAgainDevice.unknown1D csv1D = _libBornAgainDevice.csv1D +csv1D_2cols = _libBornAgainDevice.csv1D_2cols + +csv1D_3cols = _libBornAgainDevice.csv1D_3cols + +csv1D_4cols = _libBornAgainDevice.csv1D_4cols + +csv1D_5cols = _libBornAgainDevice.csv1D_5cols + bornagain1D = _libBornAgainDevice.bornagain1D mft = _libBornAgainDevice.mft diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp index 36b280ca0b2..2841de33cc3 100644 --- a/auto/Wrap/libBornAgainDevice_wrap.cpp +++ b/auto/Wrap/libBornAgainDevice_wrap.cpp @@ -39337,6 +39337,10 @@ SWIG_init(void) { SWIG_Python_SetConstant(d, "RectangularDetector_PERPENDICULAR_TO_REFLECTED_BEAM",SWIG_From_int(static_cast< int >(RectangularDetector::PERPENDICULAR_TO_REFLECTED_BEAM))); SWIG_Python_SetConstant(d, "unknown1D",SWIG_From_int(static_cast< int >(IO::unknown1D))); SWIG_Python_SetConstant(d, "csv1D",SWIG_From_int(static_cast< int >(IO::csv1D))); + SWIG_Python_SetConstant(d, "csv1D_2cols",SWIG_From_int(static_cast< int >(IO::csv1D_2cols))); + SWIG_Python_SetConstant(d, "csv1D_3cols",SWIG_From_int(static_cast< int >(IO::csv1D_3cols))); + SWIG_Python_SetConstant(d, "csv1D_4cols",SWIG_From_int(static_cast< int >(IO::csv1D_4cols))); + SWIG_Python_SetConstant(d, "csv1D_5cols",SWIG_From_int(static_cast< int >(IO::csv1D_5cols))); SWIG_Python_SetConstant(d, "bornagain1D",SWIG_From_int(static_cast< int >(IO::bornagain1D))); SWIG_Python_SetConstant(d, "mft",SWIG_From_int(static_cast< int >(IO::mft))); SWIG_Python_SetConstant(d, "unknown2D",SWIG_From_int(static_cast< int >(IO::unknown2D))); -- GitLab