21#include "MantidHistogramData/LinearGenerator.h"
22#include "MantidIndexing/IndexInfo.h"
27#include "MantidTypes/SpectrumDefinition.h"
37using namespace Kernel;
39using namespace Geometry;
40using namespace DataObjects;
41using namespace HistogramData;
42using namespace Indexing;
45using Types::Core::DateAndTime;
46using Types::Event::TofEvent;
68 "An output workspace.");
69 std::vector<std::string> typeOptions{
"Histogram",
"Event"};
70 declareProperty(
"WorkspaceType",
"Histogram", std::make_shared<StringListValidator>(typeOptions),
71 "The type of workspace to create (default: Histogram)");
79 "PeakCentre=$PC5$, Height=10, Sigma=0.7;");
81 "PeakCentre=$PC3$, Height=10, Sigma=0.7;name=Gaussian, "
82 "PeakCentre=$PC6$, Height=8, Sigma=0.5");
86 "name=Gaussian,Height=0.584528,PeakCentre=$PC1$,Sigma=14.3772;"
87 "name=Gaussian,Height=1.33361,PeakCentre=$PC2$,Sigma=15.2516;"
88 "name=Gaussian,Height=1.74691,PeakCentre=$PC3$,Sigma=15.8395;"
89 "name=Gaussian,Height=0.950388,PeakCentre=$PC4$,Sigma=19.8408;"
90 "name=Gaussian,Height=1.92185,PeakCentre=$PC5$,Sigma=18.0844;"
91 "name=Gaussian,Height=3.64069,PeakCentre=$PC6$,Sigma=19.2404;"
92 "name=Gaussian,Height=2.8998,PeakCentre=$PC7$,Sigma=21.1127;"
93 "name=Gaussian,Height=2.05237,PeakCentre=$PC8$,Sigma=21.9932;"
94 "name=Gaussian,Height=8.40976,PeakCentre=$PC9$,Sigma=25.2751;");
96 "name=Lorentzian,FWHM=0.1,PeakCentre=$PC5$,Amplitude=1;"
97 "name=LinearBackground,A0=0.1");
99 "name=LinearBackground,A0=0.1;"
100 "name=Lorentzian,FWHM=0.1,PeakCentre=$PC5$,Amplitude=1;"
101 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC7$,Amplitude=0.04;"
102 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC3$,Amplitude=0.04;"
103 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC8$,Amplitude=0.02;"
104 "name=Lorentzian,FWHM=0.05,PeakCentre=$PC2$,Amplitude=0.02");
106 std::vector<std::string> functionOptions;
109 [](
const auto &preDefinedFunction) { return preDefinedFunction.first; });
110 declareProperty(
"Function",
"One Peak", std::make_shared<StringListValidator>(functionOptions),
111 "Preset options of the data to fill the workspace with");
112 declareProperty(
"UserDefinedFunction",
"",
"Parameters defining the fitting function and its initial values");
114 declareProperty(
"XUnit",
"TOF",
"The unit to assign to the XAxis (default:\"TOF\")");
116 declareProperty(
"XMax", 20000.0,
"The maximum X axis value (default:20000)");
118 "The bin width of the X axis (default:200)");
120 "The number of events per detector, this is only used for "
121 "EventWorkspaces (default:1000)");
122 declareProperty(
"Random",
false,
"Whether to randomise the placement of events and data (default:false)");
125 "Add a number of time indexed detector scan points to the "
126 "instrument. The detectors are rotated in 1 degree "
127 "increments around the the sample position in the x-z plane. "
128 "Minimum (default) is 1 scan point, which gives a "
129 "non-scanning workspace.");
133 "The Number of banks in the instrument (default:2)");
135 "The number of monitors in the instrument (default:0)");
137 "The number of pixels in horizontally and vertically in a "
138 "bank (default:10)");
141 "Length in meters of one side of a pixel assumed to be square");
144 "Height in meters of the pixel");
147 "Distance between the center of adjacent pixels in a uniform grid "
148 "(default: 0.008 meters)");
151 "The distance along the beam direction from the sample to "
152 "bank in meters (default:5.0)");
154 "The distance along the beam direction from the source to "
155 "the sample in meters (default:10.0)");
158 std::string instrumentGroupName =
"Instrument";
174 const std::string wsType =
getProperty(
"WorkspaceType");
175 const std::string preDefinedFunction =
getProperty(
"Function");
176 const std::string userDefinedFunction =
getProperty(
"UserDefinedFunction");
179 const int numMonitors =
getProperty(
"NumMonitors");
180 const int bankPixelWidth =
getProperty(
"BankPixelWidth");
187 const double pixelDiameter =
getProperty(
"PixelDiameter");
188 const double pixelHeight =
getProperty(
"PixelHeight");
189 const double pixelSpacing =
getProperty(
"PixelSpacing");
190 const double bankDistanceFromSample =
getProperty(
"BankDistanceFromSample");
191 const double sourceSampleDistance =
getProperty(
"SourceDistanceFromSample");
192 const int numScanPoints =
getProperty(
"NumScanPoints");
195 throw std::invalid_argument(
"XMax must be larger than XMin");
198 if (pixelSpacing < pixelDiameter) {
199 g_log.
error() <<
"PixelSpacing (the distance between pixel centers in the uniform grid)"
200 "is smaller than the PixelDiameter (square pixel dimension)"
202 throw std::invalid_argument(
"PixelSpacing must be at least as large as pixelDiameter");
205 if (binWidth > (xMax - xMin)) {
208 binWidth = xMax - xMin;
209 g_log.
warning() <<
"The bin width is so large that there is less than one "
210 "bin - it has been changed to "
214 std::string functionString;
219 if (functionString.empty()) {
220 functionString = userDefinedFunction;
226 seedValue =
static_cast<int>(std::time(
nullptr));
228 m_randGen = std::make_unique<Kernel::MersenneTwister>(seedValue);
231 int numPixels = numBanks * bankPixelWidth * bankPixelWidth;
238 pixelSpacing, bankDistanceFromSample, sourceSampleDistance, instrName);
240 auto numBins =
static_cast<int>((xMax - xMin) / binWidth);
243 if (wsType ==
"Event") {
246 }
else if (numScanPoints > 1) {
260 std::shared_ptr<Units::Label> label = std::dynamic_pointer_cast<Units::Label>(unit);
261 label->setLabel(xUnit, xUnit);
264 auto sampleSphere =
createSphere(0.001,
V3D(0.0, 0.0, 0.0),
"sample-shape");
265 ws->mutableSample().setShape(sampleSphere);
267 ws->setYUnit(
"Counts");
268 ws->setTitle(
"Test Workspace");
269 DateAndTime run_start(
"2010-01-01T00:00:00");
270 DateAndTime run_end(
"2010-01-01T01:00:00");
271 Run &theRun = ws->mutableRun();
289 auto testInst = ws->getInstrument();
290 auto chopper = testInst->getComponentByName(
"chopper-position");
293 auto ¶mMap = ws->instrumentParameters();
294 const std::string description(
"The initial rotation phase of the disk used to calculate the time"
295 " for neutrons arriving at the chopper according to the formula time = "
296 "delay + initial_phase/Speed");
297 paramMap.add<
double>(
"double", chopper.get(),
"initial_phase", -3000., &description);
298 paramMap.add<std::string>(
"string", chopper.get(),
"ChopperDelayLog",
"fermi_delay");
299 paramMap.add<std::string>(
"string", chopper.get(),
"ChopperSpeedLog",
"fermi_speed");
300 paramMap.add<std::string>(
"string", chopper.get(),
"FilterBaseLog",
"is_running");
301 paramMap.add<
bool>(
"bool", chopper.get(),
"filter_with_derivative",
false);
307 double x0,
double binDelta,
309 const std::string &functionString,
bool isRandom) {
310 BinEdges
x(numBins + 1, LinearGenerator(x0, binDelta));
313 Counts
y(
evalFunction(functionString, xValues.rawData(), isRandom ? 1 : 0));
315 std::vector<SpectrumDefinition> specDefs(numPixels + numMonitors);
316 for (
int wi = 0; wi < numMonitors + numPixels; wi++)
317 specDefs[wi].add(wi < numMonitors ? numPixels + wi : wi - numMonitors);
318 Indexing::IndexInfo indexInfo(numPixels + numMonitors);
319 indexInfo.setSpectrumDefinitions(std::move(specDefs));
321 return create<Workspace2D>(inst, indexInfo, Histogram(
x,
y));
328 const std::string &functionString,
bool isRandom,
332 auto angles = std::vector<double>();
333 auto timeRanges = std::vector<double>();
334 for (
int i = 0; i < numScanPoints; ++i) {
335 angles.emplace_back(
double(i));
336 timeRanges.emplace_back(
double(i + 1));
339 builder.setTimeRanges(Types::Core::DateAndTime(0), timeRanges);
340 builder.setRelativeRotationsForScans(angles, inst->getSample()->getPos(),
V3D(0, 1, 0));
342 BinEdges
x(numBins + 1, LinearGenerator(x0, binDelta));
344 std::vector<double> xValues(cbegin(
x), cend(
x) - 1);
345 Counts
y(
evalFunction(functionString, xValues, isRandom ? 1 : 0));
347 builder.setHistogram(Histogram(
x,
y));
349 return builder.buildWorkspace();
355 int numEvents,
double x0,
double binDelta,
357 const std::string &functionString,
bool isRandom) {
358 DateAndTime run_start(
"2010-01-01T00:00:00");
360 std::vector<SpectrumDefinition> specDefs(numPixels + numMonitors);
361 for (
int wi = 0; wi < numMonitors + numPixels; wi++)
362 specDefs[wi].add(wi < numMonitors ? numPixels + wi : wi - numMonitors);
363 Indexing::IndexInfo indexInfo(numPixels + numMonitors);
364 indexInfo.setSpectrumDefinitions(std::move(specDefs));
367 int numXBins = numBins + 1;
368 BinEdges
x(numXBins, LinearGenerator(x0, binDelta));
370 auto retVal = create<EventWorkspace>(inst, indexInfo,
x);
372 std::vector<double> xValues(
x.cbegin(),
x.cend() - 1);
373 std::vector<double> yValues =
evalFunction(functionString, xValues, isRandom ? 1 : 0);
377 double sum_of_elems = std::accumulate(yValues.begin(), yValues.end(), 0.0);
378 double event_distrib_factor =
numEvents / sum_of_elems;
379 using std::placeholders::_1;
380 std::transform(yValues.begin(), yValues.end(), yValues.begin(),
381 std::bind(std::multiplies<double>(), event_distrib_factor, _1));
385 size_t workspaceIndex = 0;
387 const double hourInSeconds = 60 * 60;
388 for (
int wi = 0; wi < numPixels + numMonitors; wi++) {
389 EventList &el = retVal->getSpectrum(workspaceIndex);
390 for (
int i = 0; i < numBins; ++i) {
393 auto eventsInBin =
static_cast<int>(yValues[i]);
394 for (
int q = 0; q < eventsInBin; q++) {
395 DateAndTime pulseTime = run_start + (
m_randGen->nextValue() * hourInSeconds);
396 el += TofEvent((i +
m_randGen->nextValue()) * binDelta + x0, pulseTime);
416 const std::vector<double> &xVal,
double noiseScale = 0) {
417 size_t xSize = xVal.size();
419 std::string parsedFuncString = functionString;
420 for (
int x = 0;
x <= 10; ++
x) {
422 auto index =
static_cast<int>((xSize / 10) *
x);
423 if ((
x == 10) && (
index > 0))
425 double replace_val = xVal[
index];
426 std::ostringstream tokenStream;
427 tokenStream <<
"$PC" <<
x <<
"$";
428 std::string token = tokenStream.str();
429 std::string replaceStr = boost::lexical_cast<std::string>(replace_val);
430 replaceAll(parsedFuncString, token, replaceStr);
437 func_sptr->function(fd, fv);
440 for (
size_t x = 0;
x < xSize; ++
x) {
441 if (noiseScale != 0) {
442 results[
x] += ((
m_randGen->nextValue() - 0.5) * noiseScale);
445 results[
x] =
fabs(results[
x]);
453 size_t start_pos = 0;
454 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
455 str.replace(start_pos, from.length(), to);
456 start_pos += to.length();
486 API::Progress &progress,
int numBanks,
int numMonitors,
int pixels,
double pixelDiameter,
double pixelHeight,
487 double pixelSpacing,
const double bankDistanceFromSample,
const double sourceSampleDistance,
488 const std::string &instrName) {
489 auto testInst = std::make_shared<Instrument>(instrName);
492 testInst->setReferenceFrame(std::make_shared<ReferenceFrame>(
Y,
Z,
Left,
""));
495 const double cylRadius(pixelDiameter / 2);
496 const double cylHeight(pixelHeight);
501 for (
int banknum = 1; banknum <= numBanks; banknum++) {
503 std::ostringstream bankname;
504 bankname <<
"bank" << banknum;
507 bank->
initialize(pixelShape, pixels, 0.0, pixelSpacing, pixels, 0.0, pixelSpacing, banknum * pixels * pixels,
true,
511 for (
int x = 0;
x < pixels;
x++) {
512 for (
int y = 0;
y < pixels;
y++) {
513 std::shared_ptr<Detector> detector = bank->
getAtXY(
x,
y);
516 testInst->markAsDetector(detector.get());
523 bank->
setPos(
V3D(0.0, 0.0, bankDistanceFromSample * banknum));
528 int monitorsStart = (numBanks + 1) * pixels * pixels;
533 for (
int monitorNumber = monitorsStart; monitorNumber < monitorsStart + numMonitors; monitorNumber++) {
534 std::string monitorName =
"monitor" +
std::to_string(monitorNumber - monitorsStart + 1);
536 Detector *detector =
new Detector(monitorName, monitorNumber, monitorShape, testInst.get());
538 testInst->markAsMonitor(detector);
540 testInst->add(detector);
542 detector->
setPos(
V3D(0.0, 0.0, bankDistanceFromSample * (monitorNumber - monitorsStart + 0.5)));
547 source->
setPos(
V3D(0.0, 0.0, -sourceSampleDistance));
548 testInst->add(source);
549 testInst->markAsSource(source);
553 chopper->
setPos(
V3D(0.0, 0.0, -0.25 * sourceSampleDistance));
554 testInst->add(chopper);
558 testInst->setPos(0.0, 0.0, 0.0);
559 testInst->add(sample);
560 testInst->markAsSamplePos(sample);
570 const V3D &axis,
const std::string &
id) {
571 std::ostringstream xml;
572 xml <<
"<cylinder id=\"" <<
id <<
"\">"
573 <<
"<centre-of-bottom-base x=\"" << baseCentre.
X() <<
"\" y=\"" << baseCentre.
Y() <<
"\" z=\"" << baseCentre.
Z()
575 <<
"<axis x=\"" << axis.
X() <<
"\" y=\"" << axis.
Y() <<
"\" z=\"" << axis.
Z() <<
"\"/>"
576 <<
"<radius val=\"" <<
radius <<
"\" />"
577 <<
"<height val=\"" <<
height <<
"\" />"
591 std::ostringstream xml;
592 xml <<
"<sphere id=\"" <<
id <<
"\">"
593 <<
"<centre x=\"" << centre.
X() <<
"\" y=\"" << centre.
Y() <<
"\" z=\"" << centre.
Z() <<
"\" />"
594 <<
"<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.
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.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
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, const NexusHDF5Descriptor &descriptor)
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.