30using namespace Kernel;
32using namespace DataObjects;
57bool makeMappings(
const MatrixWorkspace &ws,
const std::vector<int> &ws_indices,
58 std::vector<int32_t> &out_detector_index, std::vector<int32_t> &out_detector_count,
59 std::vector<int32_t> &out_detector_list,
int &numberSpec,
size_t &numberDetectors) {
63 for (
auto index : ws_indices) {
66 if (numberDetectors < 1) {
71 numberSpec = int(ws_indices.size());
74 out_detector_index.resize(numberSpec + 1, 0);
75 out_detector_count.resize(numberSpec, 0);
76 out_detector_list.resize(numberDetectors, 0);
80 for (
int i = 0; i < numberSpec; i++) {
82 const int si = ws_indices[i];
88 const auto ndet1 =
static_cast<int>(detectorgroup.size());
91 out_detector_index[i + 1] = int32_t(out_detector_index[i] + ndet1);
92 out_detector_count[i] = int32_t(ndet1);
94 std::set<detid_t>::const_iterator it;
95 for (it = detectorgroup.begin(); it != detectorgroup.end(); ++it) {
96 out_detector_list[
id++] = int32_t(*it);
100 out_detector_index.resize(numberSpec);
111 "Name of the workspace to be saved");
113 const std::vector<std::string> fileExts{
".nxs",
".nx5",
".xml"};
115 "The name of the Nexus file to write, as a full or relative\n"
119 declareProperty(
"Title",
"", std::make_shared<NullValidator>(),
"A title to describe the saved workspace");
120 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
121 mustBePositive->setLower(0);
124 "Index number of first spectrum to write, only for single\n"
127 "Index of last spectrum to write, only for single period\n"
130 "List of spectrum numbers to read, only for single period\n"
134 "Determines whether .nxs file needs to be\n"
135 "over written or appended");
138 "For EventWorkspaces, preserve the events when saving (default).\n"
139 "If false, will save the 2D histogram version of the workspace with the "
140 "current binning parameters.");
145 "For EventWorkspaces, compress the Nexus data field (default False).\n"
146 "This will make smaller files but takes much longer.");
157 const std::vector<int> spec_list =
getProperty(
"WorkspaceIndexList");
160 const bool list = !spec_list.empty();
164 const auto numberOfHist =
static_cast<int>(matrixWorkspace->getNumberHistograms());
167 if (spec_max < spec_min || spec_max > numberOfHist - 1) {
168 g_log.
error(
"Invalid WorkspaceIndex min/max properties");
169 throw std::invalid_argument(
"Inconsistent properties defined");
171 indices.reserve(1 + spec_max - spec_min);
172 for (
int i = spec_min; i <= spec_max; i++)
173 indices.emplace_back(i);
175 for (
auto s : spec_list) {
178 if (s < spec_min || s > spec_max)
179 indices.emplace_back(s);
184 spec_min = numberOfHist - 1;
185 for (
auto s : spec_list) {
188 indices.emplace_back(s);
196 spec_max = numberOfHist - 1;
197 indices.reserve(1 + spec_max - spec_min);
198 for (
int i = spec_min; i <= spec_max; i++)
199 indices.emplace_back(i);
204 std::shared_ptr<Mantid::NeXus::NexusFileIO> &nexusFile,
const bool keepFile,
207 NXMEnableErrorReporting();
213 const bool PreserveEvents =
getProperty(
"PreserveEvents");
223 if (!matrixWorkspace && !tableWorkspace) {
228 if (
bool(std::dynamic_pointer_cast<const IMDEventWorkspace>(inputWorkspace)) ||
229 bool(std::dynamic_pointer_cast<const IMDHistoWorkspace>(inputWorkspace)))
233 std::stringstream msg;
234 msg <<
"Workspace \"" <<
name <<
"\" not saved because it is not of a type we can presently save.";
236 throw std::runtime_error(msg.str());
238 m_eventWorkspace = std::dynamic_pointer_cast<const EventWorkspace>(matrixWorkspace);
239 const std::string workspaceID = inputWorkspace->id();
240 if ((workspaceID.find(
"Workspace2D") == std::string::npos) &&
241 (workspaceID.find(
"RebinnedOutput") == std::string::npos) &&
242 (workspaceID.find(
"WorkspaceSingleValue") == std::string::npos) && !
m_eventWorkspace && !tableWorkspace &&
243 !offsetsWorkspace && !maskWorkspace)
245 "EventWorkspace, ITableWorkspace, OffsetsWorkspace or MaskWorkspace.");
258 title = inputWorkspace->getTitle();
261 const std::string wsName = inputWorkspace->getName();
266 nexusFile->resetProgress(&prog_init);
267 nexusFile->openNexusWrite(filename, std::move(entryNumber), append_to_file || keepFile);
270 ::NeXus::File cppFile(nexusFile->fileID);
273 if (nexusFile->writeNexusProcessedHeader(title, wsName) != 0)
279 if (matrixWorkspace) {
285 const bool uniformSpectra = matrixWorkspace->isCommonBins();
288 std::vector<int> indices;
294 this->
execEvent(nexusFile.get(), uniformSpectra, indices);
296 std::string workspaceTypeGroupName;
297 if (offsetsWorkspace)
298 workspaceTypeGroupName =
"offsets_workspace";
299 else if (maskWorkspace)
300 workspaceTypeGroupName =
"mask_workspace";
302 workspaceTypeGroupName =
"workspace";
304 nexusFile->writeNexusProcessedData2D(matrixWorkspace, uniformSpectra, indices, workspaceTypeGroupName.c_str(),
309 cppFile.openGroup(
"instrument",
"NXinstrument");
310 cppFile.makeGroup(
"detector",
"NXdetector",
true);
312 cppFile.putAttr(
"version", 1);
315 cppFile.closeGroup();
316 cppFile.closeGroup();
321 if (peaksWorkspace) {
323 peaksWorkspace->saveExperimentInfoNexus(&cppFile);
325 peaksWorkspace->saveNexus(&cppFile);
326 }
else if (tableWorkspace) {
327 nexusFile->writeNexusTableWorkspace(tableWorkspace,
"table_workspace");
332 m_history->fillAlgorithmHistory(
this, Mantid::Types::Core::DateAndTime::getCurrentTime(), 0,
335 inputWorkspace->history().addHistory(
m_history);
343 inputWorkspace->history().saveNexus(&cppFile);
344 nexusFile->closeGroup();
356 auto nexusFile = std::make_shared<Mantid::NeXus::NexusFileIO>();
359 doExec(inputWorkspace, nexusFile);
375 float *errorSquareds, int64_t *pulsetimes) {
380 const auto it = events.cbegin();
381 const auto it_end = events.cend();
385 std::transform(it, it_end, std::next(tofs, offset), [](
const T &event) {
return event.tof(); });
388 std::transform(it, it_end, std::next(weights, offset),
389 [](
const T &event) {
return static_cast<float>(
event.weight()); });
392 std::transform(it, it_end, std::next(errorSquareds, offset),
393 [](
const T &event) {
return static_cast<float>(
event.errorSquared()); });
396 std::transform(it, it_end, std::next(pulsetimes, offset),
397 [](
const T &event) {
return event.pulseTime().totalNanoseconds(); });
406 const std::vector<int> &spec) {
413 std::vector<int64_t> indices;
417 for (
int wi = 0; wi < static_cast<int>(
m_eventWorkspace->getNumberHistograms()); wi++) {
418 indices.emplace_back(
index);
422 indices.emplace_back(
index);
426 double *tofs =
nullptr;
427 float *weights =
nullptr;
428 float *errorSquareds =
nullptr;
429 int64_t *pulsetimes =
nullptr;
433 bool writeTOF =
true;
434 bool writePulsetime =
false;
435 bool writeWeight =
false;
436 bool writeError =
false;
440 writePulsetime =
true;
443 writePulsetime =
true;
455 tofs =
new double[num];
457 weights =
new float[num];
459 errorSquareds =
new float[num];
461 pulsetimes =
new int64_t[num];
465 for (
int wi = 0; wi < static_cast<int>(
m_eventWorkspace->getNumberHistograms()); wi++) {
471 size_t offset = indices[wi];
473 switch (el.getEventType()) {
478 appendEventListData(el.getWeightedEvents(), offset, tofs, weights, errorSquareds, pulsetimes);
481 appendEventListData(el.getWeightedEventsNoTime(), offset, tofs, weights, errorSquareds, pulsetimes);
484 m_progress->reportIncrement(el.getNumberEvents(),
"Copying EventList");
500 delete[] errorSquareds;
512 const std::string &propertyValue,
int perioidNum) {
513 if (propertyName ==
"Append") {
514 if (perioidNum != 1) {
527 auto nexusFile = std::make_shared<Mantid::NeXus::NexusFileIO>();
534 if (!workspaces.empty()) {
535 for (
size_t entry = 0; entry < workspaces.size(); entry++) {
538 throw std::runtime_error(
"NeXus files do not "
539 "support nested groups of groups");
541 this->
doExec(ws, nexusFile, entry > 0 , entry);
546 nexusFile->closeNexusFile();
558 const std::vector<int> &wsIndices,
559 const ::NeXus::NXcompression compression)
const {
561 std::vector<int32_t> detector_index;
562 std::vector<int32_t> detector_count;
563 std::vector<int32_t> detector_list;
565 size_t nDetectors = 0;
567 const bool mappingsToWrite =
568 makeMappings(ws, wsIndices, detector_index, detector_count, detector_list, numberSpec, nDetectors);
569 if (!mappingsToWrite)
573 std::vector<int> dims(1, numberSpec);
574 file->writeCompData(
"detector_index", detector_index, dims, compression, dims);
575 file->writeCompData(
"detector_count", detector_count, dims, compression, dims);
576 dims.front() =
static_cast<int>(nDetectors);
577 file->writeCompData(
"detector_list", detector_list, dims, compression, dims);
580 std::vector<double> detPos(nDetectors * 3);
585 for (
size_t i = 0; i < nDetectors; i++) {
586 double R, Theta, Phi;
591 R = det->getDistance(*sample);
601 detPos[3 * i + 1] = Theta;
602 detPos[3 * i + 2] = Phi;
605 for (
size_t i = 0; i < 3 * nDetectors; i++)
608 dims.front() =
static_cast<int>(nDetectors);
609 dims.emplace_back(3);
610 file->writeCompData(
"detector_positions", detPos, dims, compression, dims);
612 g_log.
error(
"Unknown error caught when saving detector positions.");
623 const std::vector<int> &wsIndices,
624 const ::NeXus::NXcompression compression)
const {
625 const auto numberSpec = int(wsIndices.size());
626 std::vector<int32_t> spectra;
627 spectra.reserve(
static_cast<size_t>(numberSpec));
628 for (
const auto index : wsIndices) {
630 spectra.emplace_back(
static_cast<int32_t
>(spectrum.getSpectrumNo()));
633 const std::vector<int> dims(1, numberSpec);
634 file->writeCompData(
"spectra", spectra, dims, compression, dims);
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_FOR_NO_WSP_CHECK()
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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.
std::shared_ptr< AlgorithmHistory > m_parentHistory
Pointer to the parent history object (if set)
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
std::shared_ptr< AlgorithmHistory > m_history
Pointer to the history for the algorithm being executed.
bool isChild() const override
To query whether algorithm is a child.
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.
bool trackingHistory()
get whether we are tracking the history for this algorithm,
std::vector< WorkspaceVector > m_unrolledInputWorkspaces
One vector of workspaces for each input workspace property.
bool isRecordingHistoryForChild()
static size_t g_execCount
Counter to keep track of algorithm execution order.
Show a property as enabled when the workspace pointed to by another is of a given type.
Geometry::Instrument_const_sptr getInstrument() const
Returns the parameterized instrument.
@ Save
to specify a file to write to, the file may or may not exist
IAlgorithm is the interface implemented by the Algorithm base class.
const std::set< detid_t > & getDetectorIDs() const
Get a const reference to the detector IDs set.
Base MatrixWorkspace Abstract Class.
virtual ISpectrum & getSpectrum(const size_t index)=0
Return the underlying ISpectrum ptr at the given workspace index.
double detectorTwoTheta(const Geometry::IDetector &det) const
Returns the 2Theta scattering angle for a detector.
Helper class for reporting progress from algorithms.
A property class for workspaces.
DataHandling/SaveNexusProcessed.h.
static void appendEventListData(const std::vector< T > &events, size_t offset, double *tofs, float *weights, float *errorSquareds, int64_t *pulsetimes)
Append out each field of a vector of events to separate array.
void execEvent(Mantid::NeXus::NexusFileIO *nexusFile, const bool uniformSpectra, const std::vector< int > &spec)
Execute the saving of event data.
DataObjects::EventWorkspace_const_sptr m_eventWorkspace
Pointer to the local workspace, cast to EventWorkspace.
void doExec(const Mantid::API::Workspace_sptr &inputWorkspace, std::shared_ptr< Mantid::NeXus::NexusFileIO > &nexusFile, const bool keepFile=false, boost::optional< size_t > entryNumber=boost::optional< size_t >())
void getWSIndexList(std::vector< int > &indices, const Mantid::API::MatrixWorkspace_const_sptr &matrixWorkspace)
Get the list of workspace indices to use.
virtual bool saveLegacyInstrument()
void init() override
Overwrites Algorithm method.
double m_timeProgInit
Proportion of progress time expected to write initial part.
bool processGroups() override
Override process groups.
void saveSpectraDetectorMapNexus(const API::MatrixWorkspace &ws, ::NeXus::File *file, const std::vector< int > &wsIndices, const ::NeXus::NXcompression compression=::NeXus::LZW) const
Save the spectra detector map to an open NeXus file.
const std::string name() const override
Algorithm's name for identification overriding a virtual method.
void exec() override
Overwrites Algorithm method.
void setOtherProperties(IAlgorithm *alg, const std::string &propertyName, const std::string &propertyValue, int perioidNum) override
sets non workspace properties for the algorithm
void saveSpectrumNumbersNexus(const API::MatrixWorkspace &ws, ::NeXus::File *file, const std::vector< int > &wsIndices, const ::NeXus::NXcompression compression=::NeXus::LZW) const
Save the spectra numbers to an open NeXus file.
std::unique_ptr< API::Progress > m_progress
Progress bar.
Support for a property that holds an array of values.
Records the filename and the description of failure.
Marks code as not implemented yet.
virtual void setPropertyValue(const std::string &name, const std::string &value)=0
Sets property value from a string.
void setPropertySettings(const std::string &name, std::unique_ptr< IPropertySettings > settings)
void debug(const std::string &msg)
Logs at debug level.
void error(const std::string &msg)
Logs at error level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
void reportIncrement(int inc, const std::string &msg="")
Sends the progress notification and increment the loop counter by more than one.
void getSpherical(double &R, double &theta, double &phi) const noexcept
Return the vector's position in spherical coordinates.
Utility method for saving NeXus format of Mantid Workspace This class interfaces to the C Nexus API.
boost::optional< size_t > optional_size_t
int writeNexusProcessedDataEventCombined(const DataObjects::EventWorkspace_const_sptr &ws, std::vector< int64_t > &indices, double *tofs, float *weights, float *errorSquareds, int64_t *pulsetimes, bool compress) const
Write out a combined chunk of event data.
int writeNexusProcessedData2D(const API::MatrixWorkspace_const_sptr &localworkspace, const bool &uniformSpectra, const std::vector< int > &indices, const char *group_name, bool write2Ddata) const
write the workspace data
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const ITableWorkspace > ITableWorkspace_const_sptr
shared pointer to Mantid::API::ITableWorkspace (const version)
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< const IPeaksWorkspace > IPeaksWorkspace_const_sptr
shared pointer to Mantid::API::IPeaksWorkspace (const version)
EventType
What kind of event list is being stored.
NeXus::NexusFileIO::optional_size_t optional_size_t
std::shared_ptr< const OffsetsWorkspace > OffsetsWorkspace_const_sptr
shared pointer to a const OffsetsWorkspace
std::shared_ptr< const MaskWorkspace > MaskWorkspace_const_sptr
shared pointer to a const MaskWorkspace
constexpr double rad2deg
Radians to degrees conversion factor.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
std::shared_ptr< const Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
@ Input
An input workspace.