Mantid
Loading...
Searching...
No Matches
SaveFocusedXYE.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8#include "MantidAPI/Axis.h"
15#include "MantidKernel/Unit.h"
16#include <Poco/File.h>
17#include <Poco/Path.h>
18#include <cmath>
19#include <exception>
20#include <fstream>
21
22using namespace Mantid::DataHandling;
23
24// Register the algorithm into the AlgorithmFactory
26
27
30void SaveFocusedXYE::init() {
31 declareProperty(std::make_unique<API::WorkspaceProperty<>>("InputWorkspace", "", Kernel::Direction::Input),
32 "The name of the workspace containing the data you wish to save");
33 declareProperty(std::make_unique<API::FileProperty>("Filename", "", API::FileProperty::Save),
34 "The filename to use when saving data");
35 declareProperty("SplitFiles", true, "Save each spectrum in a different file (default true)");
36 declareProperty("StartAtBankNumber", 0,
37 "Start bank (spectrum) numbers at this number in the file. "
38 "The bank number in the file will be the workspace index + "
39 "StartAtBankNumber.");
40 declareProperty("Append", false, "If true and Filename already exists, append, else overwrite");
41 declareProperty("IncludeHeader", true, "Whether to include the header lines (default: true)");
42 std::vector<std::string> header(3);
43 header[0] = "XYE";
44 header[1] = "MAUD";
45 header[2] = "TOPAS";
46 declareProperty("Format", "XYE", std::make_shared<Kernel::StringListValidator>(header),
47 "A type of the header: XYE (default) or MAUD.");
48}
49
54 using namespace Mantid::API;
55 // Retrieve the input workspace
56 MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
57 const size_t nHist = inputWS->getNumberHistograms();
58 const bool isHistogram = inputWS->isHistogramData();
59
60 // this would be a subroutine if it were easier to return
61 // two strings
62 std::string filename = getProperty("Filename");
63 std::string ext;
64 {
65 Poco::Path path(filename);
66 std::string directory = path.parent().toString();
67 std::string name = path.getFileName();
68
69 std::size_t pos = name.find_first_of('.');
70 if (pos != std::string::npos) // Remove the extension
71 {
72 ext = name.substr(pos + 1, name.npos);
73 name = name.substr(0, pos);
74 }
75
76 filename = Poco::Path(directory, name).toString();
77 }
78
79 const bool append = getProperty("Append");
80 const bool headers = getProperty("IncludeHeader");
81
82 const int startingbank = getProperty("StartAtBankNumber");
83 if (startingbank < 0) {
84 g_log.error() << "Starting bank number cannot be less than 0. \n";
85 throw std::invalid_argument("Incorrect starting bank number");
86 }
87 const bool split = getProperty("SplitFiles");
88 std::ostringstream number;
89 std::fstream out;
90 std::ios_base::openmode mode = (append ? (std::ios_base::out | std::ios_base::app) : std::ios_base::out);
91
92 m_comment = "#";
93 const std::string headerType = getProperty("Format");
94 if (headerType == "XYE") {
96 } else if (headerType == "MAUD") {
98 } else if (headerType == "TOPAS") {
100 m_comment = "'";
101 } else {
102 std::stringstream msg;
103 msg << "Unrecognized format \"" << m_headerType << "\"";
104 throw std::runtime_error(msg.str());
105 }
106
107 const auto &detectorInfo = inputWS->detectorInfo();
108
109 if (!split) {
110 const std::string file(std::string(filename).append(".").append(ext));
111 Poco::File fileObj(file);
112 const bool exists = fileObj.exists();
113 out.open(file.c_str(), mode);
114 if (headers && (!exists || !append))
115 writeHeaders(out, inputWS);
116 }
117
118 Progress progress(this, 0.0, 1.0, nHist);
119 for (size_t i = 0; i < nHist; i++) {
120 const auto &X = inputWS->x(i);
121 const auto &Y = inputWS->y(i);
122 const auto &E = inputWS->e(i);
123
124 double l1 = 0;
125 double l2 = 0;
126 double tth = 0;
127 if (headers) {
128 // try to get detector information
129 try {
130 l1 = detectorInfo.l1();
131 l2 = detectorInfo.l2(i);
132 tth = detectorInfo.twoTheta(i) * 180. / M_PI;
133 } catch (std::logic_error &ex) {
134 // DetectorInfo::twoTheta throws for monitors. Ignore and continue with
135 // default value.
136 g_log.warning() << ex.what() << '\n';
137 } catch (std::runtime_error &ex) {
138 g_log.warning() << ex.what() << '\n';
139 }
140 }
141
142 if (split) {
143 // Several files will be created with names filename-i.ext
144 number << "-" << i + startingbank;
145 const std::string file(std::string(filename).append(number.str()).append(".").append(ext));
146 Poco::File fileObj(file);
147 const bool exists = fileObj.exists();
148 out.open(file.c_str(), mode);
149 number.str("");
150 if (headers && (!exists || !append))
151 writeHeaders(out, inputWS);
152 }
153
154 if (!out.is_open()) {
155 g_log.information("Could not open filename: " + filename);
156 throw std::runtime_error("Could not open filename: " + filename);
157 }
158
159 if (headers) {
160 writeSpectraHeader(out, i + startingbank, inputWS->getSpectrum(i).getSpectrumNo(), l1 + l2, tth,
161 inputWS->getAxis(0)->unit()->caption(), inputWS->getAxis(1)->unit()->caption(),
162 inputWS->getAxis(1)->unit()->label(), inputWS->getAxis(1)->getValue(i));
163 }
164 const size_t datasize = Y.size();
165 for (size_t j = 0; j < datasize; j++) {
166 double xvalue(0.0);
167 if (isHistogram) {
168 xvalue = (X[j] + X[j + 1]) / 2.0;
169 } else {
170 xvalue = X[j];
171 }
172 out << std::fixed << std::setprecision(5) << std::setw(15) << xvalue << std::fixed << std::setprecision(8)
173 << std::setw(18) << Y[j] << std::fixed << std::setprecision(8) << std::setw(18) << E[j] << "\n";
174 }
175 // Close at each iteration
176 if (split) {
177 out.close();
178 }
179 progress.report();
180 }
181 // Close if single file
182 if (!split) {
183 out.close();
184 }
185}
186
193void SaveFocusedXYE::setOtherProperties(IAlgorithm *alg, const std::string &propertyName,
194 const std::string &propertyValue, int perioidNum) {
195 if (propertyName == "Append") {
196 if (perioidNum != 1) {
197 alg->setPropertyValue(propertyName, "1");
198 } else
199 alg->setPropertyValue(propertyName, propertyValue);
200 } else
201 Algorithm::setOtherProperties(alg, propertyName, propertyValue, perioidNum);
202}
203
210 if (m_headerType == XYE || m_headerType == TOPAS) {
212 } else // MAUD
213 {
215 }
216}
217
224 if (m_headerType != TOPAS)
225 os << "XYDATA\n";
226 os << m_comment << " File generated by Mantid, "
227 << "Instrument " << workspace->getInstrument()->getName() << '\n';
228 os << m_comment << " The X-axis unit is: " << workspace->getAxis(0)->unit()->caption()
229 << ", The Y-axis unit is: " << workspace->YUnitLabel() << '\n';
230}
231
238 os << "#C " << workspace->getTitle() << '\n';
239 os << "#C " << workspace->getInstrument()->getName() << workspace->getRunNumber() << '\n';
240 os << "#A OMEGA 90.00\n";
241 os << "#A CHI 0.00\n";
242 os << "#A PHI -90.00\n";
243 os << "#A ETA 0.00\n";
244}
245
247void SaveFocusedXYE::writeSpectraHeader(std::ostream &os, size_t index1, size_t index2, double flightPath, double tth,
248 const std::string &caption, const std::string &spectrumAxisCaption,
249 const std::string &spectraAxisLabel, double observable) {
250 if (m_headerType == XYE || m_headerType == TOPAS) {
251 writeXYESpectraHeader(os, index1, caption, spectrumAxisCaption, spectraAxisLabel, observable);
252 } else // MAUD
253 {
254 writeMAUDSpectraHeader(os, index1, index2, flightPath, tth, caption);
255 }
256}
257
259void SaveFocusedXYE::writeXYESpectraHeader(std::ostream &os, size_t index1, const std::string &caption,
260 const std::string &spectrumAxisCaption, const std::string &spectraAxisLabel,
261 double observable) {
262 os << m_comment << " Data for spectra :" << index1 << '\n';
263 if (spectrumAxisCaption == "Temperature") {
264 os << "TEMP " << observable << ' ' << spectraAxisLabel << '\n';
265 } else {
266 os << m_comment << " " << spectrumAxisCaption << " " << observable << ' ' << spectraAxisLabel << '\n';
267 }
268 os << m_comment << " " << caption << " Y E\n";
269}
270
272void SaveFocusedXYE::writeMAUDSpectraHeader(std::ostream &os, size_t index1, size_t index2, double flightPath,
273 double tth, const std::string &caption) {
274 os << "#S" << std::setw(5) << index1 + 1 << " - Group" << std::setw(4) << index2 << '\n';
275 os << "#P0 0 0 " << tth << ' ' << flightPath << '\n';
276 os << "#L " << caption << " Data Error\n";
277}
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
virtual void setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue, int periodNum)
Virtual method to set the non workspace properties for this algorithm.
Definition: Algorithm.cpp:1547
IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:45
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
Saves a focused data set (usually output of a diffraction focusing routine but not exclusively) into ...
void writeMAUDHeaders(std::ostream &os, API::MatrixWorkspace_const_sptr &workspace) const
Write the header information in MAUD format.
void writeXYESpectraHeader(std::ostream &os, size_t index1, const std::string &caption, const std::string &spectrumAxisCaption, const std::string &spectraAxisLabel, double observable)
Write spectra XYE header.
void writeXYEHeaders(std::ostream &os, API::MatrixWorkspace_const_sptr &workspace) const
Write the header information in default "XYE" format.
void exec() override
Execution code.
HeaderType m_headerType
Header type.
void writeMAUDSpectraHeader(std::ostream &os, size_t index1, size_t index2, double flightPath, double tth, const std::string &caption)
Write spectra MAUD header.
std::string m_comment
Comment character.
void setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue, int perioidNum) override
sets non workspace properties for the algorithm
const std::string name() const override
Algorithm's name.
void writeHeaders(std::ostream &os, API::MatrixWorkspace_const_sptr &workspace) const
Write the header information.
void writeSpectraHeader(std::ostream &os, size_t index1, size_t index2, double flightPath, double tth, const std::string &caption, const std::string &spectraAxisCaption, const std::string &spectraAxisLabel, double observable)
Write spectra header.
virtual void setPropertyValue(const std::string &name, const std::string &value)=0
Sets property value from a string.
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
void warning(const std::string &msg)
Logs at warning level.
Definition: Logger.cpp:86
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
bool exists(::NeXus::File &file, const std::string &name)
Based on the current group in the file, does the named sub-entry exist?
void split(const int A, int &S, int &V)
Split a number into the sign and positive value.
Definition: Acomp.cpp:42