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/System.h"
18#include "MantidKernel/Unit.h"
19
20using namespace Mantid::Kernel;
21using namespace Mantid::API;
22using namespace Mantid::DataObjects;
23using namespace Mantid::DataObjects;
24using namespace Mantid::Geometry;
25using Mantid::Types::Event::TofEvent;
26
27namespace Mantid::MDAlgorithms {
28
29// Register the algorithm into the AlgorithmFactory
30DECLARE_ALGORITHM(ConvertToDetectorFaceMD)
31
32//----------------------------------------------------------------------------------------------
34const std::string ConvertToDetectorFaceMD::name() const { return "ConvertToDetectorFaceMD"; }
35
37int ConvertToDetectorFaceMD::version() const { return 1; }
38
40const std::string ConvertToDetectorFaceMD::category() const { return "MDAlgorithms\\Creation"; }
41
42//----------------------------------------------------------------------------------------------
43
44//----------------------------------------------------------------------------------------------
48 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input),
49 "An input MatrixWorkspace.");
50 declareProperty(std::make_unique<ArrayProperty<int>>("BankNumbers", Direction::Input),
51 "A list of the bank numbers to convert. If empty, will use "
52 "all banksMust have at least one entry.");
53
54 // Now the box controller settings
55 this->initBoxControllerProps("2", 200, 20);
56
57 declareProperty(std::make_unique<WorkspaceProperty<IMDEventWorkspace>>("OutputWorkspace", "", Direction::Output),
58 "Name of the output MDEventWorkspace.");
59}
60
61//----------------------------------------------------------------------------------------------
75template <class T, class MDE, size_t nd>
77 size_t workspaceIndex, coord_t x, coord_t y, coord_t bankNum,
78 uint16_t expInfoIndex, uint16_t goniometerIndex, int32_t detectorID) {
79
80 EventList &el = in_ws->getSpectrum(workspaceIndex);
81
82 // The 3/4D DataObjects that will be added into the MDEventWorkspce
83 std::vector<MDE> out_events;
84 out_events.reserve(el.getNumberEvents());
85
86 // This little dance makes the getting vector of events more general (since
87 // you can't overload by return type).
88 typename std::vector<T> *events_ptr;
89 getEventsFrom(el, events_ptr);
90 typename std::vector<T> &events = *events_ptr;
91
92 // Iterators to start/end
93 auto it = events.begin();
94 auto it_end = events.end();
95
96 for (; it != it_end; it++) {
97 auto tof = static_cast<coord_t>(it->tof());
98 if (nd == 3) {
99 coord_t center[3] = {x, y, tof};
100 out_events.emplace_back(float(it->weight()), float(it->errorSquared()), expInfoIndex, goniometerIndex, detectorID,
101 center);
102 } else if (nd == 4) {
103 coord_t center[4] = {x, y, tof, bankNum};
104 out_events.emplace_back(static_cast<float>(it->weight()), static_cast<float>(it->errorSquared()), expInfoIndex,
105 detectorID, goniometerIndex, center);
106 }
107 }
108
109 // Add them to the MDEW
110 outWS->addEvents(out_events);
111}
112
113//----------------------------------------------------------------------------------------------
119std::map<int, RectangularDetector_const_sptr> ConvertToDetectorFaceMD::getBanks() {
120 Instrument_const_sptr inst = in_ws->getInstrument();
121
122 std::vector<int> bankNums = this->getProperty("BankNumbers");
123 std::sort(bankNums.begin(), bankNums.end());
124
125 std::map<int, RectangularDetector_const_sptr> banks;
126
127 if (bankNums.empty()) {
128 // --- Find all rectangular detectors ----
129 // Get all children
130 std::vector<IComponent_const_sptr> comps;
131 inst->getChildren(comps, true);
132
133 for (auto &comp : comps) {
134 // Retrieve it
135 RectangularDetector_const_sptr det = std::dynamic_pointer_cast<const RectangularDetector>(comp);
136 if (det) {
137 std::string name = det->getName();
138 if (name.size() < 5)
139 continue;
140 std::string bank = name.substr(4, name.size() - 4);
141 int bankNum;
142 if (Mantid::Kernel::Strings::convert(bank, bankNum))
143 banks[bankNum] = det;
144 g_log.debug() << "Found bank " << bank << ".\n";
145 }
146 }
147 } else {
148 // -- Find detectors using the numbers given ---
149 for (auto &bankNum : bankNums) {
150 std::string bankName = "bank" + Mantid::Kernel::Strings::toString(bankNum);
151 IComponent_const_sptr comp = inst->getComponentByName(bankName);
152 RectangularDetector_const_sptr det = std::dynamic_pointer_cast<const RectangularDetector>(comp);
153 if (det)
154 banks[bankNum] = det;
155 }
156 }
157
158 for (auto &bank : banks) {
159 RectangularDetector_const_sptr det = bank.second;
160 // Track the largest detector
161 if (det->xpixels() > m_numXPixels)
162 m_numXPixels = det->xpixels();
163 if (det->ypixels() > m_numYPixels)
164 m_numYPixels = det->ypixels();
165 }
166
167 if (banks.empty())
168 throw std::runtime_error("No RectangularDetectors with a name like "
169 "'bankXX' found in the instrument.");
170
171 return banks;
172}
173
174//----------------------------------------------------------------------------------------------
178 // TODO convert matrix to event as needed
179 MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace");
180
181 in_ws = std::dynamic_pointer_cast<EventWorkspace>(mws);
182 if (!in_ws)
183 throw std::runtime_error("InputWorkspace is not an EventWorkspace");
184
185 // Fill the map, throw if there are grouped pixels.
186 m_detID_to_WI = in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true);
187
188 // Get the map of the banks we'll display
189 std::map<int, RectangularDetector_const_sptr> banks = this->getBanks();
190
191 // Find the size in the TOF dimension
192 double tof_min, tof_max;
193 Axis *ax0 = in_ws->getAxis(0);
194 in_ws->getXMinMax(tof_min, tof_max);
195 if (ax0->getValue(0) < tof_min)
196 tof_min = ax0->getValue(0);
197 if (ax0->getValue(ax0->length() - 1) > tof_max)
198 tof_max = ax0->getValue(ax0->length() - 1);
199
200 // Get MDFrame of General Frame type
203
204 // ------------------ Build all the dimensions ----------------------------
205 MDHistoDimension_sptr dimX(new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0),
206 static_cast<coord_t>(m_numXPixels), m_numXPixels));
207 MDHistoDimension_sptr dimY(new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0),
208 static_cast<coord_t>(m_numYPixels), m_numYPixels));
209 std::string TOFname = ax0->title();
210 if (TOFname.empty())
211 TOFname = ax0->unit()->unitID();
212 MDHistoDimension_sptr dimTOF(new MDHistoDimension(TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min),
213 static_cast<coord_t>(tof_max), ax0->length()));
214
215 std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF};
216
217 if (banks.size() > 1) {
219 int min = banks.begin()->first;
220 int max = banks.rbegin()->first + 1;
221 MDHistoDimension_sptr dimBanks(new MDHistoDimension("bank", "bank", frameNumber, static_cast<coord_t>(min),
222 static_cast<coord_t>(max), max - min));
223 dims.emplace_back(dimBanks);
224 }
225
226 // --------- Create the workspace with the right number of dimensions
227 // ----------
228 size_t nd = dims.size();
230 outWS->initGeometry(dims);
231 outWS->initialize();
232 this->setBoxController(outWS->getBoxController(), mws->getInstrument());
233 outWS->splitBox();
234
235 MDEventWorkspace3::sptr outWS3 = std::dynamic_pointer_cast<MDEventWorkspace3>(outWS);
236 MDEventWorkspace4::sptr outWS4 = std::dynamic_pointer_cast<MDEventWorkspace4>(outWS);
237
238 // Copy ExperimentInfo (instrument, run, sample) to the output WS
239 ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo());
240 uint16_t expInfoIndex = outWS->addExperimentInfo(ei);
241 uint16_t goniometerIndex(0);
242 // ---------------- Convert each bank --------------------------------------
243 for (auto &bank : banks) {
244 int bankNum = bank.first;
245 RectangularDetector_const_sptr det = bank.second;
246 for (int x = 0; x < det->xpixels(); x++)
247 for (int y = 0; y < det->ypixels(); y++) {
248 // Find the workspace index for this pixel coordinate
249 detid_t detID = det->getDetectorIDAtXY(x, y);
250 size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset];
251 if (wi >= in_ws->getNumberHistograms())
252 throw std::runtime_error("Invalid workspace index found in bank " + det->getName() + "!");
253
254 auto xPos = static_cast<coord_t>(x);
255 auto yPos = static_cast<coord_t>(y);
256 auto bankPos = static_cast<coord_t>(bankNum);
257
258 EventList &el = in_ws->getSpectrum(wi);
259
260 // We want to bind to the right templated function, so we have to know
261 // the type of TofEvent contained in the EventList.
262 boost::function<void()> func;
263 switch (el.getEventType()) {
264 case TOF:
265 if (nd == 3)
266 this->convertEventList<TofEvent, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
267 goniometerIndex, detID);
268 else if (nd == 4)
269 this->convertEventList<TofEvent, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
270 goniometerIndex, detID);
271 break;
272 case WEIGHTED:
273 if (nd == 3)
274 this->convertEventList<WeightedEvent, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
275 goniometerIndex, detID);
276 else if (nd == 4)
277 this->convertEventList<WeightedEvent, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
278 goniometerIndex, detID);
279 break;
280 case WEIGHTED_NOTIME:
281 if (nd == 3)
282 this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>(outWS3, wi, xPos, yPos, bankPos, expInfoIndex,
283 goniometerIndex, detID);
284 else if (nd == 4)
285 this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>(outWS4, wi, xPos, yPos, bankPos, expInfoIndex,
286 goniometerIndex, detID);
287 break;
288 default:
289 throw std::runtime_error("EventList had an unexpected data type!");
290 }
291 }
292 }
293
294 // ---------------------- Perform all box splitting ---------------
296 ThreadPool tp(ts);
297 outWS->splitAllIfNeeded(ts);
298 tp.joinAll();
299 outWS->refreshCache();
300
301 // Save the output workspace
302 this->setProperty("OutputWorkspace", outWS);
303}
304
305} // namespace Mantid::MDAlgorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
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.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
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:56
std::size_t getNumberEvents() const override
Return the number of events in the list.
Definition: EventList.cpp:1143
Mantid::API::EventType getEventType() const override
Return the type of Event vector contained within.
Definition: EventList.cpp:643
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.
Definition: GeneralFrame.h:21
static const std::string GeneralFrameName
Definition: GeneralFrame.h:25
Support for a property that holds an array of values.
Definition: ArrayProperty.h:28
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:114
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.
@ WEIGHTED_NOTIME
Definition: IEventList.h:18
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:161
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:665
std::string toString(const T &value)
Convert a number to a string.
Definition: Strings.cpp:703
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.
Definition: SpectrumInfo.h:21
STL namespace.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54