19#include <boost/scoped_ptr.hpp>
34 : m_nDims(0), m_MDEventType(), m_fileBasedTargetWS(false), m_Filenames(), m_EventLoader(), m_OutIWS(),
35 m_totalEvents(0), m_totalLoaded(0), m_fileMutex(), m_statsMutex() {}
48 std::vector<std::string> exts(1,
".nxs");
49 declareProperty(std::make_unique<MultipleFileProperty>(
"Filenames", exts),
50 "Select several MDEventWorkspace NXS files to merge "
51 "together. Files must have common box structure.");
54 "Choose a file to which to save the output workspace. \n"
55 "Optional: if specified, the workspace created will be file-backed. \n"
56 "If not, it will be created in memory.");
59 "Run the loading tasks in parallel.\n"
60 "This can be faster but might use more memory.");
63 "An output MDEventWorkspace.");
71 this->
progress(0.05,
"Loading File Info");
76 targetEventIndexes.assign(targetEventIndexes.size(), 0);
95 throw std::runtime_error(
"Inconsistent number of boxes found in file " +
m_Filenames[i] +
96 ". Cannot merge these files. Did you generate them all with "
97 "exactly the same box structure?");
101 size_t nBoxes = Boxes.size();
102 for (
size_t j = 0; j < nBoxes; j++) {
103 size_t ID = Boxes[j]->getID();
124 uint64_t eventsStart = 0;
125 for (
auto mdBox : Boxes) {
127 size_t ID = mdBox->getID();
130 if (boxType[ID] == 2)
133 uint64_t nEvents = targetEventIndexes[2 * ID + 1];
134 targetEventIndexes[ID * 2] = eventsStart;
136 mdBox->setFileBacked(eventsStart, nEvents,
false);
138 eventsStart += nEvents;
153 uint64_t nBoxEvents(0);
157 size_t ID = TargetBox->
getID();
159 nBoxEvents += numFileEvents[iw];
166 size_t ID = TargetBox->
getID();
168 if (numFileEvents[iw] == 0)
196 m_nDims =
static_cast<int>(bc->getNDims());
200 bc->setSplitThreshold(5000);
204 bc->setFileBacked(saver, outputFile);
206 g_log.
notice() <<
"Setting cache to 400 MB write.\n";
207 bc->getFileIO()->setWriteBufferSize(400000000 /
m_OutIWS->sizeofEvent());
223 m_progress = std::make_unique<Progress>(
this, 0.1, 0.9,
size_t(numBoxes));
237 DiskBuf = bc->getFileIO();
243 for (
size_t ib = 0; ib < numBoxes; ib++) {
244 auto box = boxes[ib];
251 if (box->getDataInMemorySize() > 0) {
252 box->getISaveable()->save();
253 box->clearDataFromMemory();
276 m_progress->reportIncrement(ib,
"Loading and merging box data");
280 bc->getFileIO()->flushData();
298 this->
progress(0.90,
"Refreshing Cache");
303 if (!outputFile.empty()) {
304 g_log.
notice() <<
"Starting SaveMD to update the file back-end.\n";
312 this->
progress(0.94,
"Saving ws history and dimensions");
315 this->
progress(0.98,
"Saving experiment infos");
342 if (!multiFileProp) {
343 throw std::logic_error(
"Filenames property must have MultipleFileProperty type.");
347 throw std::invalid_argument(
"Must specify at least one filename.");
350 std::string outputFile =
getProperty(
"OutputFilename");
352 if (!outputFile.empty()) {
354 if (Poco::File(outputFile).
exists())
355 throw std::invalid_argument(
" File " + outputFile +
356 " already exists. Can not use existing file "
357 "as the target to MergeMD files.\n" +
358 " Use it as one of source files if you want to add MD data to it");
365 loader->setPropertyValue(
"Filename", firstFile);
366 loader->setProperty(
"MetadataOnly",
false);
367 loader->setProperty(
"BoxStructureOnly",
true);
368 loader->setProperty(
"FileBackEnd",
false);
369 loader->executeAsChildAlg();
372 auto firstWS = std::dynamic_pointer_cast<API::IMDEventWorkspace>(result);
374 throw std::runtime_error(
"Can not load MDEventWorkspace from initial file " + firstFile);
379 m_OutIWS->setFileNeedsUpdating(
false);
#define DECLARE_ALGORITHM(classname)
static std::unique_ptr< QThreadPool > tp
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Kernel::Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
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.
This class is used by MDBox and MDGridBox in order to intelligently determine optimal behavior.
@ OptionalSave
to specify a file to write to but an empty string is
virtual void loadAndAddFrom(API::IBoxControllerIO *const, uint64_t, size_t, std::vector< coord_t > &)=0
Load the additional box data of specified size from the disk location provided using the class,...
virtual void clear()=0
Clear all contained data including precalculated averages.
virtual size_t getID() const =0
virtual void reserveMemoryForLoad(uint64_t)=0
A property to allow a user to specify multiple files to load.
A property class for workspaces.
The class responsible for saving events into nexus file using generic box controller interface Expect...
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()
const std::vector< int > & getBoxType() const
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...
CPUTimer : Timer that uses the CPU time, rather than wall-clock time to measure execution time.
Buffer objects that need to be written out to disk so as to optimize writing operations.
void flushCache()
Flush out all the data in the memory; and writes out everything in the to-write cache.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
void information(const std::string &msg)
Logs at information level.
A Thread Pool implementation that keeps a certain number of threads running (normally,...
A First-In-First-Out Thread Scheduler.
Algorithm to merge multiple MDEventWorkspaces from files that obey a common box format.
std::string m_MDEventType
string describes type of the event, stored in the workspaces.
void doExecByCloning(const Mantid::API::IMDEventWorkspace_sptr &ws, const std::string &outputFile)
Perform the merging, but clone the initial workspace and use the same splitting as its structure is e...
std::vector< std::string > m_Filenames
Files to load.
std::vector< API::IBoxControllerIO * > m_EventLoader
Vector of file handles to each input file //TODO unique?
uint64_t loadEventsFromSubBoxes(API::IMDNode *TargetBox)
Task that loads all of the events from corresponded boxes of all files that is being merged into a pa...
void finalizeOutput(const std::string &outputFile)
Now re-save the MDEventWorkspace to update the file back end.
std::unique_ptr< Mantid::API::Progress > m_progress
Progress reporter.
int m_nDims
number of workspace dimensions
~MergeMDFiles() override
Destructor.
bool m_fileBasedTargetWS
if the workspace is indeed file-based
DataObjects::MDBoxFlatTree m_BoxStruct
std::vector< DataObjects::MDBoxFlatTree > m_fileComponentsStructure
void exec() override
Run the algorithm.
Mantid::API::IMDEventWorkspace_sptr m_OutIWS
Output IMDEventWorkspace.
void clearEventLoaders()
Set to true if the output is cloned of the first one.
void init() override
Initialise the properties.
void loadBoxData()
Loads all of the box data required (no events) for later use.
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
bool exists(::NeXus::File &file, const std::string &name)
Based on the current group in the file, does the named sub-entry exist?
std::vector< T > flattenVector(const std::vector< std::vector< T > > &v)
A convenience function to "flatten" the given vector of vectors into a single vector.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
@ Output
An output workspace.