Mantid
Loading...
Searching...
No Matches
CreateSampleWorkspace.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"
12#include "MantidAPI/Run.h"
13#include "MantidAPI/Sample.h"
21#include "MantidHistogramData/LinearGenerator.h"
22#include "MantidIndexing/IndexInfo.h"
28#include "MantidTypes/SpectrumDefinition.h"
29
30#include <algorithm>
31#include <cmath>
32#include <ctime>
33#include <iterator>
34#include <numeric>
35#include <stdexcept>
36
37namespace Mantid::Algorithms {
38using namespace Kernel;
39using namespace API;
40using namespace Geometry;
41using namespace DataObjects;
42using namespace HistogramData;
43using namespace Indexing;
46using Types::Core::DateAndTime;
47using Types::Event::TofEvent;
48
49// Register the algorithm into the AlgorithmFactory
50DECLARE_ALGORITHM(CreateSampleWorkspace)
51
52
55
57const std::string CreateSampleWorkspace::name() const { return "CreateSampleWorkspace"; }
58
60int CreateSampleWorkspace::version() const { return 1; }
61
63const std::string CreateSampleWorkspace::category() const { return "Utility\\Workspaces"; }
64
68 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
69 "An output workspace.");
70 std::vector<std::string> typeOptions{"Histogram", "Event"};
71 declareProperty("WorkspaceType", "Histogram", std::make_shared<StringListValidator>(typeOptions),
72 "The type of workspace to create (default: Histogram)");
73
74 // pre-defined function strings these use $PCx$ to define peak centres values
75 // that will be replaced before use
76 //$PC0$ is the far left of the data, and $PC10$ is the far right, and
77 // therefore will often not be used
78 //$PC5$ is the centre of the data
79 m_preDefinedFunctionmap.emplace("One Peak", "name=LinearBackground, A0=0.3; name=Gaussian, "
80 "PeakCentre=$PC5$, Height=10, Sigma=0.7;");
81 m_preDefinedFunctionmap.emplace("Multiple Peaks", "name=LinearBackground, A0=0.3;name=Gaussian, "
82 "PeakCentre=$PC3$, Height=10, Sigma=0.7;name=Gaussian, "
83 "PeakCentre=$PC6$, Height=8, Sigma=0.5");
84 m_preDefinedFunctionmap.emplace("Flat background", "name=LinearBackground, A0=1;");
85 m_preDefinedFunctionmap.emplace("Exp Decay", "name=ExpDecay, Height=100, Lifetime=1000;");
86 m_preDefinedFunctionmap.emplace("Powder Diffraction", "name= LinearBackground,A0=0.0850208,A1=-4.89583e-06;"
87 "name=Gaussian,Height=0.584528,PeakCentre=$PC1$,Sigma=14.3772;"
88 "name=Gaussian,Height=1.33361,PeakCentre=$PC2$,Sigma=15.2516;"
89 "name=Gaussian,Height=1.74691,PeakCentre=$PC3$,Sigma=15.8395;"
90 "name=Gaussian,Height=0.950388,PeakCentre=$PC4$,Sigma=19.8408;"
91 "name=Gaussian,Height=1.92185,PeakCentre=$PC5$,Sigma=18.0844;"
92 "name=Gaussian,Height=3.64069,PeakCentre=$PC6$,Sigma=19.2404;"
93 "name=Gaussian,Height=2.8998,PeakCentre=$PC7$,Sigma=21.1127;"
94 "name=Gaussian,Height=2.05237,PeakCentre=$PC8$,Sigma=21.9932;"
95 "name=Gaussian,Height=8.40976,PeakCentre=$PC9$,Sigma=25.2751;");
96 m_preDefinedFunctionmap.emplace("Quasielastic", "name=Lorentzian,FWHM=0.3,PeakCentre=$PC5$,Amplitude=0.8;"
97 "name=Lorentzian,FWHM=0.1,PeakCentre=$PC5$,Amplitude=1;"
98 "name=LinearBackground,A0=0.1");
99 m_preDefinedFunctionmap.emplace("Quasielastic Tunnelling",
100 "name=LinearBackground,A0=0.1;"
101 "name=Lorentzian,FWHM=0.1,PeakCentre=$PC5$,Amplitude=1;"
102 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC7$,Amplitude=0.04;"
103 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC3$,Amplitude=0.04;"
104 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC8$,Amplitude=0.02;"
105 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC2$,Amplitude=0.02");
106 m_preDefinedFunctionmap.emplace("User Defined", "");
107 std::vector<std::string> functionOptions;
108 functionOptions.reserve(m_preDefinedFunctionmap.size());
109 std::transform(m_preDefinedFunctionmap.cbegin(), m_preDefinedFunctionmap.cend(), std::back_inserter(functionOptions),
110 [](const auto &preDefinedFunction) { return preDefinedFunction.first; });
111 declareProperty("Function", "One Peak", std::make_shared<StringListValidator>(functionOptions),
112 "Preset options of the data to fill the workspace with");
113 declareProperty("UserDefinedFunction", "", "Parameters defining the fitting function and its initial values");
114
115 declareProperty("XUnit", "TOF", "The unit to assign to the XAxis (default:\"TOF\")");
116 declareProperty("XMin", 0.0, "The minimum X axis value (default:0)");
117 declareProperty("XMax", 20000.0, "The maximum X axis value (default:20000)");
118 declareProperty("BinWidth", 200.0, std::make_shared<BoundedValidator<double>>(0, 100000, true),
119 "The bin width of the X axis (default:200)");
120 declareProperty("NumEvents", 1000, std::make_shared<BoundedValidator<int>>(0, 100000),
121 "The number of events per detector, this is only used for "
122 "EventWorkspaces (default:1000)");
123 declareProperty("Random", false, "Whether to randomise the placement of events and data (default:false)");
124
125 declareProperty("NumScanPoints", 1, std::make_shared<BoundedValidator<int>>(0, 360, true),
126 "Add a number of time indexed detector scan points to the "
127 "instrument. The detectors are rotated in 1 degree "
128 "increments around the sample position in the x-z plane. "
129 "Minimum (default) is 1 scan point, which gives a "
130 "non-scanning workspace.");
131
132 declareProperty("InstrumentName", "basic_rect", Direction::Input);
133
134 auto dateTimeValidator = std::make_shared<Kernel::DateTimeValidator>();
135 dateTimeValidator->allowEmpty(true);
136 declareProperty("RunStart", "", dateTimeValidator,
137 "An optional ISO 8601 date-time string (e.g. \"2010-01-01T00:00:00\") for the start of the run. "
138 "If omitted, defaults to 2010-01-01T00:00:00. If only RunStart is given, RunEnd is set to +1 hour.");
139 auto dateTimeValidator2 = std::make_shared<Kernel::DateTimeValidator>();
140 dateTimeValidator2->allowEmpty(true);
141 declareProperty("RunEnd", "", dateTimeValidator2,
142 "An optional ISO 8601 date-time string (e.g. \"2010-01-01T01:00:00\") for the end of the run. "
143 "If omitted, defaults to 2010-01-01T01:00:00. If only RunEnd is given, RunStart is set to -1 hour.");
144 declareProperty("NumBanks", 2, std::make_shared<BoundedValidator<int>>(0, 100),
145 "The Number of banks in the instrument (default:2)");
146 declareProperty("NumMonitors", 0, std::make_shared<BoundedValidator<int>>(0, 100),
147 "The number of monitors in the instrument (default:0)");
148 declareProperty("BankPixelWidth", 10, std::make_shared<BoundedValidator<int>>(0, 10000),
149 "The number of pixels in horizontally and vertically in a "
150 "bank (default:10)");
151
152 declareProperty("PixelDiameter", 0.008, std::make_shared<BoundedValidator<double>>(0, 0.1),
153 "Length in meters of one side of a pixel assumed to be square");
154
155 declareProperty("PixelHeight", 0.0002, std::make_shared<BoundedValidator<double>>(0, 0.1),
156 "Height in meters of the pixel");
157
158 declareProperty("PixelSpacing", 0.008, std::make_shared<BoundedValidator<double>>(0, 100000, true),
159 "Distance between the center of adjacent pixels in a uniform grid "
160 "(default: 0.008 meters)");
161
162 declareProperty("BankDistanceFromSample", 5.0, std::make_shared<BoundedValidator<double>>(0, 1000, true),
163 "The distance along the beam direction from the sample to "
164 "bank in meters (default:5.0)");
165 declareProperty("SourceDistanceFromSample", 10.0, std::make_shared<BoundedValidator<double>>(0, 1000, true),
166 "The distance along the beam direction from the source to "
167 "the sample in meters (default:10.0)");
168
169 /* Aggregate properties in groups */
170 std::string instrumentGroupName = "Instrument";
171 setPropertyGroup("InstrumentName", instrumentGroupName);
172 setPropertyGroup("NumMonitors", instrumentGroupName);
173 setPropertyGroup("BankDistanceFromSample", instrumentGroupName);
174 setPropertyGroup("SourceDistanceFromSample", instrumentGroupName);
175 setPropertyGroup("NumBanks", instrumentGroupName);
176 setPropertyGroup("BankPixelWidth", instrumentGroupName);
177 setPropertyGroup("PixelDiameter", instrumentGroupName);
178 setPropertyGroup("PixelHeight", instrumentGroupName);
179 setPropertyGroup("PixelSpacing", instrumentGroupName);
180}
181
182//----------------------------------------------------------------------------------------------
186 const std::string wsType = getProperty("WorkspaceType");
187 const std::string preDefinedFunction = getProperty("Function");
188 const std::string userDefinedFunction = getProperty("UserDefinedFunction");
189 const std::string instrName = getPropertyValue("InstrumentName");
190 const int numBanks = getProperty("NumBanks");
191 const int numMonitors = getProperty("NumMonitors");
192 const int bankPixelWidth = getProperty("BankPixelWidth");
193 const int numEvents = getProperty("NumEvents");
194 const bool isRandom = getProperty("Random");
195 const std::string xUnit = getProperty("XUnit");
196 const double xMin = getProperty("XMin");
197 const double xMax = getProperty("XMax");
198 double binWidth = getProperty("BinWidth");
199 const double pixelDiameter = getProperty("PixelDiameter");
200 const double pixelHeight = getProperty("PixelHeight");
201 const double pixelSpacing = getProperty("PixelSpacing");
202 const double bankDistanceFromSample = getProperty("BankDistanceFromSample");
203 const double sourceSampleDistance = getProperty("SourceDistanceFromSample");
204 const int numScanPoints = getProperty("NumScanPoints");
205
206 if (xMax <= xMin) {
207 throw std::invalid_argument("XMax must be larger than XMin");
208 }
209
210 if (pixelSpacing < pixelDiameter) {
211 g_log.error() << "PixelSpacing (the distance between pixel centers in the uniform grid)"
212 "is smaller than the PixelDiameter (square pixel dimension)"
213 << '\n';
214 throw std::invalid_argument("PixelSpacing must be at least as large as pixelDiameter");
215 }
216
217 if (binWidth > (xMax - xMin)) {
218 // the bin width is so large that there is less than one bin - so adjust it
219 // down
220 binWidth = xMax - xMin;
221 g_log.warning() << "The bin width is so large that there is less than one "
222 "bin - it has been changed to "
223 << binWidth << '\n';
224 }
225
226 std::string functionString;
227 if (m_preDefinedFunctionmap.find(preDefinedFunction) != m_preDefinedFunctionmap.end()) {
228 // extract pre-defined string
229 functionString = m_preDefinedFunctionmap[preDefinedFunction];
230 }
231 if (functionString.empty()) {
232 functionString = userDefinedFunction;
233 }
234
235 if (!m_randGen) {
236 int seedValue = 0;
237 if (isRandom) {
238 seedValue = static_cast<int>(std::time(nullptr));
239 }
240 m_randGen = std::make_unique<Kernel::MersenneTwister>(seedValue);
241 }
242
243 int numPixels = numBanks * bankPixelWidth * bankPixelWidth;
244
245 Progress progress(this, 0.0, 1.0, numBanks);
246
247 // Create an instrument with one or more rectangular banks.
248 Instrument_sptr inst =
249 createTestInstrumentRectangular(progress, numBanks, numMonitors, bankPixelWidth, pixelDiameter, pixelHeight,
250 pixelSpacing, bankDistanceFromSample, sourceSampleDistance, instrName);
251
252 auto numBins = static_cast<int>((xMax - xMin) / binWidth);
253
255 if (wsType == "Event") {
256 ws = createEventWorkspace(numPixels, numBins, numMonitors, numEvents, xMin, binWidth, inst, functionString,
257 isRandom);
258 } else if (numScanPoints > 1) {
259 ws = createScanningWorkspace(numBins, xMin, binWidth, inst, functionString, isRandom, numScanPoints);
260 } else {
261 ws = createHistogramWorkspace(numPixels, numBins, numMonitors, xMin, binWidth, inst, functionString, isRandom);
262 }
263 // add chopper
264 this->addChopperParameters(ws);
265
266 // Set the Unit of the X Axis
267 try {
268 ws->getAxis(0)->unit() = UnitFactory::Instance().create(xUnit);
269 } catch (Exception::NotFoundError &) {
270 ws->getAxis(0)->unit() = UnitFactory::Instance().create("Label");
271 Unit_sptr unit = ws->getAxis(0)->unit();
272 std::shared_ptr<Units::Label> label = std::dynamic_pointer_cast<Units::Label>(unit);
273 label->setLabel(xUnit, xUnit);
274 }
275
276 auto sampleSphere = createSphere(0.001, V3D(0.0, 0.0, 0.0), "sample-shape");
277 ws->mutableSample().setShape(sampleSphere);
278
279 ws->setYUnit("Counts");
280 ws->setTitle("Test Workspace");
281
282 const std::string runStartInput = getPropertyValue("RunStart");
283 const std::string runEndInput = getPropertyValue("RunEnd");
284 const double oneHourInSeconds = 3600.0;
285 DateAndTime run_start("2010-01-01T00:00:00");
286 DateAndTime run_end("2010-01-01T01:00:00");
287 if (!runStartInput.empty() && !runEndInput.empty()) {
288 run_start = DateAndTime(runStartInput);
289 run_end = DateAndTime(runEndInput);
290 } else if (!runStartInput.empty()) {
291 run_start = DateAndTime(runStartInput);
292 run_end = run_start + oneHourInSeconds;
293 } else if (!runEndInput.empty()) {
294 run_end = DateAndTime(runEndInput);
295 run_start = run_end - oneHourInSeconds;
296 }
297
298 Run &theRun = ws->mutableRun();
299 // belt and braces use both approaches for setting start and end times
300 theRun.setStartAndEndTime(run_start, run_end);
301 theRun.addLogData(new PropertyWithValue<std::string>("run_start", run_start.toISO8601String()));
302 theRun.addLogData(new PropertyWithValue<std::string>("run_end", run_end.toISO8601String()));
303
304 // Assign it to the output workspace property
305 setProperty("OutputWorkspace", ws);
306 ;
307}
313
314 auto testInst = ws->getInstrument();
315 auto chopper = testInst->getComponentByName("chopper-position");
316
317 // add chopper parameters
318 auto &paramMap = ws->instrumentParameters();
319 const std::string description("The initial rotation phase of the disk used to calculate the time"
320 " for neutrons arriving at the chopper according to the formula time = "
321 "delay + initial_phase/Speed");
322 paramMap.add<double>("double", chopper.get(), "initial_phase", -3000., &description);
323 paramMap.add<std::string>("string", chopper.get(), "ChopperDelayLog", "fermi_delay");
324 paramMap.add<std::string>("string", chopper.get(), "ChopperSpeedLog", "fermi_speed");
325 paramMap.add<std::string>("string", chopper.get(), "FilterBaseLog", "is_running");
326 paramMap.add<bool>("bool", chopper.get(), "filter_with_derivative", false);
327}
328
332 double x0, double binDelta,
333 const Geometry::Instrument_sptr &inst,
334 const std::string &functionString, bool isRandom) {
335 BinEdges x(numBins + 1, LinearGenerator(x0, binDelta));
336 Points xValues(x);
337
338 Counts y(evalFunction(functionString, xValues.rawData(), isRandom ? 1 : 0));
339
340 std::vector<SpectrumDefinition> specDefs(numPixels + numMonitors);
341 for (int wi = 0; wi < numMonitors + numPixels; wi++)
342 specDefs[wi].add(wi < numMonitors ? numPixels + wi : wi - numMonitors);
343 Indexing::IndexInfo indexInfo(numPixels + numMonitors);
344 indexInfo.setSpectrumDefinitions(std::move(specDefs));
345
346 return create<Workspace2D>(inst, indexInfo, Histogram(x, y));
347}
348
352 const Geometry::Instrument_sptr &inst,
353 const std::string &functionString, bool isRandom,
354 int numScanPoints) {
355 auto builder = ScanningWorkspaceBuilder(inst, numScanPoints, numBins);
356
357 auto angles = std::vector<double>();
358 auto timeRanges = std::vector<double>();
359 for (int i = 0; i < numScanPoints; ++i) {
360 angles.emplace_back(double(i));
361 timeRanges.emplace_back(double(i + 1));
362 }
363
364 builder.setTimeRanges(Types::Core::DateAndTime(0), timeRanges);
365 builder.setRelativeRotationsForScans(angles, inst->getSample()->getPos(), V3D(0, 1, 0));
366
367 BinEdges x(numBins + 1, LinearGenerator(x0, binDelta));
368
369 std::vector<double> xValues(cbegin(x), cend(x) - 1);
370 Counts y(evalFunction(functionString, xValues, isRandom ? 1 : 0));
371
372 builder.setHistogram(Histogram(x, y));
373
374 return builder.buildWorkspace();
375}
376
379EventWorkspace_sptr CreateSampleWorkspace::createEventWorkspace(int numPixels, int numBins, int numMonitors,
380 int numEvents, double x0, double binDelta,
381 const Geometry::Instrument_sptr &inst,
382 const std::string &functionString, bool isRandom) {
383 DateAndTime run_start("2010-01-01T00:00:00");
384
385 std::vector<SpectrumDefinition> specDefs(numPixels + numMonitors);
386 for (int wi = 0; wi < numMonitors + numPixels; wi++)
387 specDefs[wi].add(wi < numMonitors ? numPixels + wi : wi - numMonitors);
388 Indexing::IndexInfo indexInfo(numPixels + numMonitors);
389 indexInfo.setSpectrumDefinitions(std::move(specDefs));
390
391 // add one to the number of bins as this is histogram
392 int numXBins = numBins + 1;
393 BinEdges x(numXBins, LinearGenerator(x0, binDelta));
394
395 auto retVal = create<EventWorkspace>(inst, indexInfo, x);
396
397 std::vector<double> xValues(x.cbegin(), x.cend() - 1);
398 std::vector<double> yValues = evalFunction(functionString, xValues, isRandom ? 1 : 0);
399
400 // we need to normalise the results and then multiply by the number of events
401 // to find the events per bin
402 double sum_of_elems = std::accumulate(yValues.begin(), yValues.end(), 0.0);
403 double event_distrib_factor = numEvents / sum_of_elems;
404 using std::placeholders::_1;
405 std::transform(yValues.begin(), yValues.end(), yValues.begin(),
406 std::bind(std::multiplies<double>(), event_distrib_factor, _1));
407 // the array should now contain the number of events required per bin
408
409 // Make fake events
410 size_t workspaceIndex = 0;
411
412 const double hourInSeconds = 60 * 60;
413 for (int wi = 0; wi < numPixels + numMonitors; wi++) {
414 // TODO: Can I think of *any* reason that "wi" is not the index actually used by this loop body?!
415
416 EventList &el = retVal->getSpectrum(workspaceIndex);
417 for (int i = 0; i < numBins; ++i) {
418 // create randomised events within the bin to match the number required -
419 // calculated in yValues earlier
420 auto eventsInBin = static_cast<int>(yValues[i]);
421 for (int q = 0; q < eventsInBin; q++) {
422 DateAndTime pulseTime = run_start + (m_randGen->nextValue() * hourInSeconds);
423 el += TofEvent((i + m_randGen->nextValue()) * binDelta + x0, pulseTime);
424 }
425 }
426 workspaceIndex++;
427 }
428
429 return retVal;
430}
431//----------------------------------------------------------------------------------------------
442std::vector<double> CreateSampleWorkspace::evalFunction(const std::string &functionString,
443 const std::vector<double> &xVal, double noiseScale = 0) {
444 size_t xSize = xVal.size();
445 // replace $PCx$ values
446 std::string parsedFuncString = functionString;
447 for (int x = 0; x <= 10; ++x) {
448 // get the rough peak centre value
449 auto index = static_cast<int>((xSize / 10) * x);
450 if ((x == 10) && (index > 0))
451 --index;
452 double replace_val = xVal[index];
453 std::ostringstream tokenStream;
454 tokenStream << "$PC" << x << "$";
455 std::string token = tokenStream.str();
456 std::string replaceStr = boost::lexical_cast<std::string>(replace_val);
457 replaceAll(parsedFuncString, token, replaceStr);
458 }
459 g_log.information(parsedFuncString);
460
461 IFunction_sptr func_sptr = FunctionFactory::Instance().createInitialized(parsedFuncString);
462 FunctionDomain1DVector fd(xVal);
463 FunctionValues fv(fd);
464 func_sptr->function(fd, fv);
465
466 auto results = fv.toVector();
467 for (size_t x = 0; x < xSize; ++x) {
468 if (noiseScale != 0) {
469 results[x] += ((m_randGen->nextValue() - 0.5) * noiseScale);
470 }
471 // no negative values please - it messes up the error calculation
472 results[x] = fabs(results[x]);
473 }
474 return results;
475}
476
477void CreateSampleWorkspace::replaceAll(std::string &str, const std::string &from, const std::string &to) {
478 if (from.empty())
479 return;
480 size_t start_pos = 0;
481 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
482 str.replace(start_pos, from.length(), to);
483 start_pos += to.length(); // In case 'to' contains 'from', like replacing
484 // 'x' with 'yx'
485 }
486}
487
488//----------------------------------------------------------------------------------------------
513 API::Progress &progress, int numBanks, int numMonitors, int pixels, double pixelDiameter, double pixelHeight,
514 double pixelSpacing, const double bankDistanceFromSample, const double sourceSampleDistance,
515 const std::string &instrName) {
516 auto testInst = std::make_shared<Instrument>(instrName);
517 // The instrument is going to be set up with z as the beam axis and y as the
518 // vertical axis.
519 testInst->setReferenceFrame(std::make_shared<ReferenceFrame>(Y, Z, Left, ""));
520
521 /* Captain! This is wrong */
522 const double cylRadius(pixelDiameter / 2);
523 const double cylHeight(pixelHeight);
524 // One object
525 auto pixelShape =
526 createCappedCylinder(cylRadius, cylHeight, V3D(0.0, -cylHeight / 2.0, 0.0), V3D(0., 1.0, 0.), "pixel-shape");
527
528 for (int banknum = 1; banknum <= numBanks; banknum++) {
529 // Make a new bank
530 std::ostringstream bankname;
531 bankname << "bank" << banknum;
532
533 RectangularDetector *bank = new RectangularDetector(bankname.str());
534 bank->initialize(pixelShape, pixels, 0.0, pixelSpacing, pixels, 0.0, pixelSpacing, banknum * pixels * pixels, true,
535 pixels);
536
537 // Mark them all as detectors
538 for (int x = 0; x < pixels; x++) {
539 for (int y = 0; y < pixels; y++) {
540 std::shared_ptr<Detector> detector = bank->getAtXY(x, y);
541 if (detector) {
542 // Mark it as a detector (add to the instrument cache)
543 testInst->markAsDetectorIncomplete(detector.get());
544 }
545 }
546 }
547
548 testInst->add(bank);
549 // Set the bank along the z-axis of the instrument. (beam direction).
550 bank->setPos(V3D(0.0, 0.0, bankDistanceFromSample * banknum));
551
552 progress.report();
553 }
554
555 int monitorsStart = (numBanks + 1) * pixels * pixels;
556
557 auto monitorShape =
558 createCappedCylinder(0.1, 0.1, V3D(0.0, -cylHeight / 2.0, 0.0), V3D(0., 1.0, 0.), "monitor-shape");
559
560 for (int monitorNumber = monitorsStart; monitorNumber < monitorsStart + numMonitors; monitorNumber++) {
561 std::string monitorName = "monitor" + std::to_string(monitorNumber - monitorsStart + 1);
562
563 Detector *detector = new Detector(monitorName, monitorNumber, monitorShape, testInst.get());
564 // Mark it as a monitor (add to the instrument cache)
565 testInst->markAsMonitorIncomplete(detector);
566
567 testInst->add(detector);
568 // Set the bank along the z-axis of the instrument, between the detectors.
569 detector->setPos(V3D(0.0, 0.0, bankDistanceFromSample * (monitorNumber - monitorsStart + 0.5)));
570 }
571
572 // finalize the instrument
573 testInst->markAsDetectorFinalize();
574
575 // Define a source component
576 ObjComponent *source = new ObjComponent("moderator", IObject_sptr(new CSGObject), testInst.get());
577 source->setPos(V3D(0.0, 0.0, -sourceSampleDistance));
578 testInst->add(source);
579 testInst->markAsSource(source);
580
581 // Add chopper
582 ObjComponent *chopper = new ObjComponent("chopper-position", IObject_sptr(new CSGObject), testInst.get());
583 chopper->setPos(V3D(0.0, 0.0, -0.25 * sourceSampleDistance));
584 testInst->add(chopper);
585
586 // Define a sample position
587 Component *sample = new Component("sample", testInst.get());
588 testInst->setPos(0.0, 0.0, 0.0);
589 testInst->add(sample);
590 testInst->markAsSamplePos(sample);
591
592 return testInst;
593}
594
595//----------------------------------------------------------------------------------------------
600 const V3D &axis, const std::string &id) {
601 std::ostringstream xml;
602 xml << "<cylinder id=\"" << id << "\">"
603 << "<centre-of-bottom-base x=\"" << baseCentre.X() << "\" y=\"" << baseCentre.Y() << "\" z=\"" << baseCentre.Z()
604 << "\"/>"
605 << "<axis x=\"" << axis.X() << "\" y=\"" << axis.Y() << "\" z=\"" << axis.Z() << "\"/>"
606 << "<radius val=\"" << radius << "\" />"
607 << "<height val=\"" << height << "\" />"
608 << "</cylinder>";
609
610 ShapeFactory shapeMaker;
611 return shapeMaker.createShape(xml.str());
612}
613
614//----------------------------------------------------------------------------------------------
615
619IObject_sptr CreateSampleWorkspace::createSphere(double radius, const V3D &centre, const std::string &id) {
620 ShapeFactory shapeMaker;
621 std::ostringstream xml;
622 xml << "<sphere id=\"" << id << "\">"
623 << "<centre x=\"" << centre.X() << "\" y=\"" << centre.Y() << "\" z=\"" << centre.Z() << "\" />"
624 << "<radius val=\"" << radius << "\" />"
625 << "</sphere>";
626 return shapeMaker.createShape(xml.str());
627}
628
629} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
double height
Definition GetAllEi.cpp:155
std::map< DeltaEMode::Type, std::string > index
#define fabs(x)
Definition Matrix.cpp:22
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:423
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Implements FunctionDomain1D with its own storage in form of a std::vector.
A class to store values calculated by a function.
const std::vector< double > & toVector() const
Return the calculated values as a vector.
void addLogData(Kernel::Property *p)
Add a log entry.
Definition LogManager.h:126
void setStartAndEndTime(const Types::Core::DateAndTime &start, const Types::Core::DateAndTime &end)
Set the run start and end.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:35
A property class for workspaces.
CreateSampleWorkspace : This algorithm is intended for the creation of sample workspaces for usage ex...
Geometry::IObject_sptr createSphere(double radius, const Kernel::V3D &centre, const std::string &id)
Create a sphere object.
Geometry::IObject_sptr createCappedCylinder(double radius, double height, const Kernel::V3D &baseCentre, const Kernel::V3D &axis, const std::string &id)
Create a capped cylinder object.
int version() const override
Algorithm's version for identification.
void exec() override
Execute the algorithm.
std::vector< double > evalFunction(const std::string &functionString, const std::vector< double > &xVal, double noiseScale)
Evaluates a function and returns the values as a vector.
std::unique_ptr< Kernel::PseudoRandomNumberGenerator > m_randGen
A pointer to the random number generator.
const std::string name() const override
Algorithm's name for identification.
DataObjects::EventWorkspace_sptr createEventWorkspace(int numPixels, int numBins, int numMonitors, int numEvents, double x0, double binDelta, const Geometry::Instrument_sptr &inst, const std::string &functionString, bool isRandom)
Create event workspace.
void init() override
Initialize the algorithm's properties.
API::MatrixWorkspace_sptr createHistogramWorkspace(int numPixels, int numBins, int numMonitors, double x0, double binDelta, const Geometry::Instrument_sptr &inst, const std::string &functionString, bool isRandom)
Create histogram workspace.
std::map< std::string, std::string > m_preDefinedFunctionmap
Geometry::Instrument_sptr createTestInstrumentRectangular(API::Progress &progress, int numBanks, int numMonitors, int pixels, double pixelDiameter, double pixelHeight, double pixelSpacing, const double bankDistanceFromSample, const double sourceSampleDistance, const std::string &instrName)
Create an test instrument with n panels of rectangular detectors, pixels*pixels in size,...
void addChopperParameters(API::MatrixWorkspace_sptr &ws)
Add chopper to the existing matrix workspace.
const std::string category() const override
Algorithm's category for identification.
API::MatrixWorkspace_sptr createScanningWorkspace(int numBins, double x0, double binDelta, const Geometry::Instrument_sptr &inst, const std::string &functionString, bool isRandom, int numScanPoints)
Create scanning histogram workspace.
void replaceAll(std::string &str, const std::string &from, const std::string &to)
A class for holding :
Definition EventList.h:57
ScanningWorkspaceBuilder : This is a helper class to make it easy to build a scanning workspace (a wo...
Constructive Solid Geometry object.
Definition CSGObject.h:51
Component is a wrapper for a Component which can modify some of its parameters, e....
Definition Component.h:42
void setPos(double, double, double) override
Set the IComponent position, x, y, z respective to parent (if present)
This class represents a detector - i.e.
Definition Detector.h:30
virtual void setPos(double, double, double)=0
Set the IComponent position, x, y, z respective to parent (if present)
Object Component class, this class brings together the physical attributes of the component to the po...
RectangularDetector is a type of CompAssembly, an assembly of components.
std::shared_ptr< Detector > getAtXY(const int X, const int Y) const
Return a pointer to the component in the assembly at the (X,Y) pixel position.
void initialize(std::shared_ptr< IObject > shape, int xpixels, double xstart, double xstep, int ypixels, double ystart, double ystep, int idstart, bool idfillbyfirst_y, int idstepbyrow, int idstep=1)
Create all the detector pixels of this rectangular detector.
Class originally intended to be used with the DataHandling 'LoadInstrument' algorithm.
std::shared_ptr< CSGObject > createShape(Poco::XML::Element *pElem)
Creates a geometric object from a DOM-element-node pointing to an element whose child nodes contain t...
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
Exception for when an item is not found in a collection.
Definition Exception.h:145
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
The concrete, templated class for properties.
Class for 3D vectors.
Definition V3D.h:34
constexpr double X() const noexcept
Get x.
Definition V3D.h:238
constexpr double Y() const noexcept
Get y.
Definition V3D.h:239
constexpr double Z() const noexcept
Get z.
Definition V3D.h:240
Implements a copy on write data template.
Definition cow_ptr.h:41
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition IFunction.h:743
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::size_t numEvents(Nexus::File &file, bool &hasTotalCounts, bool &oldNeXusFileNames, const std::string &prefix)
Get the number of events in the currently opened group.
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
std::shared_ptr< IObject > IObject_sptr
Typdef for a shared pointer.
Definition IObject.h:93
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
Definition Unit.h:194
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
Definition cow_ptr.h:172
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54