33template <
typename MDE,
size_t nd>
35 const std::string &filename) {
55 "An input MDEventWorkspace or MDHistoWorkspace.");
58 "The name of the Nexus file to write, as a full or relative path.\n"
59 "Optional if UpdateFileBackEnd is checked.");
61 setPropertySettings(
"Filename", std::make_unique<EnabledWhenProperty>(
"UpdateFileBackEnd",
IS_EQUAL_TO,
"0"));
63 declareProperty(
"UpdateFileBackEnd",
false,
64 "Only for MDEventWorkspaces with a file back end: check this to update "
65 "the NXS file on disk\n"
66 "to reflect the current data structure. Filename parameter is ignored.");
67 setPropertySettings(
"UpdateFileBackEnd", std::make_unique<EnabledWhenProperty>(
"MakeFileBacked",
IS_EQUAL_TO,
"0"));
69 declareProperty(
"MakeFileBacked",
false,
70 "For an MDEventWorkspace that was created in memory:\n"
71 "This saves it to a file AND makes the workspace into a "
73 setPropertySettings(
"MakeFileBacked", std::make_unique<EnabledWhenProperty>(
"UpdateFileBackEnd",
IS_EQUAL_TO,
"0"));
84 bool updateFileBackend =
getProperty(
"UpdateFileBackEnd");
85 bool makeFileBackend =
getProperty(
"MakeFileBacked");
86 if (updateFileBackend && makeFileBackend)
87 throw std::invalid_argument(
"Please choose either UpdateFileBackEnd or MakeFileBacked, not both.");
92 auto copyFile = wsIsFileBacked && !filename.empty() && filename != bc->getFilename();
94 if (makeFileBackend) {
95 throw std::runtime_error(
"MakeFileBacked selected but workspace is already file backed.");
98 if (updateFileBackend) {
99 throw std::runtime_error(
"UpdateFileBackEnd selected but workspace is not file backed.");
103 if (!wsIsFileBacked) {
104 Poco::File oldFile(filename);
105 if (oldFile.exists())
109 auto prog = std::make_unique<Progress>(
this, 0.0, 0.05, 1);
110 if (updateFileBackend)
115 throw std::runtime_error(
" attempt to update non-file backed workspace");
116 filename = bc->getFileIO()->getFileName();
122 auto nDims =
static_cast<int>(nd);
129 if (!updateFileBackend || !data_exist) {
137 if (updateFileBackend)
139 prepareUpdate<MDE, nd>(BoxFlatStruct, bc.get(), ws, filename);
140 }
else if (copyFile) {
143 prepareUpdate<MDE, nd>(BoxFlatStruct, bc.get(), ws, filename);
146 bc->getFileIO()->copyFileTo(filename);
154 if (makeFileBackend) {
156 bc->setFileBacked(Saver, filename);
158 std::vector<API::IMDNode *> &boxes = BoxFlatStruct.
getBoxes();
162 prog->resetNumSteps(boxes.size(), 0.06, 0.90);
163 for (
auto &boxe : boxes) {
164 auto saveableTag = boxe->getISaveable();
168 if (boxe->getDataInMemorySize() == 0 || boxe->getIsMasked())
175 saveableTag->clearDataFromMemory();
178 prog->report(
"Saving Box");
188 Saver->openFile(filename,
"w");
190 std::vector<API::IMDNode *> &boxes = BoxFlatStruct.
getBoxes();
191 std::vector<uint64_t> &eventIndex = BoxFlatStruct.
getEventIndex();
192 prog->resetNumSteps(boxes.size(), 0.06, 0.90);
193 for (
size_t i = 0; i < boxes.size(); i++) {
194 if (eventIndex[2 * i + 1] == 0 || boxes[i]->getIsMasked())
196 boxes[i]->saveAt(Saver.get(), eventIndex[2 * i]);
197 prog->report(
"Saving Box");
207 prog->resetNumSteps(8, 0.92, 1.00);
226 Poco::File oldFile(filename);
227 if (oldFile.exists())
231 auto file = std::make_unique<::NeXus::File>(filename, NXACC_CREATE5);
234 file->makeGroup(
"MDHistoWorkspace",
"NXentry",
true);
237 file->writeData(
"coordinate_system",
static_cast<uint32_t
>(ws->getSpecialCoordinateSystem()));
240 file->writeData(
"visual_normalization",
static_cast<uint32_t
>(ws->displayNormalization()));
243 ws->getHistory().saveNexus(file.get());
246 for (uint16_t i = 0; i < ws->getNumExperimentInfo(); i++) {
251 file->makeGroup(groupName,
"NXgroup",
true);
252 file->putAttr(
"version", 1);
253 ei->saveExperimentInfoNexus(file.get());
259 file->writeData(
"dimensions", int32_t(ws->getNumDims()));
262 for (
size_t d = 0;
d < ws->getNumDims();
d++) {
263 std::ostringstream mess;
264 mess <<
"dimension" <<
d;
265 file->putAttr(mess.str(), ws->getDimension(
d)->toXMLString());
273 static_assert(
sizeof(
signal_t) ==
sizeof(
double),
"signal_t using has been changed!");
276 auto nPoints =
static_cast<int>(ws->getNPoints());
278 file->makeData(
"signal", ::NeXus::FLOAT64, nPoints,
true);
279 file->putData(ws->getSignalArray());
282 file->makeData(
"errors_squared", ::NeXus::FLOAT64, nPoints,
true);
283 file->putData(ws->getErrorSquaredArray());
286 file->makeData(
"num_events", ::NeXus::FLOAT64, nPoints,
true);
287 file->putData(ws->getNumEventsArray());
290 file->makeData(
"mask", ::NeXus::INT8, nPoints,
true);
291 file->putData(ws->getMaskArray());
311 }
else if (histoWS) {
314 throw std::runtime_error(
"SaveMD can only save MDEventWorkspaces and "
315 "MDHistoWorkspaces.\nPlease use SaveNexus or "
316 "another algorithm appropriate for this workspace "
#define DECLARE_ALGORITHM(classname)
std::unique_ptr<::NeXus::File > file_holder_type
#define CALL_MDEVENT_FUNCTION(funcname, workspace)
Macro that makes it possible to call a templated method for a MDEventWorkspace using a IMDEventWorksp...
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.
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
IBoxControllerIO * getFileIO()
returns the pointer to the class, responsible for fileIO operations;
@ OptionalSave
to specify a file to write to but an empty string is
bool fileNeedsUpdating() const
void setFileNeedsUpdating(bool value)
Sets the marker set to true when a file-backed workspace needs its back-end file updated (by calling ...
A property class for workspaces.
The class responsible for saving events into nexus file using generic box controller interface Expect...
The class responsible for saving/loading MD boxes structure to/from HDD and for flattening/restoring ...
std::vector< API::IMDNode * > & getBoxes()
void initFlatStructure(const API::IMDEventWorkspace_sptr &pws, const std::string &fileName)
convert MDWS box structure into flat structure used for saving/loading on hdd
static void saveWSGenericInfo(::NeXus::File *const file, const API::IMDWorkspace_const_sptr &ws)
Save workspace generic info like dimension structure, history, title dimensions etc.
std::vector< uint64_t > & getEventIndex()
static void saveAffineTransformMatricies(::NeXus::File *const file, const API::IMDWorkspace_const_sptr &ws)
Save the affine matrices to both directional conversions to the data.
static void saveExperimentInfos(::NeXus::File *const file, const API::IMDEventWorkspace_const_sptr &ws)
Save each NEW ExperimentInfo to a spot in the file.
void saveBoxStructure(const std::string &fileName)
Save flat box structure into a file, defined by the file name.
::NeXus::File * createOrOpenMDWSgroup(const std::string &fileName, int &nDims, const std::string &WSEventType, bool readOnly, bool &alreadyExists)
The function to create a NeXus MD workspace group with specified events type and number of dimensions...
void setBoxesFilePositions(bool setFileBacked)
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
Mantid::API::BoxController_sptr getBoxController() override
Returns the BoxController used in this workspace.
bool isFileBacked() const override
static std::string getTypeName()
void flushCache()
Flush out all the data in the memory; and writes out everything in the to-write cache.
Save a MDEventWorkspace to a .nxs file.
void doSaveEvents(typename DataObjects::MDEventWorkspace< MDE, nd >::sptr ws)
Helper method.
void exec() override
Run the algorithm.
void doSaveHisto(const Mantid::DataObjects::MDHistoWorkspace_sptr &ws)
Save the MDHistoWorkspace.
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
std::shared_ptr< MDHistoWorkspace > MDHistoWorkspace_sptr
A shared pointer to a MDHistoWorkspace.
std::string toString(const T &value)
Convert a number to a string.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
double signal_t
Typedef for the signal recorded in a MDBox, etc.
@ Input
An input workspace.