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"
18#include "MantidKernel/Unit.h"
19
20using namespace Mantid::Kernel;
21using namespace Mantid::API;
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, size_t> ConvertToDetectorFaceMD::getBanks() {
119 auto const &componentInfo = in_ws->componentInfo();
120
121 std::vector<int> bankNums = this->getProperty("BankNumbers");
122 std::sort(bankNums.begin(), bankNums.end());
123
124 std::map<int, size_t> banks;
125
126 if (bankNums.empty()) {
127 // --- Find all rectangular detectors ----
128 size_t const root = componentInfo.root();
129 auto const topChildren = componentInfo.children(root);
130 for (size_t const panel : topChildren) {
131 size_t parentIndex = componentInfo.findBankParent(panel, "bank");
132 auto const children = componentInfo.children(parentIndex);
133 for (size_t const child : children) {
134 if (componentInfo.isGridDetector(child)) {
135 std::string name = componentInfo.name(child);
136 std::string bankNumStr = name.substr(4, name.size() - 4);
137 int bankNum = -1;
138 if (Mantid::Kernel::Strings::convert(bankNumStr, bankNum)) {
139 banks[bankNum] = child;
140 }
141 }
142 }
143 }
144 } else {
145 // -- Find detectors using the numbers given ---
146 for (auto &bankNum : bankNums) {
147 std::string bankName = "bank" + Mantid::Kernel::Strings::toString(bankNum);
148 try {
149 const size_t bankIndex = componentInfo.indexOfAny(bankName);
150 if (componentInfo.isGridDetector(bankIndex)) {
151 banks[bankNum] = bankIndex;
152 }
153 } catch (std::invalid_argument &) {
154 // No such component; skip this bank number.
155 }
156 }
157 }
158
159 for (auto &bank : banks) {
160 const auto grid = componentInfo.pixelGridComponent(bank.second);
161 // Track the largest detector
162 if (grid.nX > m_numXPixels)
163 m_numXPixels = grid.nX;
164 if (grid.nY > m_numYPixels)
165 m_numYPixels = grid.nY;
166 }
167
168 if (banks.empty())
169 throw std::runtime_error("No RectangularDetectors with a name like "
170 "'bankXX' found in the instrument.");
171
172 return banks;
173}
174
175//----------------------------------------------------------------------------------------------
179 // TODO convert matrix to event as needed
180 MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace");
181
182 in_ws = std::dynamic_pointer_cast<EventWorkspace>(mws);
183 if (!in_ws)
184 throw std::runtime_error("InputWorkspace is not an EventWorkspace");
185
186 // Fill the map, throw if there are grouped pixels.
187 m_detID_to_WI = in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true);
188
189 // Get the map of the banks we'll display
190 std::map<int, size_t> banks = this->getBanks();
191
192 // Find the size in the TOF dimension
193 double tof_min, tof_max;
194 Axis *ax0 = in_ws->getAxis(0);
195 in_ws->getXMinMax(tof_min, tof_max);
196 if (ax0->getValue(0) < tof_min)
197 tof_min = ax0->getValue(0);
198 if (ax0->getValue(ax0->length() - 1) > tof_max)
199 tof_max = ax0->getValue(ax0->length() - 1);
200
201 // Get MDFrame of General Frame type
204
205 // ------------------ Build all the dimensions ----------------------------
206 MDHistoDimension_sptr dimX(new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0),
207 static_cast<coord_t>(m_numXPixels), m_numXPixels));
208 MDHistoDimension_sptr dimY(new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0),
209 static_cast<coord_t>(m_numYPixels), m_numYPixels));
210 std::string TOFname = ax0->title();
211 if (TOFname.empty())
212 TOFname = ax0->unit()->unitID();
213 MDHistoDimension_sptr dimTOF(new MDHistoDimension(TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min),
214 static_cast<coord_t>(tof_max), ax0->length()));
215
216 std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF};
217
218 if (banks.size() > 1) {
220 int min = banks.begin()->first;
221 int max = banks.rbegin()->first + 1;
222 MDHistoDimension_sptr dimBanks(new MDHistoDimension("bank", "bank", frameNumber, static_cast<coord_t>(min),
223 static_cast<coord_t>(max), max - min));
224 dims.emplace_back(dimBanks);
225 }
226
227 // --------- Create the workspace with the right number of dimensions
228 // ----------
229 size_t nd = dims.size();
231 outWS->initGeometry(dims);
232 outWS->initialize();
233 this->setBoxController(outWS->getBoxController(), mws->getInstrument());
234 outWS->splitBox();
235
236 MDEventWorkspace3::sptr outWS3 = std::dynamic_pointer_cast<MDEventWorkspace3>(outWS);
237 MDEventWorkspace4::sptr outWS4 = std::dynamic_pointer_cast<MDEventWorkspace4>(outWS);
238
239 // Copy ExperimentInfo (instrument, run, sample) to the output WS
240 ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo());
241 uint16_t expInfoIndex = outWS->addExperimentInfo(ei);
242 uint16_t goniometerIndex(0);
243 const auto &componentInfo = in_ws->componentInfo();
244 const auto &detectorInfo = in_ws->detectorInfo();
245 // ---------------- Convert each bank --------------------------------------
246 for (auto &bank : banks) {
247 int bankNum = bank.first;
248 const size_t bankIndex = bank.second;
249 const auto grid = componentInfo.pixelGridComponent(bankIndex);
250 for (int x = 0; x < grid.nX; x++)
251 for (int y = 0; y < grid.nY; y++) {
252 // Find the workspace index for this pixel coordinate
253 detid_t detID = detectorInfo.detid(componentInfo.detectorIndexAtXYZ(bankIndex, x, y, 0));
254 size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset];
255 if (wi >= in_ws->getNumberHistograms())
256 throw std::runtime_error("Invalid workspace index found in bank " + componentInfo.name(bankIndex) + "!");
257
258 auto xPos = static_cast<coord_t>(x);
259 auto yPos = static_cast<coord_t>(y);
260 auto bankPos = static_cast<coord_t>(bankNum);
261
262 EventList &el = in_ws->getSpectrum(wi);
263
264 // We want to bind to the right templated function, so we have to know
265 // the type of TofEvent contained in the EventList.
266 boost::function<void()> func;
267 switch (el.getEventType()) {
268 case TOF:
269 if (nd == 3)
270 this->convertEventList<TofEvent, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
271 goniometerIndex, detID);
272 else if (nd == 4)
273 this->convertEventList<TofEvent, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
274 goniometerIndex, detID);
275 break;
276 case WEIGHTED:
277 if (nd == 3)
278 this->convertEventList<WeightedEvent, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
279 goniometerIndex, detID);
280 else if (nd == 4)
281 this->convertEventList<WeightedEvent, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
282 goniometerIndex, detID);
283 break;
284 case WEIGHTED_NOTIME:
285 if (nd == 3)
286 this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
287 goniometerIndex, detID);
288 else if (nd == 4)
289 this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
290 goniometerIndex, detID);
291 break;
292 default:
293 throw std::runtime_error("EventList had an unexpected data type!");
294 }
295 }
296 }
297
298 // ---------------------- Perform all box splitting ---------------
300 ThreadPool tp(ts);
301 outWS->splitAllIfNeeded(ts);
302 tp.joinAll();
303 outWS->refreshCache();
304
305 // Save the output workspace
306 this->setProperty("OutputWorkspace", outWS);
307}
308
309} // namespace Mantid::MDAlgorithms
std::string name
Definition Run.cpp:60
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
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.
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:58
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.
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, size_t > getBanks()
Component indices of the rectangular bank for each requested bank number.
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< MDHistoDimension > MDHistoDimension_sptr
Shared pointer to a MDHistoDimension.
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