21#include "boost/math/distributions.hpp"
25using Kernel::ThreadPool;
26using Kernel::ThreadSchedulerFIFO;
38FakeMD::FakeMD(
const std::vector<double> &uniformParams,
const std::vector<double> &peakParams,
39 const std::vector<double> &ellipsoidParams,
const int randomSeed,
const bool randomizeSignal)
40 : m_uniformParams(uniformParams), m_peakParams(peakParams), m_ellipsoidParams(ellipsoidParams),
41 m_randomSeed(randomSeed), m_randomizeSignal(randomizeSignal), m_detIDs(), m_randGen(1), m_uniformDist() {
42 if (uniformParams.empty() && peakParams.empty() && ellipsoidParams.empty()) {
43 throw std::invalid_argument(
"You must specify at least one of peakParams, "
44 "ellipsoidParams or uniformParams");
71 auto inst =
workspace.getExperimentInfo(0)->getInstrument();
72 m_detIDs = inst->getDetectorIDs(
true);
75 }
catch (std::invalid_argument &) {
90 throw std::invalid_argument(
"PeakParams needs to have ndims+2 arguments.");
92 throw std::invalid_argument(
"PeakParams: number_of_events needs to be > 0");
98 std::mt19937 rng(
static_cast<unsigned int>(
m_randomSeed));
99 std::uniform_real_distribution<coord_t> flat(0, 1.0);
105 for (
size_t i = 0; i < num; ++i) {
108 auto radius_frac = flat(rng);
109 auto radius =
static_cast<coord_t>(desiredRadius * pow(radius_frac, 1.0f / nd));
114 while (modulusSq < 1E-6) {
116 for (
size_t d = 0;
d < nd;
d++) {
117 centers[
d] = normal(rng);
118 modulusSq += centers[
d] * centers[
d];
122 auto inverseModulus =
static_cast<coord_t>(1.0f / sqrt(modulusSq));
123 for (
size_t d = 0;
d < nd;
d++) {
125 centers[
d] *=
radius * inverseModulus;
132 float errorSquared = 1.0;
134 signal = float(0.5 + flat(rng));
135 errorSquared = float(0.5 + flat(rng));
139 eventHelper.insertMDEvent(signal, errorSquared, 0, 0,
pickDetectorID(),
166 throw std::invalid_argument(
"EllipsoidParams: incorrect number of parameters.");
168 throw std::invalid_argument(
"EllipsoidParams: number_of_events needs to be > 0");
176 for (
size_t n = 0;
n < nd;
n++) {
179 for (
size_t d = 0;
d < nd;
d++) {
188 auto A = Evec * stds;
193 auto var = stds * stds;
199 invCov = Evec * var * invEvec;
204 boost::math::chi_squared chisq(nd);
207 std::mt19937 rng(
static_cast<unsigned int>(
m_randomSeed));
213 for (
size_t iEvent = 0; iEvent <
numEvents; ++iEvent) {
216 std::vector<double> pos;
217 for (
size_t n = 0;
n < nd;
n++) {
218 pos.push_back(
d(rng));
225 float errorSquared = 1.0;
231 auto tmp = invCov * pos;
233 for (
size_t n = 0;
n < nd;
n++) {
234 mdsq += pos[
n] *
tmp[
n];
238 signal =
static_cast<float>(boost::math::pdf(chisq, sqrt(mdsq)));
239 errorSquared = signal;
243 for (
size_t n = 0;
n < nd;
n++) {
244 eventCenter[
n] =
static_cast<coord_t>(pos[
n] + center[
n]);
248 eventHelper.insertMDEvent(signal, errorSquared, 0, 0,
pickDetectorID(),
268 bool randomEvents =
true;
270 randomEvents =
false;
276 for (
size_t d = 0;
d < nd; ++
d) {
284 for (
size_t d = 0;
d < nd; ++
d)
287 if (Vol == 0 || Vol > std::numeric_limits<float>::max())
288 throw std::invalid_argument(
" Domain ranges are not defined properly for workspace: " + ws->
getName());
290 double dV = Vol / double(nPoints);
291 double delta0 = std::pow(dV, 1. /
double(nd));
292 for (
size_t d = 0;
d < nd; ++
d) {
294 m_uniformParams.emplace_back(min * (1 + FLT_EPSILON) - min + FLT_EPSILON);
296 auto nStrides = size_t(extent / delta0);
304 throw std::invalid_argument(
"UniformParams: needs to have ndims*2+1 arguments ");
324template <
typename MDE,
size_t nd>
327 auto num = size_t(params[0]);
329 throw std::invalid_argument(
" number of distributed events can not be equal to 0");
335 std::mt19937 rng(
static_cast<unsigned int>(
m_randomSeed));
336 std::array<std::uniform_real_distribution<double>, nd> gens;
337 for (
size_t d = 0;
d < nd; ++
d) {
338 double min = params[
d * 2 + 1];
339 double max = params[
d * 2 + 2];
341 throw std::invalid_argument(
"UniformParams: min must be < max for all dimensions.");
342 gens[
d] = std::uniform_real_distribution<double>(min, max);
345 std::uniform_real_distribution<double> flat(0, 1.0);
347 for (
size_t i = 0; i < num; ++i) {
349 for (
size_t d = 0;
d < nd;
d++) {
350 centers[
d] =
static_cast<coord_t>(gens[
d](rng));
355 float errorSquared = 1.0;
357 signal = float(0.5 + flat(rng));
358 errorSquared = float(0.5 + flat(rng));
362 eventHelper.insertMDEvent(signal, errorSquared, 0, 0,
pickDetectorID(),
367template <
typename MDE,
size_t nd>
370 std::vector<double> startPoint(nd),
delta(nd);
371 std::vector<size_t> indexMax(nd);
374 auto num = size_t(params[0]);
376 throw std::invalid_argument(
" number of distributed events can not be equal to 0");
382 for (
size_t d = 0;
d < nd; ++
d) {
385 double shift = params[
d * 2 + 1];
386 double step = params[
d * 2 + 2];
390 shift = step * (1 - FLT_EPSILON);
392 startPoint[
d] = min + shift;
393 if ((startPoint[
d] < min) || (startPoint[
d] >= max))
394 throw std::invalid_argument(
"RegularData: starting point must be within "
395 "the box for all dimensions.");
398 throw(std::invalid_argument(
"Step of the regular grid is less or equal to 0"));
400 indexMax[
d] = size_t((max - min) / step);
401 if (indexMax[
d] == 0)
404 while ((startPoint[
d] +
double(indexMax[
d] - 1) * step) >= max)
405 step *= (1 - FLT_EPSILON);
409 gridSize *= indexMax[
d];
413 for (
size_t i = 0; i < num; ++i) {
418 if (cellCount >= gridSize)
421 for (
size_t d = 0;
d < nd;
d++) {
427 float errorSquared = 1.0;
430 eventHelper.insertMDEvent(signal, errorSquared, 0, 0,
pickDetectorID(),
static std::unique_ptr< QThreadPool > tp
IPeaksWorkspace_sptr workspace
#define CALL_MDEVENT_FUNCTION(funcname, workspace)
Macro that makes it possible to call a templated method for a MDEventWorkspace using a IMDEventWorksp...
Abstract base class for multi-dimension event workspaces (MDEventWorkspace).
virtual std::shared_ptr< const Mantid::Geometry::IMDDimension > getDimension(size_t index) const
Get a dimension.
const std::string & getName() const override
Get the workspace name.
void fill(const API::IMDEventWorkspace_sptr &workspace)
Add the fake data to the given workspace.
void addFakeRandomData(const std::vector< double > ¶ms, typename MDEventWorkspace< MDE, nd >::sptr ws)
Add fake randomized data to the workspace.
std::vector< detid_t > m_detIDs
const bool m_randomizeSignal
void addFakeUniformData(typename MDEventWorkspace< MDE, nd >::sptr ws)
Function makes up a fake uniform event data and adds it to the workspace.
void addFakeRegularData(const std::vector< double > ¶ms, typename MDEventWorkspace< MDE, nd >::sptr ws)
FakeMD(const std::vector< double > &uniformParams, const std::vector< double > &peakParams, const std::vector< double > &ellipsoidParams, const int randomSeed, const bool randomizeSignal)
Constructor.
Kernel::uniform_int_distribution< size_t > m_uniformDist
detid_t pickDetectorID()
Pick a detector ID for a particular event.
void setupDetectorCache(const API::IMDEventWorkspace &workspace)
Setup a detector cache for randomly picking IDs from the first instrument in the ExperimentInfo list.
std::vector< double > m_peakParams
void addFakePeak(typename MDEventWorkspace< MDE, nd >::sptr ws)
Function generates random uniformly distributed events within an nD-sphere to simulate a single-cryst...
std::vector< double > m_ellipsoidParams
std::vector< double > m_uniformParams
void addFakeEllipsoid(typename MDEventWorkspace< MDE, nd >::sptr ws)
Function that adds a fake single-crystal peak with a multivariate normal distribution (an ellipsoid) ...
MDEventInserter : Helper class that provides a generic interface for adding events to an MDWorkspace ...
void splitBox() override
Split the top-level MDBox into a MDGridBox.
std::shared_ptr< MDEventWorkspace< MDE, nd > > sptr
Typedef for a shared pointer of this kind of event workspace.
void splitAllIfNeeded(Kernel::ThreadScheduler *ts) override
Split all boxes that exceed the split threshold.
void refreshCache() override
Refresh the cache (integrated signal of each box)
T Invert()
LU inversion routine.
std::vector< T > getVector() const
A Thread Pool implementation that keeps a certain number of threads running (normally,...
A First-In-First-Out Thread Scheduler.
std::shared_ptr< IMDEventWorkspace > IMDEventWorkspace_sptr
Shared pointer to Mantid::API::IMDEventWorkspace.
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.
void getIndicesFromLinearIndex(const size_t linear_index, size_t const *const numBins, const size_t numDims, size_t *const out_indices)
Convert an linear index in nDim workspace into vector of loop indexes of nDim depth loop Unsafe (poin...
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
int32_t detid_t
Typedef for a detector ID.