Mantid
Loading...
Searching...
No Matches
ConvertToDetectorFaceMD.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8#include "MantidAPI/Axis.h"
17#include "MantidKernel/Unit.h"
18
19using namespace Mantid::Kernel;
20using namespace Mantid::API;
21using namespace Mantid::DataObjects;
22using namespace Mantid::DataObjects;
23using namespace Mantid::Geometry;
24using Mantid::Types::Event::TofEvent;
25
26namespace Mantid::MDAlgorithms {
27
28// Register the algorithm into the AlgorithmFactory
29DECLARE_ALGORITHM(ConvertToDetectorFaceMD)
30
31//----------------------------------------------------------------------------------------------
33const std::string ConvertToDetectorFaceMD::name() const { return "ConvertToDetectorFaceMD"; }
34
36int ConvertToDetectorFaceMD::version() const { return 1; }
37
39const std::string ConvertToDetectorFaceMD::category() const { return "MDAlgorithms\\Creation"; }
40
41//----------------------------------------------------------------------------------------------
42
43//----------------------------------------------------------------------------------------------
47 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input),
48 "An input MatrixWorkspace.");
49 declareProperty(std::make_unique<ArrayProperty<int>>("BankNumbers", Direction::Input),
50 "A list of the bank numbers to convert. If empty, will use "
51 "all banksMust have at least one entry.");
52
53 // Now the box controller settings
54 this->initBoxControllerProps("2", 200, 20);
55
56 declareProperty(std::make_unique<WorkspaceProperty<IMDEventWorkspace>>("OutputWorkspace", "", Direction::Output),
57 "Name of the output MDEventWorkspace.");
58}
59
60//----------------------------------------------------------------------------------------------
74template <class T, class MDE, size_t nd>
76 size_t workspaceIndex, coord_t x, coord_t y, coord_t bankNum,
77 uint16_t expInfoIndex, uint16_t goniometerIndex, int32_t detectorID) {
78
79 EventList &el = in_ws->getSpectrum(workspaceIndex);
80
81 // The 3/4D DataObjects that will be added into the MDEventWorkspce
82 std::vector<MDE> out_events;
83 out_events.reserve(el.getNumberEvents());
84
85 // This little dance makes the getting vector of events more general (since
86 // you can't overload by return type).
87 typename std::vector<T> *events_ptr;
88 getEventsFrom(el, events_ptr);
89 typename std::vector<T> &events = *events_ptr;
90
91 // Iterators to start/end
92 auto it = events.begin();
93 auto it_end = events.end();
94
95 for (; it != it_end; it++) {
96 auto tof = static_cast<coord_t>(it->tof());
97 if (nd == 3) {
98 coord_t center[3] = {x, y, tof};
99 out_events.emplace_back(float(it->weight()), float(it->errorSquared()), expInfoIndex, goniometerIndex, detectorID,
100 center);
101 } else if (nd == 4) {
102 coord_t center[4] = {x, y, tof, bankNum};
103 out_events.emplace_back(static_cast<float>(it->weight()), static_cast<float>(it->errorSquared()), expInfoIndex,
104 detectorID, goniometerIndex, center);
105 }
106 }
107
108 // Add them to the MDEW
109 outWS->addEvents(out_events);
110}
111
112//----------------------------------------------------------------------------------------------
118std::map<int, RectangularDetector_const_sptr> ConvertToDetectorFaceMD::getBanks() {
119 Instrument_const_sptr inst = in_ws->getInstrument();
120
121 std::vector<int> bankNums = this->getProperty("BankNumbers");
122 std::sort(bankNums.begin(), bankNums.end());
123
124 std::map<int, RectangularDetector_const_sptr> banks;
125
126 if (bankNums.empty()) {
127 // --- Find all rectangular detectors ----
128 // Get all children
129 std::vector<IComponent_const_sptr> comps;
130 inst->getChildren(comps, true);
131
132 for (auto &comp : comps) {
133 // Retrieve it
134 RectangularDetector_const_sptr det = std::dynamic_pointer_cast<const RectangularDetector>(comp);
135 if (det) {
136 std::string name = det->getName();
137 if (name.size() < 5)
138 continue;
139 std::string bank = name.substr(4, name.size() - 4);
140 int bankNum;
141 if (Mantid::Kernel::Strings::convert(bank, bankNum))
142 banks[bankNum] = det;
143 g_log.debug() << "Found bank " << bank << ".\n";
144 }
145 }
146 } else {
147 // -- Find detectors using the numbers given ---
148 for (auto &bankNum : bankNums) {
149 std::string bankName = "bank" + Mantid::Kernel::Strings::toString(bankNum);
150 IComponent_const_sptr comp = inst->getComponentByName(bankName);
151 RectangularDetector_const_sptr det = std::dynamic_pointer_cast<const RectangularDetector>(comp);
152 if (det)
153 banks[bankNum] = det;
154 }
155 }
156
157 for (auto &bank : banks) {
158 RectangularDetector_const_sptr det = bank.second;
159 // Track the largest detector
160 if (det->xpixels() > m_numXPixels)
161 m_numXPixels = det->xpixels();
162 if (det->ypixels() > m_numYPixels)
163 m_numYPixels = det->ypixels();
164 }
165
166 if (banks.empty())
167 throw std::runtime_error("No RectangularDetectors with a name like "
168 "'bankXX' found in the instrument.");
169
170 return banks;
171}
172
173//----------------------------------------------------------------------------------------------
177 // TODO convert matrix to event as needed
178 MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace");
179
180 in_ws = std::dynamic_pointer_cast<EventWorkspace>(mws);
181 if (!in_ws)
182 throw std::runtime_error("InputWorkspace is not an EventWorkspace");
183
184 // Fill the map, throw if there are grouped pixels.
185 m_detID_to_WI = in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true);
186
187 // Get the map of the banks we'll display
188 std::map<int, RectangularDetector_const_sptr> banks = this->getBanks();
189
190 // Find the size in the TOF dimension
191 double tof_min, tof_max;
192 Axis *ax0 = in_ws->getAxis(0);
193 in_ws->getXMinMax(tof_min, tof_max);
194 if (ax0->getValue(0) < tof_min)
195 tof_min = ax0->getValue(0);
196 if (ax0->getValue(ax0->length() - 1) > tof_max)
197 tof_max = ax0->getValue(ax0->length() - 1);
198
199 // Get MDFrame of General Frame type
202
203 // ------------------ Build all the dimensions ----------------------------
204 MDHistoDimension_sptr dimX(new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0),
205 static_cast<coord_t>(m_numXPixels), m_numXPixels));
206 MDHistoDimension_sptr dimY(new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0),
207 static_cast<coord_t>(m_numYPixels), m_numYPixels));
208 std::string TOFname = ax0->title();
209 if (TOFname.empty())
210 TOFname = ax0->unit()->unitID();
211 MDHistoDimension_sptr dimTOF(new MDHistoDimension(TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min),
212 static_cast<coord_t>(tof_max), ax0->length()));
213
214 std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF};
215
216 if (banks.size() > 1) {
218 int min = banks.begin()->first;
219 int max = banks.rbegin()->first + 1;
220 MDHistoDimension_sptr dimBanks(new MDHistoDimension("bank", "bank", frameNumber, static_cast<coord_t>(min),
221 static_cast<coord_t>(max), max - min));
222 dims.emplace_back(dimBanks);
223 }
224
225 // --------- Create the workspace with the right number of dimensions
226 // ----------
227 size_t nd = dims.size();
229 outWS->initGeometry(dims);
230 outWS->initialize();
231 this->setBoxController(outWS->getBoxController(), mws->getInstrument());
232 outWS->splitBox();
233
234 MDEventWorkspace3::sptr outWS3 = std::dynamic_pointer_cast<MDEventWorkspace3>(outWS);
235 MDEventWorkspace4::sptr outWS4 = std::dynamic_pointer_cast<MDEventWorkspace4>(outWS);
236
237 // Copy ExperimentInfo (instrument, run, sample) to the output WS
238 ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo());
239 uint16_t expInfoIndex = outWS->addExperimentInfo(ei);
240 uint16_t goniometerIndex(0);
241 // ---------------- Convert each bank --------------------------------------
242 for (auto &bank : banks) {
243 int bankNum = bank.first;
244 RectangularDetector_const_sptr det = bank.second;
245 for (int x = 0; x < det->xpixels(); x++)
246 for (int y = 0; y < det->ypixels(); y++) {
247 // Find the workspace index for this pixel coordinate
248 detid_t detID = det->getDetectorIDAtXY(x, y);
249 size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset];
250 if (wi >= in_ws->getNumberHistograms())
251 throw std::runtime_error("Invalid workspace index found in bank " + det->getName() + "!");
252
253 auto xPos = static_cast<coord_t>(x);
254 auto yPos = static_cast<coord_t>(y);
255 auto bankPos = static_cast<coord_t>(bankNum);
256
257 EventList &el = in_ws->getSpectrum(wi);
258
259 // We want to bind to the right templated function, so we have to know
260 // the type of TofEvent contained in the EventList.
261 boost::function<void()> func;
262 switch (el.getEventType()) {
263 case TOF:
264 if (nd == 3)
265 this->convertEventList<TofEvent, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
266 goniometerIndex, detID);
267 else if (nd == 4)
268 this->convertEventList<TofEvent, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
269 goniometerIndex, detID);
270 break;
271 case WEIGHTED:
272 if (nd == 3)
273 this->convertEventList<WeightedEvent, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
274 goniometerIndex, detID);
275 else if (nd == 4)
276 this->convertEventList<WeightedEvent, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
277 goniometerIndex, detID);
278 break;
279 case WEIGHTED_NOTIME:
280 if (nd == 3)
281 this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
282 goniometerIndex, detID);
283 else if (nd == 4)
284 this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
285 goniometerIndex, detID);
286 break;
287 default:
288 throw std::runtime_error("EventList had an unexpected data type!");
289 }
290 }
291 }
292
293 // ---------------------- Perform all box splitting ---------------
295 ThreadPool tp(ts);
296 outWS->splitAllIfNeeded(ts);
297 tp.joinAll();
298 outWS->refreshCache();
299
300 // Save the output workspace
301 this->setProperty("OutputWorkspace", outWS);
302}
303
304} // namespace Mantid::MDAlgorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
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.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
Class to represent the axis of a workspace.
Definition Axis.h:30
const std::string & title() const
Returns the user-defined title for this axis.
Definition Axis.cpp:20
virtual std::size_t length() const =0
Get the length of the axis.
const std::shared_ptr< Kernel::Unit > & unit() const
The unit for this axis.
Definition Axis.cpp:28
double getValue(const std::size_t &index, const std::size_t &verticalIndex=0) const
Gets the value at the specified index.
Definition Axis.cpp:51
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.
A property class for workspaces.
A class for holding :
Definition EventList.h:57
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 reserve(size_t num) override
Reserve a certain number of entries in event list of the specified eventType.
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 for the multi-dimensional event workspace.
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
GeneralFrame : Any MDFrame that isn't related to momemtum transfer.
static const std::string GeneralFrameName
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
A Thread Pool implementation that keeps a certain number of threads running (normally,...
Definition ThreadPool.h:36
A Largest Cost Thread Scheduler.
The ThreadScheduler object defines how tasks are allocated to threads and in what order.
Convert a MatrixWorkspace containing to a MD workspace for viewing the detector face.
Mantid::DataObjects::EventWorkspace_sptr in_ws
The input event workspace.
const std::string name() const override
Algorithm's name for identification.
int m_numYPixels
Height in pixels of the widest detector.
void convertEventList(std::shared_ptr< Mantid::DataObjects::MDEventWorkspace< MDE, nd > > outWS, size_t workspaceIndex, coord_t x, coord_t y, coord_t bankNum, uint16_t expInfoIndex, uint16_t goniometerIndex, int32_t detectorID)
Convert an event list to 3/4D detector face space add it to the MDEventWorkspace.
int m_numXPixels
Width in pixels of the widest detector.
void init() override
Initialize the algorithm's properties.
std::map< int, Geometry::RectangularDetector_const_sptr > getBanks()
Get the list of banks, given the settings.
const std::string category() const override
Algorithm's category for identification.
int version() const override
Algorithm's version for identification.
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< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
DLLExport void getEventsFrom(EventList &el, std::vector< Types::Event::TofEvent > *&events)
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:167
std::shared_ptr< const RectangularDetector > RectangularDetector_const_sptr
std::shared_ptr< MDHistoDimension > MDHistoDimension_sptr
Shared pointer to a MDHistoDimension.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition Strings.cpp:696
std::string toString(const T &value)
Convert a number to a string.
Definition Strings.cpp:734
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition MDTypes.h:27
int32_t detid_t
Typedef for a detector ID.
STL namespace.
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54