From 172f07be616d985451f3fe9ed47d878112e47bd7 Mon Sep 17 00:00:00 2001 From: Alex Buts <Alex.Buts@stfc.ac.uk> Date: Tue, 26 Jun 2012 15:35:33 +0100 Subject: [PATCH] refs #5244 further modifications to allow ConvToMD running multithread refs #5537 Renamed couple of classes responsible for event conversion --- .../API/inc/MantidAPI/BoxController.h | 16 +- Code/Mantid/Framework/Kernel/CMakeLists.txt | 3 + .../Kernel/inc/MantidKernel/FunctionTask.h | 5 +- .../MantidMDAlgorithms/ConvertToMDEvents.h | 8 +- .../MDAlgorithms/src/ConvertToMDEvents.cpp | 3 - Code/Mantid/Framework/MDEvents/CMakeLists.txt | 8 +- .../{ConvToMDEventsBase.h => ConvToMDBase.h} | 6 +- .../MantidMDEvents/ConvToMDEventsSelector.h | 2 +- .../inc/MantidMDEvents/ConvToMDEventsWS.h | 74 ++++++++ .../inc/MantidMDEvents/ConvToMDPreprocDet.h | 9 +- .../MantidMDEvents/UnitsConversionHelper.h | 3 +- ...onvToMDEventsBase.cpp => ConvToMDBase.cpp} | 11 +- .../MDEvents/src/ConvToMDEventsEvents.cpp | 93 ---------- .../MDEvents/src/ConvToMDEventsHisto.cpp | 10 +- .../MDEvents/src/ConvToMDEventsSelector.cpp | 14 +- .../MDEvents/src/ConvToMDEventsWS.cpp | 162 ++++++++++++++++++ .../MDEvents/src/ConvToMDPreprocDet.cpp | 30 ---- .../src/ConvertToDiffractionMDWorkspace.cpp | 10 +- .../MDEvents/src/MDEventWSWrapper.cpp | 2 +- .../MDEvents/src/UnitsConversionHelper.cpp | 20 ++- .../test/ConvertToMDEventsParamsTest.h | 35 +--- 21 files changed, 309 insertions(+), 215 deletions(-) rename Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/{ConvToMDEventsBase.h => ConvToMDBase.h} (97%) create mode 100644 Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h rename Code/Mantid/Framework/MDEvents/src/{ConvToMDEventsBase.cpp => ConvToMDBase.cpp} (77%) delete mode 100644 Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp create mode 100644 Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp diff --git a/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h b/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h index 1636da8d049..be33cc72273 100644 --- a/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h +++ b/Code/Mantid/Framework/API/inc/MantidAPI/BoxController.h @@ -241,15 +241,25 @@ namespace API * would be a slow-down, but keeping the boxes split at an earlier stage * should help scalability for later adding, so there is a balance to get. * - * @param eventsAdded :: How many events were added since the last split? - * @param numMDBoxes :: How many un-split MDBoxes are there (total) in the workspace + * @param nEventsInOutput :: How many events are currently in workspace in memory; + * @param eventsAdded :: How many events were added since the last split? + * @param numMDBoxes :: How many un-split MDBoxes are there (total) in the workspace * @return true if the boxes should get split. */ - bool shouldSplitBoxes(size_t eventsAdded, size_t numMDBoxes) const + bool shouldSplitBoxes(size_t nEventsInOutput,size_t eventsAdded, size_t numMDBoxes) const { // Avoid divide by zero if(numMDBoxes == 0) return false; + // Performance depends pretty strongly on WHEN you split the boxes. + // This is an empirically-determined way to optimize the splitting calls. + // Split when adding 1/16^th as many events as are already in the output, + // (because when the workspace gets very large you should split less often) + // But no more often than every 10 million events. + size_t comparisonPoint = nEventsInOutput/16; + if (comparisonPoint < 10000000) + comparisonPoint = 10000000; + if (eventsAdded > (comparisonPoint))return true; // Return true if the average # of events per box is big enough to split. return ((eventsAdded / numMDBoxes) > m_SplitThreshold); diff --git a/Code/Mantid/Framework/Kernel/CMakeLists.txt b/Code/Mantid/Framework/Kernel/CMakeLists.txt index dc79c8038d2..b7ca873bb5e 100644 --- a/Code/Mantid/Framework/Kernel/CMakeLists.txt +++ b/Code/Mantid/Framework/Kernel/CMakeLists.txt @@ -185,10 +185,13 @@ set ( INC_FILES inc/MantidKernel/Strings.h inc/MantidKernel/System.h inc/MantidKernel/TestChannel.h + inc/MantidKernel/ThreadPool.h inc/MantidKernel/ThreadPoolRunnable.h inc/MantidKernel/ThreadSafeLogStream.h inc/MantidKernel/ThreadScheduler.h inc/MantidKernel/ThreadSchedulerMutexes.h + inc/MantidKernel/Task.h + inc/MantidKernel/FunctionTask.h inc/MantidKernel/TimeSeriesProperty.h inc/MantidKernel/TimeSplitter.h inc/MantidKernel/Timer.h diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h index 164eee61c18..62038dcac44 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/FunctionTask.h @@ -27,6 +27,8 @@ public: /// Typedef for a function with no arguments and no return typedef void(*voidFunction)(); + /// Typedef for a function with no arguments and size_t return + typedef size_t(*sizetFunction)(); //--------------------------------------------------------------------------------------------- /** Constructor for a simple void function. @@ -40,7 +42,7 @@ public: * @param cost :: computational cost */ FunctionTask(voidFunction func, double cost=1.0) - : Task(cost), m_voidFunc(func) + : Task(cost), m_voidFunc(func),m_sizetFunc(NULL) { } @@ -74,6 +76,7 @@ public: protected: boost::function<void ()> m_voidFunc; + boost::function<size_t ()> m_sizetFunc; }; diff --git a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h index 22b6f7b31fb..13269aac092 100644 --- a/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h +++ b/Code/Mantid/Framework/MDAlgorithms/inc/MantidMDAlgorithms/ConvertToMDEvents.h @@ -75,13 +75,7 @@ namespace MDAlgorithms /// logger -> to provide logging, for MD dataset file operations static Mantid::Kernel::Logger& convert_log; /// pointer to the class, which does the particular conversion - boost::shared_ptr<MDEvents::ConvToMDEventsBase> pConvertor; - - /// the class which knows about existing subalgorithms and generates alforithm ID as function of input parameters of this algorithm. - ///ConvertToMD::ConvertToMDEventsParams ParamParser; - /// The class which keeps map of all existing subalgorithms converting to MDEventWorkspace. - /// It returns the pointer to the subalgorithm receiving alogID from ParamParser. Shoud be re-implemented through a singleton if used not only here. - //ConvertToMDEventsSubalgFactory subAlgFactory; + boost::shared_ptr<MDEvents::ConvToMDEventsBase> pConvertor; //------------------------------------------------------------------------------------------------------------------------------------------ protected: //for testing static Mantid::Kernel::Logger & getLogger(); diff --git a/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp b/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp index a653b676713..31bc521a83e 100644 --- a/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp +++ b/Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp @@ -185,9 +185,6 @@ ConvertToMDEvents::init() /* Execute the algorithm. */ void ConvertToMDEvents::exec() { - // initiate all availible subalgorithms for further usage (it will do it only once, first time the algorithm is executed); - // this->subAlgFactory.init(ParamParser); - // initiate class which would deal with any dimension workspaces, handling if(!pWSWrapper.get()){ pWSWrapper = boost::shared_ptr<MDEvents::MDEventWSWrapper>(new MDEvents::MDEventWSWrapper()); diff --git a/Code/Mantid/Framework/MDEvents/CMakeLists.txt b/Code/Mantid/Framework/MDEvents/CMakeLists.txt index 4e76b3f2820..2d045ca8bd4 100644 --- a/Code/Mantid/Framework/MDEvents/CMakeLists.txt +++ b/Code/Mantid/Framework/MDEvents/CMakeLists.txt @@ -8,8 +8,8 @@ set ( SRC_FILES src/BoxControllerSettingsAlgorithm.cpp src/CentroidPeaksMD.cpp src/CloneMDWorkspace.cpp - src/ConvToMDEventsBase.cpp - src/ConvToMDEventsEvents.cpp + src/ConvToMDBase.cpp + src/ConvToMDEventsWS.cpp src/ConvToMDEventsHisto.cpp src/ConvToMDEventsSelector.cpp src/ConvToMDPreprocDet.cpp @@ -78,8 +78,8 @@ set ( INC_FILES inc/MantidMDEvents/BoxControllerSettingsAlgorithm.h inc/MantidMDEvents/CentroidPeaksMD.h inc/MantidMDEvents/CloneMDWorkspace.h - inc/MantidMDEvents/ConvToMDEventsBase.h - inc/MantidMDEvents/ConvToMDEventsEvents.h + inc/MantidMDEvents/ConvToMDBase.h + inc/MantidMDEvents/ConvToMDEventsWS.h inc/MantidMDEvents/ConvToMDEventsHisto.h inc/MantidMDEvents/ConvToMDEventsSelector.h inc/MantidMDEvents/ConvToMDPreprocDet.h diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsBase.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDBase.h similarity index 97% rename from Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsBase.h rename to Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDBase.h index 44875836109..cf597e375f0 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsBase.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDBase.h @@ -50,18 +50,18 @@ namespace MDEvents Code Documentation is available at: <http://doxygen.mantidproject.org> */ - class DLLExport ConvToMDEventsBase + class DLLExport ConvToMDBase { public: // constructor; - ConvToMDEventsBase(); + ConvToMDBase(); ///method which initates all main class variables virtual size_t initialize(const MDWSDescription &WSD, boost::shared_ptr<MDEventWSWrapper> inWSWrapper); /// method which starts the conversion procedure virtual void runConversion(API::Progress *)=0; /// virtual destructor - virtual ~ConvToMDEventsBase(){}; + virtual ~ConvToMDBase(){}; protected: diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h index f99b23c0f77..d940bf7b0d9 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsSelector.h @@ -2,7 +2,7 @@ #define H_CONV_TOMDEVENTS_SELECTOR -#include "MantidMDEvents/ConvToMDEventsEvents.h" +#include "MantidMDEvents/ConvToMDEventsWS.h" #include "MantidMDEvents/ConvToMDEventsHisto.h" namespace Mantid diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h new file mode 100644 index 00000000000..19d9ab3e4bf --- /dev/null +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDEventsWS.h @@ -0,0 +1,74 @@ +#ifndef H_CONVERT_TO_MD_EVENTWS +#define H_CONVERT_TO_MD_EVENTWS +// +#include "MantidKernel/System.h" +#include "MantidKernel/Exception.h" +#include "MantidAPI/Algorithm.h" +#include <vector> + +#include "MantidDataObjects/EventWorkspace.h" + +#include "MantidAPI/NumericAxis.h" +#include "MantidAPI/Progress.h" +#include "MantidKernel/PhysicalConstants.h" + +#include "MantidMDEvents/MDEventWSWrapper.h" +#include "MantidMDEvents/MDEvent.h" + +#include "MantidMDEvents/ConvToMDPreprocDet.h" +#include "MantidMDEvents/ConvToMDBase.h" +// coordinate transformation +#include "MantidMDEvents/MDTransfFactory.h" + +namespace Mantid +{ +namespace MDEvents +{ +/** The class specializes ConvToMDEventsBase for the case when the conversion occurs from Events WS to the MD events WS + * + * @date 11-10-2011 + + Copyright © 2010 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File/ change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> +*/ + +// Class to process event workspace by direct conversion: + +class ConvToMDEventsWS: public ConvToMDBase +{ + public: + size_t initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper); + void runConversion(API::Progress *pProg); + +private: + // function runs the conversion on + virtual size_t conversionChunk(size_t workspaceIndex); + // the pointer to the source event workspace as event ws does not work through the public Matrix WS interface + DataObjects::EventWorkspace_const_sptr pEventWS; + + /**function converts particular type of events into MD space and add these events to the workspace itself */ + template <class T> size_t convertEventList(size_t workspaceIndex); + +}; + +} // endNamespace MDEvents +} // endNamespace Mantid + +#endif diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h index 533a5098662..97cbe313697 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/ConvToMDPreprocDet.h @@ -115,14 +115,7 @@ private: // function allocates the class detectors memory void allocDetMemory(size_t nSpectra); - //void setEi(const API::MatrixWorkspace_sptr inputWS); - - - // parameter which describes the conversion mode, used to convert uints using TOF and detector's positions - // int emode; - // parameter wjocj describes the energy used to convert uints using TOF and detector's positions - // double efix; - // source-sample distance used to convert uints using TOF and detector's positions + // source-sample distance used to convert uints using TOF and detector's positions double L1; // minimal position for the detectors Kernel::V3D minDetPosition; diff --git a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h index 0ed70fb10a5..aacd2877652 100644 --- a/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h +++ b/Code/Mantid/Framework/MDEvents/inc/MantidMDEvents/UnitsConversionHelper.h @@ -73,7 +73,8 @@ public: void initialize(const MDWSDescription &TWSD,const std::string &units_to); void updateConversion(size_t i); double convertUnits(double val); - + // copy constructor + UnitsConversionHelper(const UnitsConversionHelper &another); protected: // for testing /// establish and initialize proper units conversion from input to output units; ConvertToMD::ConvertUnits analyzeUnitsConversion(const std::string &UnitsFrom,const std::string &UnitsTo); diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsBase.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDBase.cpp similarity index 77% rename from Code/Mantid/Framework/MDEvents/src/ConvToMDEventsBase.cpp rename to Code/Mantid/Framework/MDEvents/src/ConvToMDBase.cpp index a75bbcc55aa..dbb65ed051d 100644 --- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsBase.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDBase.cpp @@ -1,4 +1,4 @@ -#include "MantidMDEvents/ConvToMDEventsBase.h" +#include "MantidMDEvents/ConvToMDBase.h" namespace Mantid @@ -7,18 +7,16 @@ namespace MDEvents { // logger for conversion - Kernel::Logger& ConvToMDEventsBase::convert_log =Kernel::Logger::get("MD-Algorithms"); + Kernel::Logger& ConvToMDBase::convert_log =Kernel::Logger::get("MD-Algorithms"); /** method which initates all main class variables - * @param pWS2D -- shared pointer to input matirx workspace to process - * @param detLoc -- class with information about datecotrs, partially transformed for convenient Q calculations * @param WSD -- class describing the target workspace. * the algorithm uses target workspace limints, transformation matix from source to the target workspace and the parameters, needed for * unit conversion (if any) * @param pWSWrapper -- shared pointer to target MD Event workspace to add converted events to. */ -size_t ConvToMDEventsBase::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper) +size_t ConvToMDBase::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper) { pDetLoc = WSD.getDetectors(); inWS2D = WSD.getInWS(); @@ -49,7 +47,8 @@ size_t ConvToMDEventsBase::initialize(const MDEvents::MDWSDescription &WSD, boo return n_spectra; }; -ConvToMDEventsBase::ConvToMDEventsBase() +/** empty default constructor */ +ConvToMDBase::ConvToMDBase() {} diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp deleted file mode 100644 index 537ed67a4dc..00000000000 --- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsEvents.cpp +++ /dev/null @@ -1,93 +0,0 @@ -#include "MantidMDEvents/ConvToMDEventsEvents.h" -// - -namespace Mantid -{ -namespace MDEvents -{ - - -size_t ConvToMDEventsEvents::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper) -{ - size_t numSpec=ConvToMDEventsBase::initialize(WSD,inWSWrapper); - - - pEventWS = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>(inWS2D); - if(!pEventWS.get()){ - throw(std::logic_error(" ConvertToMDEvensEventWS should work with defined event workspace")); - } - - return numSpec; -} - -void ConvToMDEventsEvents::runConversion(API::Progress *pProg) -{ - // Get the box controller - Mantid::API::BoxController_sptr bc = pWSWrapper->pWorkspace()->getBoxController(); - size_t lastNumBoxes = bc->getTotalNumMDBoxes(); - - // preprocessed detectors insure that each detector has its own spectra - size_t nValidSpectra = this->pDetLoc->nDetectors(); - - // if any property dimension is outside of the data range requested, the job is done; - if(!pQConverter->calcGenericVariables(Coord,this->n_dims))return; - - size_t eventsAdded = 0; - for (size_t wi=0; wi <nValidSpectra; wi++) - { - size_t iSpec = this->pDetLoc->getDetSpectra(wi); - UnitConversion.updateConversion(wi); - - eventsAdded += this->conversionChunk(iSpec); - // Give this task to the scheduler - //%double cost = double(el.getNumberEvents()); - //ts->push( new FunctionTask( func, cost) ); - - // Keep a running total of how many events we've added - if (bc->shouldSplitBoxes(eventsAdded, lastNumBoxes)){ - // Do all the adding tasks - // tp.joinAll(); - // Now do all the splitting tasks - //ws->splitAllIfNeeded(ts); - pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL); - //if (ts->size() > 0) tp.joinAll(); - - // Count the new # of boxes. - lastNumBoxes = pWSWrapper->pWorkspace()->getBoxController()->getTotalNumMDBoxes(); - pProg->report(wi); - } - - } - //tp.joinAll(); - // Do a final splitting of everything - //ws->splitAllIfNeeded(ts); - //tp.joinAll(); - pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL); - // Recount totals at the end. - pWSWrapper->pWorkspace()->refreshCache(); - pWSWrapper->refreshCentroid(); - pProg->report(); -} - -// -size_t ConvToMDEventsEvents::conversionChunk(size_t workspaceIndex) -{ - - switch (this->pEventWS->getEventList(workspaceIndex).getEventType()) - { - case Mantid::API::TOF: - return this->convertEventList<Mantid::DataObjects::TofEvent>(workspaceIndex); - case Mantid::API::WEIGHTED: - return this->convertEventList<Mantid::DataObjects::WeightedEvent>(workspaceIndex); - case Mantid::API::WEIGHTED_NOTIME: - return this->convertEventList<Mantid::DataObjects::WeightedEventNoTime>(workspaceIndex); - default: - throw std::runtime_error("EventList had an unexpected data type!"); - } -} - - -} // endNamespace MDEvents -} // endNamespace Mantid - - diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp index cfb1a8a1d79..a12e878ec82 100644 --- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsHisto.cpp @@ -13,11 +13,15 @@ inline bool isNaN(T val){ return (val!=buf); } +/** method sets up all internal variables necessary to convert from Matrix2D workspace to MDEvent workspace + @parameter WSD -- the class describing the target MD workspace, sorurce matrtix workspace and the transformations, necessary to perform on these workspaces + @parameter inWSWrapper -- the class wrapping the target MD workspace +*/ size_t ConvToMDEventsHisto::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper) { size_t numSpec=ConvToMDEventsBase::initialize(WSD,inWSWrapper); - + // check if we indeed have matrix workspace as input. DataObjects::Workspace2D_const_sptr pWS2D = boost::dynamic_pointer_cast<const DataObjects::Workspace2D>(inWS2D); if(!pWS2D.get()){ throw(std::logic_error("ConvToMDEventsHisto should work with defined histrohram workspace")); @@ -33,6 +37,7 @@ void ConvToMDEventsHisto::runConversion(API::Progress *pProg) // Mantid::API::BoxController_sptr bc = pWSWrapper->pWorkspace()->getBoxController(); size_t lastNumBoxes = bc->getTotalNumMDBoxes(); + size_t nEventsInWS = pWSWrapper->pWorkspace()->getNPoints(); // const size_t specSize = this->inWS2D->blocksize(); @@ -100,11 +105,12 @@ void ConvToMDEventsHisto::runConversion(API::Progress *pProg) if(n_buf_events>=buf_size){ pWSWrapper->addMDData(sig_err,run_index,det_ids,allCoord,n_buf_events); n_added_events+=n_buf_events; + nEventsInWS +=n_buf_events; // reset buffer counts n_coordinates= 0; n_buf_events = 0; - if (bc->shouldSplitBoxes(n_added_events, lastNumBoxes)){ + if (bc->shouldSplitBoxes(nEventsInWS,n_added_events, lastNumBoxes)){ // Do all the adding tasks // tp.joinAll(); // Now do all the splitting tasks diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp index 740fdc74733..305882fa9bf 100644 --- a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsSelector.cpp @@ -22,8 +22,8 @@ enum wsType { // identify what kind of workspace we expect to process wsType inputWSType(Undefined); - if(dynamic_cast<DataObjects::EventWorkspace *>(inputWS.get())) inputWSType = EventWS; - if(dynamic_cast<DataObjects::Workspace2D *>(inputWS.get()) ) inputWSType = Matrix2DWS; + if(boost::dynamic_pointer_cast<DataObjects::EventWorkspace>(inputWS)) inputWSType = EventWS; + if(boost::dynamic_pointer_cast<DataObjects::Workspace2D>(inputWS)) inputWSType = Matrix2DWS; if(inputWSType == Undefined) { @@ -35,8 +35,8 @@ enum wsType ConvToMDEventsBase *pSolver = currentSolver.get(); if(pSolver) { - if(dynamic_cast<ConvToMDEventsEvents *>(pSolver)) wsConvType = EventWS; - if(dynamic_cast<ConvToMDEventsHisto *>(pSolver)) wsConvType = Matrix2DWS; + if(dynamic_cast<ConvToMDEventsEvents *>(pSolver)) wsConvType = EventWS; + if(dynamic_cast<ConvToMDEventsHisto *>(pSolver)) wsConvType = Matrix2DWS; } // select a converter, which corresponds to the workspace type @@ -44,9 +44,9 @@ enum wsType { switch(inputWSType) { - case(EventWS): return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsEvents()); - case(Matrix2DWS): return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsHisto()); - default: throw(std::logic_error("ConvToMDEventsSelector: requested converter for unknown ws type")); + case(EventWS): return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsEvents()); + case(Matrix2DWS): return boost::shared_ptr<ConvToMDEventsBase>(new ConvToMDEventsHisto()); + default: throw(std::logic_error("ConvToMDEventsSelector: requested converter for unknown ws type")); } }else{ // existing converter is suitable for the workspace diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp new file mode 100644 index 00000000000..8fd92b0fb36 --- /dev/null +++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDEventsWS.cpp @@ -0,0 +1,162 @@ +#include "MantidMDEvents/ConvToMDEventsEvents.h" +// + +namespace Mantid +{ +namespace MDEvents +{ +/**function converts particular list of events type T into MD space and adds these events to the workspace itself */ +template <class T> +size_t ConvToMDEventsEvents::convertEventList(size_t workspaceIndex) +{ + + const Mantid::DataObjects::EventList & el = this->pEventWS->getEventList(workspaceIndex); + size_t iSpec = this->pDetLoc->getDetSpectra(workspaceIndex); + // create local unit conversion class + UnitConversionHelper localUnitConv(UnitConversion); + + size_t numEvents = el.getNumberEvents(); + size_t detNum = this->pDetLoc->getWSDet(workspaceIndex); + uint32_t detID = this->pDetLoc->getDetID(detNum); + uint16_t runIndexLoc = this->runIndex; + + std::vector<coord_t>locCoord(this->Coord); + // set up unit conversion and calculate up all coordinates, which depend on spectra index only + if(!pQConverter->calcYDepCoordinates(locCoord,detNum))return 0; // skip if any y outsize of the range of interest; + localUnitConv.updateConversion(detNum); +// + // allocate temporary buffers for MD Events data + // MD events coordinates buffer + std::vector<coord_t> allCoord; + std::vector<float> sig_err; // array for signal and error. + std::vector<uint16_t> run_index; // Buffer run index for each event + std::vector<uint32_t> det_ids; // Buffer of det Id-s for each event + + allCoord.reserve(this->n_dims*numEvents); sig_err.reserve(2*numEvents); + run_index.reserve(numEvents); det_ids.reserve(numEvents); + + // This little dance makes the getting vector of events more general (since you can't overload by return type). + typename std::vector<T>const * events_ptr; + getEventsFrom(el, events_ptr); + const typename std::vector<T> & events = *events_ptr; + + + + // Iterators to start/end + typename std::vector<T>::const_iterator it = events.begin(); + typename std::vector<T>::const_iterator it_end = events.end(); + + + it = events.begin(); + for (; it != it_end; it++) + { + double val=localUnitConv.convertUnits(it->tof()); + if(!pQConverter->calcMatrixCoord(val,locCoord))continue; // skip ND outside the range + + + sig_err.push_back(float(it->weight())); + sig_err.push_back(float(it->errorSquared())); + run_index.push_back(runIndexLoc); + det_ids.push_back(detID); + allCoord.insert(allCoord.end(),locCoord.begin(),locCoord.end()); + } + + // Add them to the MDEW + size_t n_added_events = run_index.size(); + pWSWrapper->addMDData(sig_err,run_index,det_ids,allCoord,n_added_events); + return n_added_events; +} + + +/** method sets up all internal variables necessary to convert from Event Workspace to MDEvent workspace + @parameter WSD -- the class describing the target MD workspace, sorurce Event workspace and the transformations, necessary to perform on these workspaces + @parameter inWSWrapper -- the class wrapping the target MD workspace +*/ +size_t ConvToMDEventsEvents::initialize(const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper) +{ + size_t numSpec=ConvToMDEventsBase::initialize(WSD,inWSWrapper); + + + pEventWS = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>(inWS2D); + if(!pEventWS.get()){ + throw(std::logic_error(" ConvertToMDEvensEventWS should work with defined event workspace")); + } + + return numSpec; +} + +void ConvToMDEventsEvents::runConversion(API::Progress *pProg) +{ + // Get the box controller + Mantid::API::BoxController_sptr bc = pWSWrapper->pWorkspace()->getBoxController(); + size_t lastNumBoxes = bc->getTotalNumMDBoxes(); + size_t nEventsInWS = pWSWrapper->pWorkspace()->getNPoints(); + // Is the access to input events thread-safe? + bool MultiThreadedAdding = pEventWS->threadSafe(); + + + // preprocessed detectors insure that each detector has its own spectra + size_t nValidSpectra = this->pDetLoc->nDetectors(); + + // if any property dimension is outside of the data range requested, the job is done; + if(!pQConverter->calcGenericVariables(Coord,this->n_dims))return; + + size_t eventsAdded = 0; + for (size_t wi=0; wi <nValidSpectra; wi++) + { + + size_t nConverted = this->conversionChunk(wi); + eventsAdded += nConverted; + nEventsInWS += nConverted; + // Give this task to the scheduler + //%double cost = double(el.getNumberEvents()); + //ts->push( new FunctionTask( func, cost) ); + + // Keep a running total of how many events we've added + if (bc->shouldSplitBoxes(nEventsInWS,eventsAdded, lastNumBoxes)){ + // Do all the adding tasks + // tp.joinAll(); + // Now do all the splitting tasks + //ws->splitAllIfNeeded(ts); + pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL); + //if (ts->size() > 0) tp.joinAll(); + + // Count the new # of boxes. + lastNumBoxes = pWSWrapper->pWorkspace()->getBoxController()->getTotalNumMDBoxes(); + pProg->report(wi); + } + + } + //tp.joinAll(); + // Do a final splitting of everything + //ws->splitAllIfNeeded(ts); + //tp.joinAll(); + pWSWrapper->pWorkspace()->splitAllIfNeeded(NULL); + // Recount totals at the end. + pWSWrapper->pWorkspace()->refreshCache(); + pWSWrapper->refreshCentroid(); + pProg->report(); +} + +// +size_t ConvToMDEventsEvents::conversionChunk(size_t workspaceIndex) +{ + + switch (this->pEventWS->getEventList(workspaceIndex).getEventType()) + { + case Mantid::API::TOF: + return this->convertEventList<Mantid::DataObjects::TofEvent>(workspaceIndex); + case Mantid::API::WEIGHTED: + return this->convertEventList<Mantid::DataObjects::WeightedEvent>(workspaceIndex); + case Mantid::API::WEIGHTED_NOTIME: + return this->convertEventList<Mantid::DataObjects::WeightedEventNoTime>(workspaceIndex); + default: + throw std::runtime_error("EventList had an unexpected data type!"); + } +} + + +} // endNamespace MDEvents +} // endNamespace Mantid + + diff --git a/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp b/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp index cf8ef985a38..a23e346f9ff 100644 --- a/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ConvToMDPreprocDet.cpp @@ -9,36 +9,6 @@ namespace Mantid { namespace MDEvents { -///// function sets appropriate energy conversion mode to work with detectors and unit conversion -//void ConvToMDPreprocDet::setEmode(int mode) -//{ -// if(mode<-1||mode>2){ -// std::string Err="Energy conversion mode has to be between -1 and 2 but trying to set: "+boost::lexical_cast<std::string>(mode); -// throw(std::invalid_argument(Err)); -// } -// emode = mode; -//} -/// function sets appropriate energy to work with detectors and unit conversion -//void ConvToMDPreprocDet::setEfix(double Ei) -//{ -// if(Ei<=0){ -// std::string Err="Input neutron's energy can not be negative but equal: "+boost::lexical_cast<std::string>(Ei); -// throw(std::invalid_argument(Err)); -// } -// efix = Ei; -//} -/** Function sets up energy of neurtorns used by number of conversion algorithms */ -//void ConvToMDPreprocDet::setEi(const API::MatrixWorkspace_sptr inputWS) -//{ -// try{ -// Kernel::PropertyWithValue<double> *pProp(NULL); -// pProp=dynamic_cast<Kernel::PropertyWithValue<double> *>(inputWS->run().getProperty("Ei")); -// efix=(*pProp); -// }catch(...){ -// efix= std::numeric_limits<double>::quiet_NaN(); -// } -//} - /// function sets source-sample distance to work with detectors and unit conversion void ConvToMDPreprocDet::setL1(double Dist) { diff --git a/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp b/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp index 6290a5e9e8f..b5b8a92d82c 100644 --- a/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp +++ b/Code/Mantid/Framework/MDEvents/src/ConvertToDiffractionMDWorkspace.cpp @@ -558,15 +558,7 @@ namespace MDEvents eventsAdded += eventsAdding; approxEventsInOutput += eventsAdding; - // Performance depends pretty strongly on WHEN you split the boxes. - // This is an empirically-determined way to optimize the splitting calls. - // Split when adding 1/16^th as many events as are already in the output, - // (because when the workspace gets very large you should split less often) - // But no more often than every 10 million events. - size_t comparisonPoint = approxEventsInOutput/16; - if (comparisonPoint < 10000000) - comparisonPoint = 10000000; - if (bc->shouldSplitBoxes(eventsAdded, lastNumBoxes) || (eventsAdded > (comparisonPoint))) + if (bc->shouldSplitBoxes(approxEventsInOutput,eventsAdded, lastNumBoxes)) { if (DODEBUG) g_log.information() << cputim << ": Added tasks worth " << eventsAdded << " events. WorkspaceIndex " << wi << std::endl; // Do all the adding tasks diff --git a/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp b/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp index 9313f95fc9c..b5dd6a8fb33 100644 --- a/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp +++ b/Code/Mantid/Framework/MDEvents/src/MDEventWSWrapper.cpp @@ -57,7 +57,7 @@ void MDEventWSWrapper::addMDData(std::vector<float> &sig_err,std::vector<uint16 /** method should be called at the end of the algorithm, to let the workspace manager know that it has whole responsibility for the workspace - (As the algorithm is static, it will hold the pointer to the workspace otherwise, not allowing the WS manager to delete WS on request or when it find this usefull)*/ + (As the algorithm is static, it will hold the pointer to the workspace otherwise, not allowing the WS manager to delete WS on request or when it finds this usefull)*/ void MDEventWSWrapper::releaseWorkspace() { // decrease the sp count by one diff --git a/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp b/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp index b41786944ea..e04ce9bada3 100644 --- a/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp +++ b/Code/Mantid/Framework/MDEvents/src/UnitsConversionHelper.cpp @@ -150,8 +150,24 @@ double UnitsConversionHelper::convertUnits(double val) throw std::runtime_error("updateConversion: unknown type of conversion requested"); } - - +} +// copy constructor; +UnitsConversionHelper::UnitsConversionHelper(const UnitsConversionHelper &another) +{ + UnitCnvrsn = another.UnitCnvrsn; + factor = another.factor; + power = another.power; + + emode = another.emode; + L1 = another.L1; + efix = another.efix; + twoTheta = another.twoTheta; + L2 = another.L2; + pTwoTheta = another.pTwoTheta; + pL2 = another.pL2; + + if(pSourceWSUnit.get())pSourceWSUnit = Kernel::Unit_sptr(another.pSourceWSUnit->clone()); + if(pTargetUnit.get()) pTargetUnit = Kernel::Unit_sptr(another.pSourceWSUnit->clone()); } } // endNamespace MDEvents diff --git a/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h b/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h index 0585465221e..99ed0529947 100644 --- a/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h +++ b/Code/Mantid/Framework/MDEvents/test/ConvertToMDEventsParamsTest.h @@ -69,40 +69,7 @@ void testGetWS4DimIDFine() } -//void testGetWS3DimIDFine() -//{ -// Mantid::API::MatrixWorkspace_sptr ws2D =WorkspaceCreationHelper::createProcessedWorkspaceWithCylComplexInstrument(4,10,true); -// API::NumericAxis *pAx = new API::NumericAxis(3); -// pAx->title() = "Dim1"; -// pAx->setUnit("dSpacing"); -// ws2D->replaceAxis(0,pAx); -// MDEvents::MDWSDescription TWS; -// -// -// std::vector<std::string> dim_units; -// std::string Alg_ID; -// ConvertToMDEventsParams params; -// std::vector<std::string> other_dim_names; -// -// TS_ASSERT_THROWS_NOTHING(Alg_ID=params.identifyMatrixAlg(ws2D,"Q3D","Elastic",dim_units, TWS)); -// -// TSM_ASSERT_EQUALS("Inelastic workspace will produce 3 dimensions",3,dim_units.size()); -// TSM_ASSERT_EQUALS("Last dimension of Elastic transformation should be ","Momentum",dim_units[2]); -// TSM_ASSERT_EQUALS("Alg ID would be: ","WS2DHistoQ3DCrystElasticCnvByTOF",Alg_ID); -// TS_ASSERT(!TWS.detInfoLost); -// -// TS_ASSERT_THROWS_NOTHING(params.buildMDDimDescription(ws2D,Alg_ID,other_dim_names,TWS)); -// TSM_ASSERT_EQUALS("elastic workspace will produce 3 dimensions",3,TWS.nDims); -// TS_ASSERT_EQUALS(TWS.dimIDs.size(),TWS.dimNames.size()); -// -// std::vector<std::string> dimID= TWS.getDefaultDimIDQ3D(0); -// for(size_t i=0;i<TWS.dimNames.size();i++) -// { -// TS_ASSERT_EQUALS(dimID[i],TWS.dimIDs[i]); -// TS_ASSERT_EQUALS(dimID[i],TWS.dimNames[i]); -// } -// -//} + //void testGetWSDimNames2AxisNoQ() //{ // Mantid::API::MatrixWorkspace_sptr ws2D =WorkspaceCreationHelper::Create2DWorkspace(4,10); -- GitLab