39using Mantid::Types::Event::TofEvent;
51 : ClearInputWorkspace(false),
52 OneEventPerBin(false),
54 LorentzCorrection(false),
55 l1(1.), beamline_norm(1.), failedDetectorLookupCount(0), m_extentsMin(
nullptr),
63 auto validator = std::make_shared<API::WorkspaceUnitValidator>(
"TOF");
66 "An input workspace in time-of-flight. If you specify a "
67 "Workspace2D, it gets converted to "
68 "an EventWorkspace using ConvertToEventWorkspace.");
71 "Name of the output MDEventWorkspace. If the workspace "
72 "already exists, then the events will be added to it.");
74 "Append events to the output workspace. The workspace is replaced if "
77 "Clear the events from the input workspace during "
78 "conversion, to save memory.");
81 "Use the histogram representation (event for event workspaces).\n"
82 "One MDEvent will be created for each histogram bin (even empty ones).\n"
83 "Warning! This can use significantly more memory!");
85 std::vector<std::string> propOptions{
"Q (lab frame)",
"Q (sample frame)",
"HKL"};
86 declareProperty(
"OutputDimensions",
"Q (lab frame)", std::make_shared<StringListValidator>(propOptions),
87 "What will be the dimensions of the output workspace?\n"
88 " Q (lab frame): Wave-vector change of the lattice in the lab frame.\n"
89 " Q (sample frame): Wave-vector change of the lattice in the frame of "
90 "the sample (taking out goniometer rotation).\n"
91 " HKL: Use the sample's UB matrix to convert to crystal's HKL indices.");
94 "Correct the weights of events by multiplying by the Lorentz "
95 "formula: sin(theta)^2 / lambda^4");
101 "Optional. If specified, then all the boxes will be split to this "
102 "minimum recursion depth. 1 = one level of splitting, etc.\n"
103 "Be careful using this since it can quickly create a huge number of "
104 ":math:`boxes = SplitInto^{MinRercursionDepth \\times NumDimensions}`.\n"
105 "But setting this property equal to MaxRecursionDepth property is "
106 "necessary if one wants to generate multiple file based workspaces in "
107 "order to merge them later\n");
110 std::vector<double> extents{-50, +50};
112 "A comma separated list of min, max for each dimension,\n"
113 "specifying the extents of each dimension. Optional, default "
114 "+-50 in each dimension.");
138 this->convertEventList<TofEvent>(workspaceIndex, specInfo, el);
141 this->convertEventList<WeightedEvent>(workspaceIndex, specInfo, el);
144 this->convertEventList<WeightedEventNoTime>(workspaceIndex, specInfo, el);
147 throw std::runtime_error(
"EventList had an unexpected data type!");
156 const auto &inSpec =
m_inWS->getSpectrum(workspaceIndex);
163 this->convertEventList<WeightedEventNoTime>(workspaceIndex, specInfo, el);
184 if (!detectors.empty()) {
193 double distance =
l1 + specInfo.
l2(workspaceIndex);
196 const V3D detPos = specInfo.
position(workspaceIndex);
199 const V3D detDir = detPos / detPos.
norm();
207 if (convention ==
"Crystallography")
209 Q_dir_lab_frame *= qSign;
214 const V3D Q_dir =
mat * Q_dir_lab_frame;
222 double sin_theta_squared = 0;
228 double theta = specInfo.
twoTheta(workspaceIndex) / 2.0;
229 sin_theta_squared = sin(theta);
230 sin_theta_squared = sin_theta_squared * sin_theta_squared;
236 const double wavenumber_in_angstrom_times_tof_in_microsec =
241 typename std::vector<T> *events_ptr;
243 typename std::vector<T> &events = *events_ptr;
246 auto it = events.begin();
247 auto it_end = events.end();
249 for (; it != it_end; it++) {
251 auto wavenumber =
coord_t(wavenumber_in_angstrom_times_tof_in_microsec / it->tof());
255 coord_t center[3] = {Q_dir_x * wavenumber, Q_dir_y * wavenumber, Q_dir_z * wavenumber};
268 auto correct = float(sin_theta_squared * wavenumber * wavenumber * wavenumber * wavenumber);
270 box->
addEvent(
MDE(
float(it->weight() * correct),
float(it->errorSquared() * correct * correct), center));
273 box->
addEvent(
MDE(
float(it->weight()),
float(it->errorSquared()), center));
308 g_log.
warning() <<
"Lorentz Correction was already done for this "
309 "workspace. LorentzCorrection was changed to false.\n";
317 if (
m_inWS->getAxis(0)->unit()->unitID() !=
"TOF")
318 throw std::invalid_argument(
"Input event workspace's X axis must be in TOF units.");
322 ws = std::dynamic_pointer_cast<DataObjects::MDEventWorkspace<DataObjects::MDLeanEvent<3>, 3>>(i_out);
330 std::string dimensionNames[3] = {
"Q_lab_x",
"Q_lab_y",
"Q_lab_z"};
337 if (OutputDimensions ==
"Q (sample frame)") {
339 mat =
m_inWS->mutableRun().getGoniometerMatrix();
343 dimensionNames[0] =
"Q_sample_x";
344 dimensionNames[1] =
"Q_sample_y";
345 dimensionNames[2] =
"Q_sample_z";
349 frame = frameFactory->create(frameArgQSample);
351 }
else if (OutputDimensions ==
"HKL") {
362 dimensionNames[0] =
"H";
363 dimensionNames[1] =
"K";
364 dimensionNames[2] =
"L";
367 frame = frameFactory->create(frameArgQLab);
370 frame = frameFactory->create(frameArgQLab);
377 if (
ws->getDimension(0)->getName() != dimensionNames[0])
378 throw std::runtime_error(
"The existing MDEventWorkspace " +
ws->getName() +
379 " has different dimensions than were requested! "
380 "Either give a different name for the output, "
381 "or change the OutputDimensions parameter.");
390 ws = std::dynamic_pointer_cast<DataObjects::MDEventWorkspace3Lean>(i_out);
393 std::vector<double> extents =
getProperty(
"Extents");
395 if (extents.size() == 2) {
396 for (
size_t d = 1;
d < nd;
d++) {
397 extents.emplace_back(extents[0]);
398 extents.emplace_back(extents[1]);
401 if (extents.size() != nd * 2)
402 throw std::invalid_argument(
"You must specify either 2 or 6 extents (min,max).");
405 for (
size_t d = 0;
d < nd;
d++) {
408 static_cast<coord_t>(extents[
d * 2 + 1]), 10);
421 int minDepth = this->
getProperty(
"MinRecursionDepth");
422 int maxDepth = this->
getProperty(
"MaxRecursionDepth");
423 if (minDepth > maxDepth)
424 throw std::invalid_argument(
"MinRecursionDepth must be <= MaxRecursionDepth ");
425 ws->setMinRecursionDepth(
size_t(minDepth));
431 throw std::runtime_error(
"Error creating a 3D MDEventWorkspace!");
435 throw std::runtime_error(
"Output MDEventWorkspace does not have a BoxController!");
440 for (
size_t d = 0;
d < 3;
d++) {
447 uint16_t expInfoIndex =
ws->addExperimentInfo(ei);
458 size_t totalEvents =
m_inWS->size();
461 prog = std::make_shared<Progress>(
this, 0.0, 1.0, totalEvents);
469 size_t eventsAdded = 0;
470 size_t approxEventsInOutput = 0;
471 size_t lastNumBoxes =
ws->getBoxController()->getTotalNumMDBoxes();
473 g_log.
information() << cputim <<
": initial setup. There are " << lastNumBoxes <<
" MDBoxes.\n";
475 const auto &specInfo =
m_inWS->spectrumInfo();
476 for (
size_t wi = 0; wi <
m_inWS->getNumberHistograms();) {
478 auto start =
static_cast<int>(wi);
479 for (; wi <
m_inWS->getNumberHistograms(); ++wi) {
481 size_t eventsAdding =
m_inWS->blocksize();
483 eventsAdding =
m_inEventWS->getSpectrum(wi).getNumberEvents();
486 eventsAdded += eventsAdding;
487 approxEventsInOutput += eventsAdding;
489 if (bc->shouldSplitBoxes(approxEventsInOutput, eventsAdded, lastNumBoxes))
495 for (
int i = start; i < static_cast<int>(wi); ++i) {
504 g_log.
information() << cputim <<
": Added tasks worth " << eventsAdded <<
" events. WorkspaceIndex " << wi
506 g_log.
information() << cputim <<
": Performing the addition of these events.\n";
509 ws->splitAllIfNeeded(ts);
511 prog->doReport(
"Splitting Boxes");
518 lastNumBoxes =
ws->getBoxController()->getTotalNumMDBoxes();
520 g_log.
information() << cputim <<
": Performing the splitting. There are now " << lastNumBoxes <<
" boxes.\n";
527 <<
" spectrum. It has been skipped.\n";
530 <<
" spectra. They have been skipped.\n";
538 g_log.
information() <<
"Workspace has " <<
ws->getNPoints() <<
" events. This took " << cputimtotal
540 std::vector<std::string> stats =
ws->getBoxControllerStats();
541 for (
auto &stat : stats)
547 ws->setCoordinateSystem(coordinateSystem);
550 setProperty(
"OutputWorkspace", std::dynamic_pointer_cast<IMDEventWorkspace>(
ws));
#define DECLARE_ALGORITHM(classname)
static std::unique_ptr< QThreadPool > tp
#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_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_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void setBoxController(const Mantid::API::BoxController_sptr &bc, const Mantid::Geometry::Instrument_const_sptr &instrument)
Set the settings in the given box controller.
void initBoxControllerProps(const std::string &SplitInto="5", int SplitThreshold=1000, int MaxRecursionDepth=5)
Initialise the properties.
std::string getBoxSettingsGroupName()
const std::set< detid_t > & getDetectorIDs() const
Get a const reference to the detector IDs set.
bool hasProperty(const std::string &name) const
Does the property exist on the object.
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
This class stores information regarding an experimental run as a series of log entries.
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
bool hasDetectors(const size_t index) const
Returns true if the spectrum is associated with detectors in the instrument.
double twoTheta(const size_t index) const
Returns the scattering angle 2 theta in radians (angle w.r.t.
Kernel::V3D position(const size_t index) const
Returns the position of the spectrum with given index.
double l2(const size_t index) const
Returns L2 (distance from sample to spectrum).
A property class for workspaces.
std::size_t getNumberEvents() const override
Return the number of events in the list.
Mantid::API::EventType getEventType() const override
Return the type of Event vector contained within.
void createFromHistogram(const ISpectrum *inSpec, bool GenerateZeros, bool GenerateMultipleEvents, int MaxEventsPerBin)
Create an EventList from a histogram.
void clear(const bool removeDetIDs=true) override
Clear the list of events and any associated detector ID's.
Templated super-class of a multi-dimensional event "box".
virtual size_t addEvent(const MDE &point)=0
Add a single event.
static API::IMDEventWorkspace_sptr CreateMDWorkspace(size_t nd, const std::string &eventType="MDLeanEvent", const Mantid::API::MDNormalization &preferredNormalization=Mantid::API::MDNormalization::VolumeNormalization, const Mantid::API::MDNormalization &preferredNormalizationHisto=Mantid::API::MDNormalization::VolumeNormalization)
Create a MDEventWorkspace of the given type.
Templated class holding data about a neutron detection event in N-dimensions (for example,...
static const std::string HKLName
Input argument type for MDFrameFactory chainable factory.
static const std::string QLabName
static const std::string QSampleName
Support for a property that holds an array of values.
CPUTimer : Timer that uses the CPU time, rather than wall-clock time to measure execution time.
void reset()
Explicitly reset the timer.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
T Invert()
LU inversion routine.
The concrete, templated class for properties.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
A Thread Pool implementation that keeps a certain number of threads running (normally,...
A First-In-First-Out Thread Scheduler.
The ThreadScheduler object defines how tasks are allocated to threads and in what order.
virtual size_t size()=0
Returns the size of the queue.
A simple class that provides a wall-clock (not processor time) timer.
static const UnitLabel RLU
Reciprocal lattice units.
constexpr double X() const noexcept
Get x.
constexpr double Y() const noexcept
Get y.
double norm() const noexcept
constexpr double Z() const noexcept
Get z.
ConvertToDiffractionMDWorkspace : Create a MDEventWorkspace with events in reciprocal space (Qx,...
DataObjects::EventWorkspace_sptr m_inEventWS
The input event workspace.
void exec() override
Execute the algorithm.
double beamline_norm
Path length between source and sample.
coord_t * m_extentsMax
Maximum extents of the workspace. Cached for speed.
Kernel::V3D beamline
Beam direction and length.
bool ClearInputWorkspace
Do we clear events on the input during loading?
Kernel::V3D beamDir
Beam direction (unit vector)
size_t failedDetectorLookupCount
Path length between source and sample.
API::MatrixWorkspace_sptr m_inWS
The input MatrixWorkspace.
Kernel::V3D samplePos
Sample position.
DataObjects::MDEventWorkspace3Lean::sptr ws
The output MDEventWorkspace<3>
bool Append
Are we appending?
void convertSpectrum(const API::SpectrumInfo &specInfo, int workspaceIndex)
Convert one spectrum to DataObjects.
double l1
Primary flight path (source to sample)
Kernel::Matrix< double > mat
Matrix.
bool LorentzCorrection
Perform LorentzCorrection on the fly.
void convertEventList(int workspaceIndex, const API::SpectrumInfo &specInfo, DataObjects::EventList &el)
Convert an event list to 3D q-space and add it to the MDEventWorkspace.
std::shared_ptr< Kernel::ProgressBase > prog
Progress reporter (shared)
coord_t * m_extentsMin
Minimum extents of the workspace. Cached for speed.
void init() override
Initialize the algorithm's properties.
bool OneEventPerBin
Use the histogram representation with one event per bin.
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< BoxController > BoxController_sptr
Shared ptr to BoxController.
std::size_t numEvents(::NeXus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix, const NexusHDF5Descriptor &descriptor)
Get the number of events in the currently opened group.
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
std::unique_ptr< MDFrame > MDFrame_uptr
MDFrameFactory_uptr MANTID_GEOMETRY_DLL makeMDFrameFactoryChain()
Make a complete factory chain.
std::shared_ptr< MDHistoDimension > MDHistoDimension_sptr
Shared pointer to a MDHistoDimension.
SpecialCoordinateSystem
Special coordinate systems for Q3D.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
DataObjects::MDLeanEvent< 3 > MDE
Our MDLeanEvent dimension.
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h_bar
Planck constant in J*s, divided by 2 PI.
Helper class which provides the Collimation Length for SANS instruments.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
@ Input
An input workspace.
@ Output
An output workspace.