diff --git a/Framework/DataHandling/CMakeLists.txt b/Framework/DataHandling/CMakeLists.txt index 0371fc1ba0dbc27720273eaae80e552a2555f77e..15810963635c4e923a63dbbfcd47144927d55872 100644 --- a/Framework/DataHandling/CMakeLists.txt +++ b/Framework/DataHandling/CMakeLists.txt @@ -183,6 +183,7 @@ set(SRC_FILES src/SaveReflCustomAscii.cpp src/SaveReflThreeColumnAscii.cpp src/SaveReflectometryAscii.cpp + src/SaveRMCProfile.cpp src/SaveSESANS.cpp src/SaveSPE.cpp src/SaveSampleEnvironmentAndShape.cpp @@ -382,6 +383,7 @@ set(INC_FILES inc/MantidDataHandling/SaveReflCustomAscii.h inc/MantidDataHandling/SaveReflThreeColumnAscii.h inc/MantidDataHandling/SaveReflectometryAscii.h + inc/MantidDataHandling/SaveRMCProfile.h inc/MantidDataHandling/SaveSESANS.h inc/MantidDataHandling/SaveSPE.h inc/MantidDataHandling/SaveSampleEnvironmentAndShape.h @@ -567,6 +569,7 @@ set(TEST_FILES SaveReflCustomAsciiTest.h SaveReflThreeColumnAsciiTest.h SaveReflectometryAsciiTest.h + SaveRMCProfileTest.h SaveSESANSTest.h SaveSPETest.h SaveSampleEnvironmentAndShapeTest.h diff --git a/Framework/DataHandling/inc/MantidDataHandling/SaveRMCProfile.h b/Framework/DataHandling/inc/MantidDataHandling/SaveRMCProfile.h new file mode 100644 index 0000000000000000000000000000000000000000..32c887b768df7e379255a8a14dc5bd99f5b4b0a0 --- /dev/null +++ b/Framework/DataHandling/inc/MantidDataHandling/SaveRMCProfile.h @@ -0,0 +1,48 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2020 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#ifndef MANTID_DATAHANDLING_SAVERMCPROFILE_H_ +#define MANTID_DATAHANDLING_SAVERMCPROFILE_H_ + +#include "MantidAPI/Algorithm.h" +#include "MantidKernel/System.h" + +namespace Mantid { +namespace DataHandling { + +/** SaveRMCProfile : Saves a workspace containing a spectral density in +a format readable by the RMCProfile package. + +Required Properties: +<UL> +<LI> InputWorkspace - An input workspace with units of Q </LI> +<LI> Filename - The filename to use for the saved data </LI> +</UL> + */ +class DLLExport SaveRMCProfile : public API::Algorithm { +public: + const std::string name() const override; + int version() const override; + const std::vector<std::string> seeAlso() const override { + return {"SaveRMCProfile"}; + } + const std::string category() const override; + const std::string summary() const override; + std::map<std::string, std::string> validateInputs() override; + +private: + void init() override; + void exec() override; + void writeMetaData(std::ofstream &out, + API::MatrixWorkspace_const_sptr inputWS); + void writeWSData(std::ofstream &out, + API::MatrixWorkspace_const_sptr inputWS); +}; + +} // namespace DataHandling +} // namespace Mantid + +#endif /* MANTID_DATAHANDLING_SAVERMCPROFILE_H_ */ diff --git a/Framework/DataHandling/src/SaveRMCProfile.cpp b/Framework/DataHandling/src/SaveRMCProfile.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ee9c5d5d22d991fe85dec6313028ed8b885769fe --- /dev/null +++ b/Framework/DataHandling/src/SaveRMCProfile.cpp @@ -0,0 +1,120 @@ +// Mantid Repository : https://github.com/mantidproject/mantid +// +// Copyright © 2020 ISIS Rutherford Appleton Laboratory UKRI, +// NScD Oak Ridge National Laboratory, European Spallation Source +// & Institut Laue - Langevin +// SPDX - License - Identifier: GPL - 3.0 + +#include "MantidDataHandling/SaveRMCProfile.h" + +#include "MantidAPI/Axis.h" +#include "MantidAPI/FileProperty.h" +#include "MantidAPI/MatrixWorkspace.h" +#include "MantidAPI/Run.h" +#include "MantidKernel/MantidVersion.h" +#include "MantidKernel/Unit.h" + +#include <fstream> + +namespace Mantid { +namespace DataHandling { + +using Mantid::API::WorkspaceProperty; +using Mantid::Kernel::Direction; + +// Register the algorithm into the AlgorithmFactory +DECLARE_ALGORITHM(SaveRMCProfile) + +/// Algorithm's name for identification. @see Algorithm::name +const std::string SaveRMCProfile::name() const { return "SaveRMCProfile"; } + +/// Algorithm's version for identification. @see Algorithm::version +int SaveRMCProfile::version() const { return 1; } + +/// Algorithm's category for identification. @see Algorithm::category +const std::string SaveRMCProfile::category() const { return "DataHandling\\Text"; } + +/// Algorithm's summary for use in the GUI and help. @see Algorithm::summary +const std::string SaveRMCProfile::summary() const { + return "Save files readable by RMCProfile"; +} + +/** Initialize the algorithm's properties. + */ +void SaveRMCProfile::init() { + declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", + Direction::Input), + "An input workspace with units of Q."); + declareProperty(std::make_unique<API::FileProperty>( + "Filename", "", API::FileProperty::Save, ".gr"), + "The filename to use for the saved data"); +} + +/// @copydoc Algorithm::validateInputs +std::map<std::string, std::string> SaveRMCProfile::validateInputs() { + std::map<std::string, std::string> result; + + // check for null pointers - this is to protect against workspace groups + API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); + if (!inputWS) { + return result; + } + + const auto nHist = static_cast<int>(inputWS->getNumberHistograms()); + if (nHist != 1) { + result["InputWorkspace"] = "Workspace must contain only one spectrum"; + } else if (std::string(inputWS->getAxis(0)->unit()->label()) != "Angstrom^-1") { + result["InputWorkspace"] = "Expected x-units of Angstrom^-1"; + } + + return result; +} + +/** Execute the algorithm. + */ +void SaveRMCProfile::exec() { + API::MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace"); + const std::string filename = getProperty("Filename"); + + // --------- open the file + std::ofstream out; + out.open(filename.c_str(), std::ios_base::out); + + // --------- write the header in the style of required metadata + writeMetaData(out, inputWS); + + // --------- write the data + writeWSData(out, inputWS); + + // --------- close the file + out.close(); +} + +void SaveRMCProfile::writeMetaData(std::ofstream& out, + API::MatrixWorkspace_const_sptr inputWS) { + out << "#example comment"; +} + +void SaveRMCProfile::writeWSData(std::ofstream& out, + API::MatrixWorkspace_const_sptr inputWS) { + const auto &x = inputWS->x(0); + const auto &y = inputWS->y(0); + const auto &dy = inputWS->e(0); + HistogramData::HistogramDx dx(y.size(), 0.0); + if (inputWS->sharedDx(0)) + dx = inputWS->dx(0); + const size_t length = x.size(); + if (x.size() == y.size()) { + for (size_t i = 0; i < length; ++i) { + out << " " << x[i] << " " << y[i] << " " << dx[i] << " " << dy[i] + << "\n"; + } + } else { + for (size_t i = 0; i < length - 1; ++i) { + out << " " << (x[i] + x[i + 1]) / 2.0 << " " << y[i] << " " << dx[i] + << " " << dy[i] << "\n"; + } + } +} + +} // namespace DataHandling +} // namespace Mantid diff --git a/docs/source/algorithms/SaveRCMProfile-v1.rst b/docs/source/algorithms/SaveRCMProfile-v1.rst new file mode 100644 index 0000000000000000000000000000000000000000..aa97aa61a6a3a66c488da5966058ba51f243ab19 --- /dev/null +++ b/docs/source/algorithms/SaveRCMProfile-v1.rst @@ -0,0 +1,59 @@ + +.. algorithm:: + +.. summary:: + +.. relatedalgorithms:: + +.. properties:: + +Description +----------- + +This algorithm saves S(Q)-1 files consistent with `RMCProfile <http://www.rmcprofile.org/Main_Page>`_. +The body of the file is of the form ``Q SQ-1 dQ dSQ``. + +Usage +----- +.. Try not to use files in your examples, + but if you cannot avoid it then the (small) files must be added to + autotestdata\UsageData and the following tag unindented + .. include:: ../usagedata-note.txt + +**Example - SaveRMCProfile** + +.. testcode:: SaveRMCProfileExample + + # Create a host workspace + ws = CreateWorkspace(DataX=range(0,3), DataY=range(0,3), UnitX="Angstrom^-1") + + # Create a filename + import os + path = os.path.join(os.path.expanduser("~"), "savermcprofile.gr") + + # Save as S(Q)-1 file + SavePDFGui(ws, path) + + # Check that the file exists + print(os.path.isfile(path)) + +Output: + +.. testoutput:: SaveRMCProfileExample + + True + +.. testcleanup:: SaveRMCProfileExample + + DeleteWorkspace(ws) + import os + try: + path = os.path.join(os.path.expanduser("~"), "savermcprofile.gr") + os.remove(path) + except: + pass + +.. categories:: + +.. sourcelink:: +