From ae7aac3929dd1c201f086f2e4bc5c933a317cf45 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 10 May 2023 17:22:40 +0200
Subject: [PATCH] read|writeNumpyTxt in ns IO

---
 Device/IO/IOFactory.cpp                  |  6 ++----
 Device/IO/ReadWriteNumpyTXT.cpp          | 25 +++++++++---------------
 Device/IO/ReadWriteNumpyTXT.h            | 16 +++++++--------
 Tests/Unit/Device/IOReaderWriterTest.cpp |  6 ++----
 4 files changed, 21 insertions(+), 32 deletions(-)

diff --git a/Device/IO/IOFactory.cpp b/Device/IO/IOFactory.cpp
index ca0c08528e5..baae6e36a28 100644
--- a/Device/IO/IOFactory.cpp
+++ b/Device/IO/IOFactory.cpp
@@ -65,8 +65,7 @@ Datafield* IOFactory::readDatafield(const std::string& file_name, LoaderSelector
         // Try to read ASCII by default. Binary maps to ASCII.
         // If the file is not actually a matrix of numbers,
         // the error will be thrown during the reading.
-        result = functional_read(
-            file_name, [](std::istream& s) { return ReadWriteNumpyTXT().readDatafield(s); });
+        result = functional_read(file_name, [](std::istream& s) { return IO::readNumpyTxt(s); });
 
     ASSERT(result);
     return result;
@@ -89,8 +88,7 @@ void IOFactory::writeDatafield(const Datafield& data, const std::string& file_na
             functional_write(file_name, [&](std::ostream& s) { IO::writeTiff(data, s); });
 #endif
         else
-            functional_write(file_name,
-                             [&](std::ostream& s) { ReadWriteNumpyTXT().writeDatafield(data, s); });
+            functional_write(file_name, [&](std::ostream& s) { IO::writeNumpyTxt(data, s); });
     } catch (const std::exception& ex) {
         throw std::runtime_error("Failed writing to " + file_name + ": " + ex.what());
     }
diff --git a/Device/IO/ReadWriteNumpyTXT.cpp b/Device/IO/ReadWriteNumpyTXT.cpp
index 5dd36fe0361..15dbd006c30 100644
--- a/Device/IO/ReadWriteNumpyTXT.cpp
+++ b/Device/IO/ReadWriteNumpyTXT.cpp
@@ -14,6 +14,7 @@
 
 #include "Device/IO/ReadWriteNumpyTXT.h"
 #include "Base/Axis/Scale.h"
+#include "Base/Util/Assert.h"
 #include "Base/Util/StringUtil.h"
 #include "Device/Data/ArrayUtil.h"
 #include "Device/Data/Datafield.h"
@@ -69,7 +70,7 @@ void write2DRepresentation(const Datafield& data, std::ostream& output_stream)
 
 } // namespace
 
-Datafield* ReadWriteNumpyTXT::readDatafield(std::istream& input_stream)
+Datafield* IO::readNumpyTxt(std::istream& input_stream)
 {
     std::string line;
     std::vector<std::vector<double>> data;
@@ -79,13 +80,8 @@ Datafield* ReadWriteNumpyTXT::readDatafield(std::istream& input_stream)
         line = BaseUtil::String::trim(line);
         if (line.empty() || !isDoubleStartChar(line[0]))
             continue;
-
-        try {
-            std::vector<double> dataInRow = DataUtil::Format::parse_doubles(line);
-            data.push_back(dataInRow);
-        } catch (...) {
-            continue;
-        }
+        std::vector<double> dataInRow = DataUtil::Format::parse_doubles(line);
+        data.push_back(dataInRow);
     }
 
     // validating
@@ -95,14 +91,12 @@ Datafield* ReadWriteNumpyTXT::readDatafield(std::istream& input_stream)
         ncols = data[0].size();
 
     if (ncols == 0)
-        throw std::runtime_error("ReadNumpyTXTStrategy::readDatafield -> Error. "
-                                 "Cannot parse file");
+        throw std::runtime_error("Numpy txt file has invalid content");
 
-    for (size_t row = 0; row < nrows; row++) {
+    for (size_t row = 0; row < nrows; row++)
         if (data[row].size() != ncols)
-            throw std::runtime_error("ReadNumpyTXTStrategy::readDatafield -> Error. "
+            throw std::runtime_error("Error in Numpy txt file: "
                                      "Number of elements is different from row to row.");
-    }
 
     if (nrows < 2)
         return DataUtil::Array::createPField1D(data[0]).release();
@@ -118,7 +112,7 @@ Datafield* ReadWriteNumpyTXT::readDatafield(std::istream& input_stream)
     return DataUtil::Array::createPField2D(data).release();
 }
 
-void ReadWriteNumpyTXT::writeDatafield(const Datafield& data, std::ostream& output_stream)
+void IO::writeNumpyTxt(const Datafield& data, std::ostream& output_stream)
 {
     output_stream << "# BornAgain Intensity Data" << std::endl;
     output_stream << "# Simple array suitable for numpy, matlab etc." << std::endl;
@@ -132,7 +126,6 @@ void ReadWriteNumpyTXT::writeDatafield(const Datafield& data, std::ostream& outp
         write2DRepresentation(data, output_stream);
         break;
     default:
-        throw std::runtime_error("Error in DatafieldWriteNumpyTXTStrategy::writeDatafield: data "
-                                 "of unsupported dimensions");
+        ASSERT(false);
     }
 }
diff --git a/Device/IO/ReadWriteNumpyTXT.h b/Device/IO/ReadWriteNumpyTXT.h
index 6492610f0b8..f56b3f96b45 100644
--- a/Device/IO/ReadWriteNumpyTXT.h
+++ b/Device/IO/ReadWriteNumpyTXT.h
@@ -3,7 +3,7 @@
 //  BornAgain: simulate and fit reflection and scattering
 //
 //! @file      Device/IO/ReadWriteNumpyTXT.h
-//! @brief     Defines ReadWriteNumpyTXT
+//! @brief     Declares functions read|writeNumpyTxt
 //!
 //! @homepage  http://www.bornagainproject.org
 //! @license   GNU General Public License v3 or higher (see COPYING)
@@ -22,13 +22,13 @@
 
 class Datafield;
 
-//! Class for reading and writing Datafield from simple ASCII file with the layout as in
-//! numpy.savetxt.
+namespace IO {
 
-class ReadWriteNumpyTXT {
-public:
-    static Datafield* readDatafield(std::istream& input_stream);
-    static void writeDatafield(const Datafield& data, std::ostream& output_stream);
-};
+//! Reads Datafield from simple ASCII file with layout as in numpy.savetxt.
+Datafield* readNumpyTxt(std::istream& input_stream);
+//! Writes Datafield to simple ASCII file with layout as in numpy.savetxt.
+void writeNumpyTxt(const Datafield& data, std::ostream& output_stream);
+
+}; // namespace IO
 
 #endif // BORNAGAIN_DEVICE_IO_READWRITENUMPYTXT_H
diff --git a/Tests/Unit/Device/IOReaderWriterTest.cpp b/Tests/Unit/Device/IOReaderWriterTest.cpp
index 60d69021671..5ec6931efea 100644
--- a/Tests/Unit/Device/IOReaderWriterTest.cpp
+++ b/Tests/Unit/Device/IOReaderWriterTest.cpp
@@ -42,11 +42,9 @@ TEST_F(IOReaderWriterTest, TestRWINT)
 TEST_F(IOReaderWriterTest, TestRWNumpyTXT)
 {
     std::stringstream ss;
-    ReadWriteNumpyTXT write_txt;
-    write_txt.writeDatafield(m_model_data, ss);
+    IO::writeNumpyTxt(m_model_data, ss);
 
-    ReadWriteNumpyTXT read_txt;
-    auto result = std::unique_ptr<Datafield>(read_txt.readDatafield(ss));
+    auto result = std::unique_ptr<Datafield>(IO::readNumpyTxt(ss));
     EXPECT_EQ(m_model_data.rank(), result->rank());
     for (size_t i = 0, size = m_model_data.size(); i < size; ++i)
         EXPECT_EQ(m_model_data[i], (*result)[i]);
-- 
GitLab