32template <
typename MDE,
size_t nd>
34 const std::string &filename) {
52 "An input MDEventWorkspace or MDHistoWorkspace.");
55 "The name of the Nexus file to write, as a full or relative path.\n"
56 "Optional if UpdateFileBackEnd is checked.");
58 setPropertySettings(
"Filename", std::make_unique<EnabledWhenProperty>(
"UpdateFileBackEnd",
IS_EQUAL_TO,
"0"));
60 declareProperty(
"UpdateFileBackEnd",
false,
61 "Only for MDEventWorkspaces with a file back end: check this to update "
62 "the NXS file on disk\n"
63 "to reflect the current data structure. Filename parameter is ignored.");
64 setPropertySettings(
"UpdateFileBackEnd", std::make_unique<EnabledWhenProperty>(
"MakeFileBacked",
IS_EQUAL_TO,
"0"));
66 declareProperty(
"MakeFileBacked",
false,
67 "For an MDEventWorkspace that was created in memory:\n"
68 "This saves it to a file AND makes the workspace into a "
70 setPropertySettings(
"MakeFileBacked", std::make_unique<EnabledWhenProperty>(
"UpdateFileBackEnd",
IS_EQUAL_TO,
"0"));
80 bool updateFileBackend =
getProperty(
"UpdateFileBackEnd");
81 bool makeFileBackend =
getProperty(
"MakeFileBacked");
82 if (updateFileBackend && makeFileBackend)
83 throw std::invalid_argument(
"Please choose either UpdateFileBackEnd or MakeFileBacked, not both.");
88 auto copyFile = wsIsFileBacked && !filename.empty() && filename != bc->getFilename();
90 if (makeFileBackend) {
91 throw std::runtime_error(
"MakeFileBacked selected but workspace is already file backed.");
94 if (updateFileBackend) {
95 throw std::runtime_error(
"UpdateFileBackEnd selected but workspace is not file backed.");
99 if (!wsIsFileBacked) {
100 Poco::File oldFile(filename);
101 if (oldFile.exists())
105 auto prog = std::make_unique<Progress>(
this, 0.0, 0.05, 1);
106 if (updateFileBackend)
109 throw std::runtime_error(
" attempt to update non-file backed workspace");
110 filename = bc->getFileIO()->getFileName();
115 auto nDims =
static_cast<int>(nd);
122 if (!updateFileBackend || !data_exist) {
130 if (updateFileBackend)
132 prepareUpdate<MDE, nd>(BoxFlatStruct, bc.get(), ws, filename);
133 }
else if (copyFile) {
136 prepareUpdate<MDE, nd>(BoxFlatStruct, bc.get(), ws, filename);
139 bc->getFileIO()->copyFileTo(filename);
147 if (makeFileBackend) {
149 bc->setFileBacked(Saver, filename);
151 std::vector<API::IMDNode *> &boxes = BoxFlatStruct.
getBoxes();
155 prog->resetNumSteps(boxes.size(), 0.06, 0.90);
156 for (
auto &boxe : boxes) {
157 auto saveableTag = boxe->getISaveable();
161 if (boxe->getDataInMemorySize() == 0 || boxe->getIsMasked())
167 saveableTag->clearDataFromMemory();
170 prog->report(
"Saving Box");
180 Saver->openFile(filename,
"w");
182 std::vector<API::IMDNode *> &boxes = BoxFlatStruct.
getBoxes();
183 std::vector<uint64_t> &eventIndex = BoxFlatStruct.
getEventIndex();
184 prog->resetNumSteps(boxes.size(), 0.06, 0.90);
185 for (
size_t i = 0; i < boxes.size(); i++) {
186 if (eventIndex[2 * i + 1] == 0 || boxes[i]->getIsMasked())
188 boxes[i]->saveAt(Saver.get(), eventIndex[2 * i]);
189 prog->report(
"Saving Box");
199 prog->resetNumSteps(8, 0.92, 1.00);
218 Poco::File oldFile(filename);
219 if (oldFile.exists())
226 file->makeGroup(
"MDHistoWorkspace",
"NXentry",
true);
229 file->writeData(
"coordinate_system",
static_cast<uint32_t
>(ws->getSpecialCoordinateSystem()));
232 file->writeData(
"visual_normalization",
static_cast<uint32_t
>(ws->displayNormalization()));
235 ws->getHistory().saveNexus(file.get());
238 for (uint16_t i = 0; i < ws->getNumExperimentInfo(); i++) {
243 file->makeGroup(groupName,
"NXgroup",
true);
244 file->putAttr(
"version", 1);
245 ei->saveExperimentInfoNexus(file.get());
251 file->writeData(
"dimensions", int32_t(ws->getNumDims()));
254 for (
size_t d = 0;
d < ws->getNumDims();
d++) {
255 std::ostringstream mess;
256 mess <<
"dimension" <<
d;
257 file->putAttr(mess.str(), ws->getDimension(
d)->toXMLString());
265 static_assert(
sizeof(
signal_t) ==
sizeof(
double),
"signal_t using has been changed!");
268 auto nPoints =
static_cast<int>(ws->getNPoints());
271 file->putData(ws->getSignalArray());
275 file->putData(ws->getErrorSquaredArray());
279 file->putData(ws->getNumEventsArray());
283 file->putData(ws->getMaskArray());
303 }
else if (histoWS) {
306 throw std::runtime_error(
"SaveMD can only save MDEventWorkspaces and "
307 "MDHistoWorkspaces.\nPlease use SaveNexus or "
308 "another algorithm appropriate for this workspace "
#define DECLARE_ALGORITHM(classname)
std::unique_ptr< Mantid::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
std::vector< uint64_t > & getEventIndex()
static void saveAffineTransformMatricies(Mantid::Nexus::File *const file, const API::IMDWorkspace_const_sptr &ws)
Save the affine matrices to both directional conversions to the data.
static void saveWSGenericInfo(Mantid::Nexus::File *const file, const API::IMDWorkspace_const_sptr &ws)
Save workspace generic info like dimension structure, history, title dimensions etc.
void saveBoxStructure(const std::string &fileName)
Save flat box structure into a file, defined by the file name.
void setBoxesFilePositions(bool setFileBacked)
static Mantid::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...
static void saveExperimentInfos(Mantid::Nexus::File *const file, const API::IMDEventWorkspace_const_sptr &ws)
Save each NEW ExperimentInfo to a spot in the file.
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
bool isFileBacked() const override
Mantid::API::BoxController_sptr getBoxController() override
Returns the BoxController used in this workspace.
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.
static unsigned short constexpr INT8
static unsigned short constexpr FLOAT64
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.