24#include <boost/scoped_array.hpp>
26#include <nexus/NeXusFile.hpp>
33using namespace Kernel;
50 auto wsValidator = std::make_shared<CompositeValidator>();
51 wsValidator->add(std::make_shared<API::WorkspaceUnitValidator>(
"DeltaE"));
57 "The name of the workspace to save.");
60 std::make_unique<API::FileProperty>(
"Filename",
"",
FileProperty::Save, std::vector<std::string>(1,
".nxspe")),
61 "The name of the NXSPE file to write, as a full or relative path");
65 declareProperty(
"KiOverKfScaling",
true,
"Flags in the file whether Ki/Kf scaling has been done or not.");
68 std::vector<std::string> fileExts{
".par",
".phx"};
71 "If provided, will replace detectors parameters in resulting nxspe file with the values taken from the file. \n\
72 Should be used only if the parameters, calculated by the [[FindDetectorsPar]] algorithm are not suitable for some reason. \n\
73 See [[FindDetectorsPar]] description for the details.");
84 const auto nHist =
static_cast<int64_t
>(inputWS->getNumberHistograms());
86 const auto nBins =
static_cast<int64_t
>(inputWS->blocksize());
92 ::NeXus::File nxFile(filename, NXACC_CREATE5);
96 if (entryName.empty()) {
97 entryName =
"mantid_workspace";
99 nxFile.makeGroup(entryName,
"NXentry",
true);
102 nxFile.writeData(
"definition",
"NXSPE");
103 nxFile.openData(
"definition");
108 nxFile.writeData(
"program_name",
"mantid");
109 nxFile.openData(
"program_name");
114 nxFile.makeGroup(
"NXSPE_info",
"NXcollection",
true);
122 const API::Run &run = inputWS->run();
126 nxFile.writeData(
"fixed_energy",
efixed);
127 nxFile.openData(
"fixed_energy");
128 nxFile.putAttr(
"units",
"meV");
134 nxFile.writeData(
"psi", psi);
135 nxFile.openData(
"psi");
136 nxFile.putAttr(
"units",
"degrees");
141 nxFile.writeData(
"ki_over_kf_scaling", 1);
143 nxFile.writeData(
"ki_over_kf_scaling", 0);
149 nxFile.makeGroup(
"instrument",
"NXinstrument",
true);
151 nxFile.writeData(
"name", inputWS->getInstrument()->getName());
153 nxFile.openData(
"name");
155 nxFile.putAttr(
"short_name", inputWS->getInstrument()->getName());
159 nxFile.makeGroup(
"fermi",
"NXfermi_chopper",
true);
161 nxFile.writeData(
"energy",
efixed);
167 nxFile.makeGroup(
"sample",
"NXsample",
true);
176 nxFile.makeGroup(
"data",
"NXdata",
true);
181 const auto &
X = inputWS->x(0);
182 nxFile.writeData(
"energy",
X.rawData());
183 nxFile.openData(
"energy");
184 nxFile.putAttr(
"units",
"meV");
188 using Dimensions = std::vector<int64_t>;
189 Dimensions arrayDims(2);
190 arrayDims[0] = nHist;
191 arrayDims[1] = nBins;
192 nxFile.makeData(
"data", ::NeXus::FLOAT64, arrayDims,
false);
193 nxFile.makeData(
"error", ::NeXus::FLOAT64, arrayDims,
false);
196 nxFile.openData(
"data");
197 nxFile.putAttr(
"signal", 1);
198 nxFile.putAttr(
"axes",
"polar:energy");
204 Dimensions slabStart(2, 0), slabSize(2, 0);
205 auto chunkRows =
static_cast<Dimensions::value_type
>(
MAX_CHUNK_SIZE / 8 / nBins);
206 if (nHist < chunkRows) {
210 slabSize[0] = chunkRows;
214 using Buffer = boost::scoped_array<double>;
215 const size_t bufferSize(slabSize[0] * slabSize[1]);
216 Buffer signalBuffer(
new double[bufferSize]);
217 Buffer errorBuffer(
new double[bufferSize]);
221 int64_t bufferCounter(0);
222 const auto &spectrumInfo = inputWS->spectrumInfo();
223 for (int64_t i = 0; i < nHist; ++i) {
226 double *signalBufferStart = signalBuffer.get() + bufferCounter * nBins;
227 double *errorBufferStart = errorBuffer.get() + bufferCounter * nBins;
228 if (spectrumInfo.hasDetectors(i) && !spectrumInfo.isMonitor(i)) {
230 if (!spectrumInfo.isMasked(i)) {
231 std::copy(inputWS->y(i).cbegin(), inputWS->y(i).cend(), signalBufferStart);
232 std::copy(inputWS->e(i).cbegin(), inputWS->e(i).cend(), errorBufferStart);
234 std::fill_n(signalBufferStart, nBins,
MASK_FLAG);
235 std::fill_n(errorBufferStart, nBins,
MASK_ERROR);
239 std::fill_n(signalBufferStart, nBins, 0.0);
240 std::fill_n(errorBufferStart, nBins, 0.0);
247 if (bufferCounter == chunkRows || i == nHist - 1) {
250 slabSize[0] = bufferCounter;
251 nxFile.openData(
"data");
252 nxFile.putSlab(signalBuffer.get(), slabStart, slabSize);
256 nxFile.openData(
"error");
257 nxFile.putSlab(errorBuffer.get(), slabStart, slabSize);
261 slabStart[0] += bufferCounter;
269 spCalcDetPar->initialize();
270 spCalcDetPar->setProperty(
"InputWorkspace", inputWS);
272 if (!(parFileName.empty() || parFileName ==
"not_used.par")) {
273 spCalcDetPar->setPropertyValue(
"ParFile", parFileName);
275 spCalcDetPar->execute();
280 throw(std::bad_cast());
282 const std::vector<double> &azimuthal = pCalcDetPar->
getAzimuthal();
283 const std::vector<double> &polar = pCalcDetPar->getPolar();
284 const std::vector<double> &azimuthal_width = pCalcDetPar->getAzimWidth();
285 const std::vector<double> &polar_width = pCalcDetPar->getPolarWidth();
286 const std::vector<double> &secondary_flightpath = pCalcDetPar->getFlightPath();
289 nxFile.writeData(
"polar", polar);
292 nxFile.writeData(
"azimuthal", azimuthal);
295 nxFile.writeData(
"polar_width", polar_width);
296 nxFile.writeData(
"azimuthal_width", azimuthal_width);
299 nxFile.writeData(
"distance", secondary_flightpath);
#define DECLARE_ALGORITHM(classname)
Base class from which all concrete algorithm classes should be derived.
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
static bool isEmpty(const NumT toCheck)
checks that the value was not set by users, uses the value in empty double/int.
A validator which provides a TENTATIVE check that a workspace contains common bins in each spectrum.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
@ Save
to specify a file to write to, the file may or may not exist
A validator which checks that a workspace contains histogram data (the default) or point data as requ...
bool hasProperty(const std::string &name) const
Does the property exist on the object.
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
Helper class for reporting progress from algorithms.
This class stores information regarding an experimental run as a series of log entries.
A property class for workspaces.
std::vector< double > const & getAzimuthal() const
the accessors, used to return algorithm results when called as Child Algorithm, without setting the p...
static const size_t MAX_CHUNK_SIZE
The size in bytes of a chunk to accumulate to write to the file at once.
void init() override
Initialisation code.
static const std::string NXSPE_VER
file format version
void exec() override
Execution code.
static const double MASK_FLAG
Value for data if pixel is masked.
static const double MASK_ERROR
Value for error if pixel is masked.
static const char * version()
The full version number.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
@ Input
An input workspace.