21#include "MantidHistogramData/LinearGenerator.h"
22#include "MantidIndexing/IndexInfo.h"
28#include "MantidTypes/SpectrumDefinition.h"
38using namespace Kernel;
40using namespace Geometry;
41using namespace DataObjects;
42using namespace HistogramData;
43using namespace Indexing;
46using Types::Core::DateAndTime;
47using Types::Event::TofEvent;
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)");
80 "PeakCentre=$PC5$, Height=10, Sigma=0.7;");
82 "PeakCentre=$PC3$, Height=10, Sigma=0.7;name=Gaussian, "
83 "PeakCentre=$PC6$, Height=8, Sigma=0.5");
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;");
97 "name=Lorentzian,FWHM=0.1,PeakCentre=$PC5$,Amplitude=1;"
98 "name=LinearBackground,A0=0.1");
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");
107 std::vector<std::string> 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");
115 declareProperty(
"XUnit",
"TOF",
"The unit to assign to the XAxis (default:\"TOF\")");
117 declareProperty(
"XMax", 20000.0,
"The maximum X axis value (default:20000)");
119 "The bin width of the X axis (default:200)");
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)");
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.");
134 auto dateTimeValidator = std::make_shared<Kernel::DateTimeValidator>();
135 dateTimeValidator->allowEmpty(
true);
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);
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.");
145 "The Number of banks in the instrument (default:2)");
147 "The number of monitors in the instrument (default:0)");
149 "The number of pixels in horizontally and vertically in a "
150 "bank (default:10)");
153 "Length in meters of one side of a pixel assumed to be square");
156 "Height in meters of the pixel");
159 "Distance between the center of adjacent pixels in a uniform grid "
160 "(default: 0.008 meters)");
163 "The distance along the beam direction from the sample to "
164 "bank in meters (default:5.0)");
166 "The distance along the beam direction from the source to "
167 "the sample in meters (default:10.0)");
170 std::string instrumentGroupName =
"Instrument";
186 const std::string wsType =
getProperty(
"WorkspaceType");
187 const std::string preDefinedFunction =
getProperty(
"Function");
188 const std::string userDefinedFunction =
getProperty(
"UserDefinedFunction");
191 const int numMonitors =
getProperty(
"NumMonitors");
192 const int bankPixelWidth =
getProperty(
"BankPixelWidth");
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");
207 throw std::invalid_argument(
"XMax must be larger than XMin");
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)"
214 throw std::invalid_argument(
"PixelSpacing must be at least as large as pixelDiameter");
217 if (binWidth > (xMax - xMin)) {
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 "
226 std::string functionString;
231 if (functionString.empty()) {
232 functionString = userDefinedFunction;
238 seedValue =
static_cast<int>(std::time(
nullptr));
240 m_randGen = std::make_unique<Kernel::MersenneTwister>(seedValue);
243 int numPixels = numBanks * bankPixelWidth * bankPixelWidth;
250 pixelSpacing, bankDistanceFromSample, sourceSampleDistance, instrName);
252 auto numBins =
static_cast<int>((xMax - xMin) / binWidth);
255 if (wsType ==
"Event") {
258 }
else if (numScanPoints > 1) {
268 ws->getAxis(0)->unit() = UnitFactory::Instance().create(xUnit);
270 ws->getAxis(0)->unit() = UnitFactory::Instance().create(
"Label");
272 std::shared_ptr<Units::Label> label = std::dynamic_pointer_cast<Units::Label>(unit);
273 label->setLabel(xUnit, xUnit);
276 auto sampleSphere =
createSphere(0.001,
V3D(0.0, 0.0, 0.0),
"sample-shape");
277 ws->mutableSample().setShape(sampleSphere);
279 ws->setYUnit(
"Counts");
280 ws->setTitle(
"Test Workspace");
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;
298 Run &theRun = ws->mutableRun();
314 auto testInst = ws->getInstrument();
315 auto chopper = testInst->getComponentByName(
"chopper-position");
318 auto ¶mMap = 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);
332 double x0,
double binDelta,
334 const std::string &functionString,
bool isRandom) {
335 BinEdges
x(numBins + 1, LinearGenerator(x0, binDelta));
338 Counts
y(
evalFunction(functionString, xValues.rawData(), isRandom ? 1 : 0));
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));
346 return create<Workspace2D>(inst, indexInfo, Histogram(
x,
y));
353 const std::string &functionString,
bool isRandom,
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));
364 builder.setTimeRanges(Types::Core::DateAndTime(0), timeRanges);
365 builder.setRelativeRotationsForScans(angles, inst->getSample()->getPos(),
V3D(0, 1, 0));
367 BinEdges
x(numBins + 1, LinearGenerator(x0, binDelta));
369 std::vector<double> xValues(cbegin(
x), cend(
x) - 1);
370 Counts
y(
evalFunction(functionString, xValues, isRandom ? 1 : 0));
372 builder.setHistogram(Histogram(
x,
y));
374 return builder.buildWorkspace();
380 int numEvents,
double x0,
double binDelta,
382 const std::string &functionString,
bool isRandom) {
383 DateAndTime run_start(
"2010-01-01T00:00:00");
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));
392 int numXBins = numBins + 1;
393 BinEdges
x(numXBins, LinearGenerator(x0, binDelta));
395 auto retVal = create<EventWorkspace>(inst, indexInfo,
x);
397 std::vector<double> xValues(
x.cbegin(),
x.cend() - 1);
398 std::vector<double> yValues =
evalFunction(functionString, xValues, isRandom ? 1 : 0);
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));
410 size_t workspaceIndex = 0;
412 const double hourInSeconds = 60 * 60;
413 for (
int wi = 0; wi < numPixels + numMonitors; wi++) {
416 EventList &el = retVal->getSpectrum(workspaceIndex);
417 for (
int i = 0; i < numBins; ++i) {
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);
443 const std::vector<double> &xVal,
double noiseScale = 0) {
444 size_t xSize = xVal.size();
446 std::string parsedFuncString = functionString;
447 for (
int x = 0;
x <= 10; ++
x) {
449 auto index =
static_cast<int>((xSize / 10) *
x);
450 if ((
x == 10) && (
index > 0))
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);
461 IFunction_sptr func_sptr = FunctionFactory::Instance().createInitialized(parsedFuncString);
464 func_sptr->function(fd, fv);
467 for (
size_t x = 0;
x < xSize; ++
x) {
468 if (noiseScale != 0) {
469 results[
x] += ((
m_randGen->nextValue() - 0.5) * noiseScale);
472 results[
x] =
fabs(results[
x]);
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();
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);
519 testInst->setReferenceFrame(std::make_shared<ReferenceFrame>(
Y,
Z,
Left,
""));
522 const double cylRadius(pixelDiameter / 2);
523 const double cylHeight(pixelHeight);
528 for (
int banknum = 1; banknum <= numBanks; banknum++) {
530 std::ostringstream bankname;
531 bankname <<
"bank" << banknum;
534 bank->
initialize(pixelShape, pixels, 0.0, pixelSpacing, pixels, 0.0, pixelSpacing, banknum * pixels * pixels,
true,
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);
543 testInst->markAsDetectorIncomplete(detector.get());
550 bank->
setPos(
V3D(0.0, 0.0, bankDistanceFromSample * banknum));
555 int monitorsStart = (numBanks + 1) * pixels * pixels;
560 for (
int monitorNumber = monitorsStart; monitorNumber < monitorsStart + numMonitors; monitorNumber++) {
561 std::string monitorName =
"monitor" +
std::to_string(monitorNumber - monitorsStart + 1);
563 Detector *detector =
new Detector(monitorName, monitorNumber, monitorShape, testInst.get());
565 testInst->markAsMonitorIncomplete(detector);
567 testInst->add(detector);
569 detector->
setPos(
V3D(0.0, 0.0, bankDistanceFromSample * (monitorNumber - monitorsStart + 0.5)));
573 testInst->markAsDetectorFinalize();
577 source->
setPos(
V3D(0.0, 0.0, -sourceSampleDistance));
578 testInst->add(source);
579 testInst->markAsSource(source);
583 chopper->
setPos(
V3D(0.0, 0.0, -0.25 * sourceSampleDistance));
584 testInst->add(chopper);
588 testInst->setPos(0.0, 0.0, 0.0);
589 testInst->add(sample);
590 testInst->markAsSamplePos(sample);
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()
605 <<
"<axis x=\"" << axis.
X() <<
"\" y=\"" << axis.
Y() <<
"\" z=\"" << axis.
Z() <<
"\"/>"
606 <<
"<radius val=\"" << radius <<
"\" />"
607 <<
"<height val=\"" <<
height <<
"\" />"
621 std::ostringstream xml;
622 xml <<
"<sphere id=\"" <<
id <<
"\">"
623 <<
"<centre x=\"" << centre.
X() <<
"\" y=\"" << centre.
Y() <<
"\" z=\"" << centre.
Z() <<
"\" />"
624 <<
"<radius val=\"" << radius <<
"\" />"
#define DECLARE_ALGORITHM(classname)
std::map< DeltaEMode::Type, std::string > index
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.
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.
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.
This class stores information regarding an experimental run as a series of log entries.
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 ¢re, 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)
ScanningWorkspaceBuilder : This is a helper class to make it easy to build a scanning workspace (a wo...
Constructive Solid Geometry object.
Component is a wrapper for a Component which can modify some of its parameters, e....
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.
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.
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.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
The concrete, templated class for properties.
constexpr double X() const noexcept
Get x.
constexpr double Y() const noexcept
Get y.
constexpr double Z() const noexcept
Get z.
Implements a copy on write data template.
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
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.
std::shared_ptr< Unit > Unit_sptr
Shared pointer to the Unit base class.
std::vector< double > MantidVec
typedef for the data storage used in Mantid matrix workspaces
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
@ Output
An output workspace.