Mantid
Loading...
Searching...
No Matches
SingleCrystalDiffractionTestHelper.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 +
7/* Test functions for algorithms for single crystal diffraction
8 */
9
12#include "MantidAPI/Axis.h"
13#include "MantidAPI/Run.h"
14#include "MantidAPI/Sample.h"
19#include "MantidKernel/V3D.h"
21
22#include <cmath>
23#include <random>
24#include <tuple>
25
26using namespace Mantid;
27using namespace Mantid::API;
28using namespace Mantid::DataObjects;
30using namespace Mantid::Geometry;
32using namespace Mantid::Kernel;
33using Mantid::Types::Event::TofEvent;
34
36
37void WorkspaceBuilder::setNumPixels(const int numPixels) {
38 m_numPixels = numPixels;
39 m_totalNPixels = numPixels * numPixels;
40}
41
55void WorkspaceBuilder::addPeakByHKL(const V3D &hkl, const int numEvents,
56 const std::tuple<double, double, double> &sigmas) {
57 m_peakDescriptors.emplace_back(hkl, numEvents, sigmas);
58}
59
71std::tuple<MatrixWorkspace_sptr, PeaksWorkspace_sptr> WorkspaceBuilder::build() {
77
80
81 return std::make_tuple(m_workspace, m_peaksWorkspace);
82}
83
92 1 /*num_banks*/, m_numPixels /*pixels in each direction yields n by n*/, 0.01, 1.0);
93}
94
102 // Create a peaks workspace
103 m_peaksWorkspace = std::make_shared<PeaksWorkspace>();
104 // Set the instrument to be the fake rectangular bank above.
105 m_peaksWorkspace->setInstrument(m_instrument);
106 // Set the oriented lattice for a cubic crystal
107 auto lattice = std::make_unique<OrientedLattice>(6, 6, 6, 90, 90, 90);
108 lattice->setUFromVectors(V3D(6, 0, 0), V3D(0, 6, 0));
109 m_peaksWorkspace->mutableSample().setOrientedLattice(std::move(lattice));
110}
111
117 // Make an event workspace and add fake peak data
118 m_eventWorkspace = std::make_shared<EventWorkspace>();
119 m_eventWorkspace->setInstrument(m_instrument);
120 m_eventWorkspace->initialize(m_totalNPixels /*n spectra*/, 3 /* x-size */, 3 /* y-size */);
121 m_eventWorkspace->getAxis(0)->setUnit("TOF");
122 // Give the spectra-detector mapping for all event lists
123 for (int i = 0; i < m_totalNPixels; ++i) {
124 EventList &el = m_eventWorkspace->getSpectrum(i);
126 }
127
128 // set the output workspace to be the event workspace
129 // this may or may not be converted later to a histogram
131}
132
136 int index = 0;
137 for (const auto &descriptor : m_peakDescriptors) {
138 createPeak(descriptor);
139 if (m_useBackground)
141 ++index;
142 }
143}
144
157 const auto hkl = std::get<0>(descriptor);
158 const auto nEvents = std::get<1>(descriptor);
159 const auto sigmas = std::get<2>(descriptor);
160
161 // Create the peak and add it to the peaks ws
162 auto ipeak = m_peaksWorkspace->createPeakHKL(hkl);
163 Peak_uptr peak(dynamic_cast<Peak *>(ipeak.release()));
164 m_peaksWorkspace->addPeak(*peak);
165
166 // Get detector ID and TOF position of peak
167 const auto detectorId = peak->getDetectorID();
168 const auto tofExact = peak->getTOF();
169 const auto &info = m_eventWorkspace->detectorInfo();
170 const auto detPos = info.position(info.indexOf(detectorId));
171
172 const auto xSigma = std::get<0>(sigmas);
173 const auto ySigma = std::get<1>(sigmas);
174 const auto tofSigma = std::get<2>(sigmas);
175
176 // distributions for beam divergence and TOF broadening
177 Kernel::normal_distribution<> xDist(0, xSigma);
178 Kernel::normal_distribution<> yDist(0, ySigma);
179 Kernel::normal_distribution<> tofDist(tofExact, tofSigma);
180
181 // add events to the workspace
182 for (int i = 0; i < nEvents; ++i) {
183 const auto xOffset = xDist(m_generator);
184 const auto yOffset = yDist(m_generator);
185 const auto tof = tofDist(m_generator);
186
187 const auto pos = V3D(detPos[0] + xOffset, detPos[1] + yOffset, detPos[2]);
188 const auto result = m_detectorSearcher->findNearest(Eigen::Vector3d(pos[0], pos[1], pos[2]));
189 const auto index = std::get<1>(result[0]);
190 auto &el = m_eventWorkspace->getSpectrum(index);
191 el.addEventQuickly(TofEvent(tof));
192 }
193}
194
203void WorkspaceBuilder::createBackground(const int peakIndex) {
204 const auto &peak = m_peaksWorkspace->getPeak(peakIndex);
205 const auto detectorId = peak.getDetectorID();
206 const auto tofExact = peak.getTOF();
207 const auto &info = m_eventWorkspace->detectorInfo();
208 const auto detPos = info.position(info.indexOf(detectorId));
209
210 const auto nBackgroundEvents = std::get<0>(m_backgroundParameters);
211 const auto backgroundDetSize = std::get<1>(m_backgroundParameters);
212 const auto backgroundTOFSize = std::get<2>(m_backgroundParameters);
213
214 std::uniform_real_distribution<> backgroundXDist(-backgroundDetSize, backgroundDetSize);
215 std::uniform_real_distribution<> backgroundYDist(-backgroundDetSize, backgroundDetSize);
216 std::uniform_real_distribution<> backgroundTOFDist(tofExact - backgroundTOFSize, tofExact + backgroundTOFSize);
217
218 for (int i = 0; i < nBackgroundEvents; ++i) {
219 const auto xOffset = backgroundXDist(m_generator);
220 const auto yOffset = backgroundYDist(m_generator);
221 const auto tof = backgroundTOFDist(m_generator);
222
223 const auto pos = V3D(detPos[0] + xOffset, detPos[1] + yOffset, detPos[2]);
224 const auto result = m_detectorSearcher->findNearest(Eigen::Vector3d(pos[0], pos[1], pos[2]));
225 const auto index = std::get<1>(result[0]);
226
227 auto &el = m_eventWorkspace->getSpectrum(index);
228 el.addEventQuickly(TofEvent(tof));
229 }
230}
231
236 const auto &info = m_eventWorkspace->detectorInfo();
237 std::vector<Eigen::Vector3d> points;
238 for (size_t i = 0; i < info.size(); ++i) {
239 const auto pos = info.position(i);
240 points.emplace_back(pos[0], pos[1], pos[2]);
241 }
242 m_detectorSearcher = std::make_unique<NearestNeighbours<3>>(points);
243}
244
248 auto rebinAlg = AlgorithmManager::Instance().createUnmanaged("Rebin");
249 rebinAlg->setChild(true);
250 rebinAlg->initialize();
251 rebinAlg->setProperty("InputWorkspace", m_eventWorkspace);
252 rebinAlg->setProperty("Params", m_rebinParams);
253 rebinAlg->setProperty("PreserveEvents", false); // Make a histo workspace
254 rebinAlg->setPropertyValue("OutputWorkspace", "__SXD_test_helper_rebin");
255 rebinAlg->execute();
256 m_workspace = rebinAlg->getProperty("OutputWorkspace");
257}
258} // namespace Mantid::SingleCrystalDiffractionTestHelper
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
void setDetectorID(const detid_t detID)
Clear the list of detector IDs, then add one.
Definition: ISpectrum.cpp:84
A class for holding :
Definition: EventList.h:56
Structure describing a single-crystal peak.
Definition: Peak.h:34
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Class for 3D vectors.
Definition: V3D.h:34
void rebinWorkspace()
Rebin the event workspace to a histogram workspace.
Mantid::API::MatrixWorkspace_sptr m_workspace
Handle to the final output workspace (event OR histogram)
std::tuple< Mantid::API::MatrixWorkspace_sptr, Mantid::DataObjects::PeaksWorkspace_sptr > build()
Make a tuple of event workspace and peaks workspace.
std::tuple< int, double, double > m_backgroundParameters
background parameters
std::unique_ptr< Mantid::Kernel::NearestNeighbours< 3 > > m_detectorSearcher
Nearest neighbour search tree for detectors.
void createBackground(const int peakIndex)
Create a flat background for the workspace.
void createEventWorkspace()
Create an empty event workspace with the instrument attached.
int m_numPixels
number of pixels along a single axis on the detector bank
void addPeakByHKL(const Mantid::Kernel::V3D &hkl, const int numEvents, const std::tuple< double, double, double > &sigmas)
Add a HKL peak to the diffraction dataset.
Mantid::DataObjects::PeaksWorkspace_sptr m_peaksWorkspace
Handle to the peaks workspace.
void createNeighbourSearch()
Create a neighbour search tree for finding nearest neighbours.
std::vector< HKLPeakDescriptor > m_peakDescriptors
List of peak descriptors for creating peaks.
Mantid::DataObjects::EventWorkspace_sptr m_eventWorkspace
Handle to the event workspace.
std::tuple< Mantid::Kernel::V3D, int, std::tuple< double, double, double > > HKLPeakDescriptor
void setNumPixels(const int numPixels)
Set the total number of peaks to use.
void createPeaksWorkspace()
Create a peaks workspace with the request HKL peaks.
void createPeak(const HKLPeakDescriptor &descriptor)
Create a single HKL peak in the event workspace.
Mantid::Geometry::Instrument_sptr m_instrument
Handle to the instrument object.
Mantid::Geometry::Instrument_sptr createTestInstrumentRectangular(int num_banks, int pixels, double pixelSpacing=0.008, double bankDistanceFromSample=5.0, bool addMonitor=false)
Create a test instrument with n panels of rectangular detectors, pixels*pixels in size,...
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.
std::unique_ptr< Peak > Peak_uptr
Definition: Peak.h:170
std::unique_ptr< IPeak > IPeak_uptr
Definition: IPeak.h:103
Helper class which provides the Collimation Length for SANS instruments.