Mantid
Loading...
Searching...
No Matches
FitMD.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
17
20
23
24#include <algorithm>
25
26namespace Mantid::MDAlgorithms {
28
29using namespace API;
30using namespace DataObjects;
31using namespace Kernel;
32
37 : API::IDomainCreator(nullptr, std::vector<std::string>(), IDomainCreator::Simple), m_maxSize(0), m_startIndex(0),
38 m_count(0) {}
39
43FitMD::FitMD(IPropertyManager *fit, const std::string &workspacePropertyName, IDomainCreator::DomainType domainType)
44 : API::IDomainCreator(fit, std::vector<std::string>(1, workspacePropertyName), domainType), m_maxSize(0),
45 m_startIndex(0), m_count(0) {
46 if (domainType != IDomainCreator::Simple) {
47 throw std::runtime_error("FitMD only supports simple domains");
48 }
49 if (m_workspacePropertyNames.empty()) {
50 throw std::runtime_error("Cannot create FitMD: no workspace given");
51 }
53}
54
62void FitMD::initialize(Kernel::IPropertyManager *pm, const std::string &workspacePropertyName,
63 IDomainCreator::DomainType domainType) {
64 m_manager = pm;
65 m_workspacePropertyName = workspacePropertyName;
66 m_domainType = domainType;
67 m_workspacePropertyNames = std::vector<std::string>(1, workspacePropertyName);
68}
69
75void FitMD::declareDatasetProperties(const std::string &suffix, bool addProp) {
76 if (m_domainType != Simple) {
77 m_maxSizePropertyName = "MaxSize" + suffix;
79 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
80 mustBePositive->setLower(1);
82 "The maximum number of values per a simple domain.");
83 }
84 }
85}
86
93void FitMD::createDomain(std::shared_ptr<API::FunctionDomain> &domain, std::shared_ptr<API::FunctionValues> &ivalues,
94 size_t i0) {
95 UNUSED_ARG(i0);
97 auto iterator = m_IMDWorkspace->createIterator();
98 const size_t n = iterator->getDataSize();
99
100 if (m_count == 0) {
101 m_count = n;
102 }
103
105 domain.reset(dmd);
106 auto values = new API::FunctionValues(*domain);
107 ivalues.reset(values);
108
109 auto iter = dmd->getNextIterator();
110 size_t i = 0;
111 while (iter) {
112 values->setFitData(i, iter->getNormalizedSignal());
113 // there is a problem with errors in md workspaces. Until it is solved
114 // set all weights to 1.0
115 // code commented out after the next line is the normal way of setting
116 // weights
117 values->setFitWeight(i, 1.0);
118 // double err = iter->getNormalizedError();
119 // if (err <= 0.0) err = 1.0;
120 // values->setFitWeight(i,1/err);
121 iter = dmd->getNextIterator();
122 ++i;
123 };
124 dmd->reset();
125}
126
136std::shared_ptr<API::Workspace> FitMD::createOutputWorkspace(const std::string &baseName, API::IFunction_sptr function,
137 std::shared_ptr<API::FunctionDomain> domain,
138 std::shared_ptr<API::FunctionValues> values,
139 const std::string &outputWorkspacePropertyName) {
140 if (!values) {
141 return std::shared_ptr<API::Workspace>();
142 }
143 auto functionMD = std::dynamic_pointer_cast<API::FunctionDomainMD>(domain);
144 if (!functionMD) {
145 return std::shared_ptr<API::Workspace>();
146 }
147 API::IMDWorkspace_const_sptr domainWS = functionMD->getWorkspace();
148
149 auto inputEventWS = std::dynamic_pointer_cast<const API::IMDEventWorkspace>(domainWS);
150 if (inputEventWS) {
151 return createEventOutputWorkspace(baseName, *inputEventWS, *values, outputWorkspacePropertyName);
152 }
153
154 auto inputHistoWS = std::dynamic_pointer_cast<const API::IMDHistoWorkspace>(domainWS);
155 if (inputHistoWS) {
156 return createHistoOutputWorkspace(baseName, function, inputHistoWS, outputWorkspacePropertyName);
157 }
158
159 return std::shared_ptr<API::Workspace>();
160}
161
170std::shared_ptr<API::Workspace> FitMD::createEventOutputWorkspace(const std::string &baseName,
171 const API::IMDEventWorkspace &inputWorkspace,
172 const API::FunctionValues &values,
173 const std::string &outputWorkspacePropertyName) {
174 auto outputWS = MDEventFactory::CreateMDWorkspace(inputWorkspace.getNumDims(), "MDEvent");
175 // Add events
176 // TODO: Generalize to ND (the current framework is a bit limiting)
177 auto mdWS = std::dynamic_pointer_cast<DataObjects::MDEventWorkspace<DataObjects::MDEvent<4>, 4>>(outputWS);
178 if (!mdWS) {
179 return std::shared_ptr<API::Workspace>();
180 }
181
182 // Bins extents and meta data
183 for (size_t i = 0; i < 4; ++i) {
184 std::shared_ptr<const Geometry::IMDDimension> inputDim = inputWorkspace.getDimension(i);
186 builder.setName(inputDim->getName());
187 builder.setId(inputDim->getDimensionId());
188 builder.setUnits(inputDim->getUnits());
189 builder.setNumBins(inputDim->getNBins());
190 builder.setMin(inputDim->getMinimum());
191 builder.setMax(inputDim->getMaximum());
192 builder.setFrameName(inputDim->getMDFrame().name());
193
194 outputWS->addDimension(builder.create());
195 }
196
197 // Run information
198 outputWS->copyExperimentInfos(inputWorkspace);
199 // Coordinates
200 outputWS->setCoordinateSystem(inputWorkspace.getSpecialCoordinateSystem());
201 // Set sensible defaults for splitting behaviour
202 BoxController_sptr bc = outputWS->getBoxController();
203 bc->setSplitInto(3);
204 bc->setSplitThreshold(3000);
205 outputWS->initialize();
206 outputWS->splitBox();
207
208 auto inputIter = inputWorkspace.createIterator();
209 size_t resultValueIndex(0);
210 const float errorSq = 0.0;
211 do {
212 const size_t numEvents = inputIter->getNumEvents();
213 const auto signal = static_cast<float>(values.getCalculated(resultValueIndex));
214 for (size_t i = 0; i < numEvents; ++i) {
215 coord_t centers[4] = {inputIter->getInnerPosition(i, 0), inputIter->getInnerPosition(i, 1),
216 inputIter->getInnerPosition(i, 2), inputIter->getInnerPosition(i, 3)};
217 mdWS->addEvent(MDEvent<4>(signal, errorSq, inputIter->getInnerExpInfoIndex(i),
218 inputIter->getInnerGoniometerIndex(i), inputIter->getInnerDetectorID(i), centers));
219 }
220 ++resultValueIndex;
221 } while (inputIter->next());
222
223 // This splits up all the boxes according to split thresholds and sizes.
224 auto threadScheduler = new Kernel::ThreadSchedulerFIFO();
225 Kernel::ThreadPool threadPool(threadScheduler);
226 outputWS->splitAllIfNeeded(threadScheduler);
227 threadPool.joinAll();
228 outputWS->refreshCache();
229
230 // Store it
231 if (!outputWorkspacePropertyName.empty()) {
233 new API::WorkspaceProperty<API::IMDEventWorkspace>(outputWorkspacePropertyName, "", Direction::Output),
234 "Name of the output Workspace holding resulting simulated spectrum");
235 m_manager->setPropertyValue(outputWorkspacePropertyName, baseName + "Workspace");
236 m_manager->setProperty(outputWorkspacePropertyName, outputWS);
237 }
238
239 return outputWS;
240}
241
250std::shared_ptr<API::Workspace>
251FitMD::createHistoOutputWorkspace(const std::string &baseName, const API::IFunction_sptr &function,
252 const API::IMDHistoWorkspace_const_sptr &inputWorkspace,
253 const std::string &outputWorkspacePropertyName) {
254 // have to cast const away to be able to pass the workspace to the algorithm
255 API::IMDHistoWorkspace_sptr nonConstInputWS =
256 std::const_pointer_cast<API::IMDHistoWorkspace, const API::IMDHistoWorkspace>(inputWorkspace);
257 // evaluate the function on the input workspace
258 auto alg = API::AlgorithmFactory::Instance().create("EvaluateMDFunction", -1);
259 alg->setChild(true);
260 alg->setRethrows(true);
261 alg->initialize();
262 alg->setProperty("Function", function);
263 alg->setProperty("InputWorkspace", nonConstInputWS);
264 alg->setProperty("OutputWorkspace", "__FitMD_createHistoOutputWorkspace_outputWorkspace");
265 alg->execute();
266
267 // get the result
268 API::IMDHistoWorkspace_sptr outputWorkspace = alg->getProperty("OutputWorkspace");
269 // Store it
270 if (!outputWorkspacePropertyName.empty()) {
272 new API::WorkspaceProperty<API::IMDHistoWorkspace>(outputWorkspacePropertyName, "", Direction::Output),
273 "Name of the output Workspace holding resulting simulated spectrum");
274 m_manager->setPropertyValue(outputWorkspacePropertyName, baseName + "Workspace");
275 m_manager->setProperty(outputWorkspacePropertyName, outputWorkspace);
276 }
277
278 return outputWorkspace;
279}
280
285 // if property manager is set overwrite any set parameters
286 if (m_manager) {
287 if (m_workspacePropertyNames.empty()) {
288 throw std::runtime_error("Cannot create FunctionDomainMD: no workspace given");
289 }
290 // get the workspace
292 m_IMDWorkspace = std::dynamic_pointer_cast<API::IMDWorkspace>(ws);
293 if (!m_IMDWorkspace) {
294 throw std::invalid_argument("InputWorkspace must be a MatrixWorkspace.");
295 }
296 if (m_domainType != Simple) {
297 const int maxSizeInt = m_manager->getProperty(m_maxSizePropertyName);
298 m_maxSize = static_cast<size_t>(maxSizeInt);
299 }
300 }
301}
302
308void FitMD::setRange(size_t startIndex, size_t count) {
309 m_startIndex = startIndex;
310 m_count = count;
311}
312
316size_t FitMD::getDomainSize() const {
318 if (!m_IMDWorkspace)
319 throw std::runtime_error("FitMD: workspace wasn't defined");
320 auto iterator = m_IMDWorkspace->createIterator();
321 size_t n = iterator->getDataSize();
322 if (m_count != 0) {
323 if (m_startIndex + m_count > n)
324 throw std::range_error("FitMD: index is out of range");
325 n = m_count;
326 }
327 return n;
328}
329
330} // namespace Mantid::MDAlgorithms
#define DECLARE_DOMAINCREATOR(classname)
int count
counter
Definition: Matrix.cpp:37
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition: System.h:64
Implements a domain for MD functions (IFunctionMD).
const IMDIterator * getNextIterator() const
Next iterator.
void reset() const override
Reset the iterator to point to the start of the domain.
A class to store values calculated by a function.
double getCalculated(size_t i) const
Get i-th calculated value.
An base class for domain creators for use in Fit.
DomainType
Type of domain to create.
std::vector< std::string > m_workspacePropertyNames
Property names for workspaces to get the data from.
Kernel::IPropertyManager * m_manager
Pointer to a property manager.
void declareProperty(Kernel::Property *prop, const std::string &doc)
Declare a property to the algorithm.
DomainType m_domainType
Domain type.
Abstract base class for multi-dimension event workspaces (MDEventWorkspace).
virtual Kernel::SpecialCoordinateSystem getSpecialCoordinateSystem() const =0
std::unique_ptr< IMDIterator > createIterator(Mantid::Geometry::MDImplicitFunction *function=nullptr) const
Creates a single iterator and returns it.
virtual std::shared_ptr< const Mantid::Geometry::IMDDimension > getDimension(size_t index) const
Get a dimension.
Definition: MDGeometry.cpp:161
virtual size_t getNumDims() const
Definition: MDGeometry.cpp:148
A property class for workspaces.
static API::IMDEventWorkspace_sptr CreateMDWorkspace(size_t nd, const std::string &eventType="MDLeanEvent", const Mantid::API::MDNormalization &preferredNormalization=Mantid::API::MDNormalization::VolumeNormalization, const Mantid::API::MDNormalization &preferredNormalizationHisto=Mantid::API::MDNormalization::VolumeNormalization)
Create a MDEventWorkspace of the given type.
Templated class holding data about a neutron detection event in N-dimensions (for example,...
Definition: MDEvent.h:36
void setFrameName(std::string frameName)
Setter for the frame name.
void setUnits(const Kernel::UnitLabel &units)
Interface to PropertyManager.
virtual void setPropertyValue(const std::string &name, const std::string &value)=0
Sets property value from a string.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
virtual bool existsProperty(const std::string &name) const =0
Checks whether the named property is already in the list of managed property.
virtual TypedValue getProperty(const std::string &name) const =0
Get the value of a property.
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...
A Thread Pool implementation that keeps a certain number of threads running (normally,...
Definition: ThreadPool.h:36
void joinAll()
Wait for all threads that have started to finish.
Definition: ThreadPool.cpp:150
A First-In-First-Out Thread Scheduler.
FitMD()
Default constructor.
Definition: FitMD.cpp:36
void declareDatasetProperties(const std::string &suffix="", bool addProp=true) override
declare properties that specify the dataset within the workspace to fit to.
Definition: FitMD.cpp:75
std::string m_maxSizePropertyName
Store maxSize property name.
Definition: FitMD.h:84
void createDomain(std::shared_ptr< API::FunctionDomain > &, std::shared_ptr< API::FunctionValues > &, size_t i0) override
Create a domain from the input workspace.
Definition: FitMD.cpp:93
size_t m_maxSize
Max size for seq domain.
Definition: FitMD.h:88
std::shared_ptr< API::Workspace > createEventOutputWorkspace(const std::string &baseName, const API::IMDEventWorkspace &inputWorkspace, const API::FunctionValues &values, const std::string &outputWorkspacePropertyName)
Create event output workspace.
Definition: FitMD.cpp:170
size_t m_count
Size of the domain if part of the workspace is used.
Definition: FitMD.h:92
void setParameters() const
Set all parameters.
Definition: FitMD.cpp:284
std::string m_workspacePropertyName
Store workspace property name.
Definition: FitMD.h:82
std::shared_ptr< API::Workspace > createOutputWorkspace(const std::string &baseName, API::IFunction_sptr function, std::shared_ptr< API::FunctionDomain > domain, std::shared_ptr< API::FunctionValues > values, const std::string &outputWorkspacePropertyName="OutputWorkspace") override
Create an output workspace filled with data simulated with the fitting function.
Definition: FitMD.cpp:136
void initialize(Kernel::IPropertyManager *pm, const std::string &workspacePropertyName, DomainType domainType) override
Initialize.
Definition: FitMD.cpp:62
void setRange(size_t startIndex, size_t count)
Set the range.
Definition: FitMD.cpp:308
std::shared_ptr< API::Workspace > createHistoOutputWorkspace(const std::string &baseName, const API::IFunction_sptr &function, const std::shared_ptr< const API::IMDHistoWorkspace > &inputWorkspace, const std::string &outputWorkspacePropertyName)
Create histo output workspace.
Definition: FitMD.cpp:251
size_t m_startIndex
Starting index.
Definition: FitMD.h:90
std::shared_ptr< API::IMDWorkspace > m_IMDWorkspace
The input IMDWorkspace.
Definition: FitMD.h:86
size_t getDomainSize() const override
Return the size of the domain to be created.
Definition: FitMD.cpp:316
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< const IMDWorkspace > IMDWorkspace_const_sptr
Shared pointer to the IMDWorkspace base class (const version)
Definition: IMDWorkspace.h:148
std::shared_ptr< IMDHistoWorkspace > IMDHistoWorkspace_sptr
shared pointer to Mantid::API::IMDHistoWorkspace
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
std::shared_ptr< BoxController > BoxController_sptr
Shared ptr to BoxController.
std::shared_ptr< const IMDHistoWorkspace > IMDHistoWorkspace_const_sptr
shared pointer to Mantid::API::IMDHistoWorkspace (const version)
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.
float coord_t
Typedef for the data type to use for coordinate axes in MD objects such as MDBox, MDEventWorkspace,...
Definition: MDTypes.h:27
STL namespace.
@ Output
An output workspace.
Definition: Property.h:54