Mantid
Loading...
Searching...
No Matches
QENSFitSimultaneous.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 +
10
18#include "MantidAPI/TextAxis.h"
20
26
27#include <boost/algorithm/string/join.hpp>
28#include <utility>
29
30namespace {
32
33using namespace Mantid::API;
34
35void extractFunctionNames(const CompositeFunction_sptr &composite, std::vector<std::string> &names) {
36 for (auto i = 0u; i < composite->nFunctions(); ++i)
37 names.emplace_back(composite->getFunction(i)->name());
38}
39
40void extractFunctionNames(const IFunction_sptr &function, std::vector<std::string> &names) {
41 auto composite = std::dynamic_pointer_cast<CompositeFunction>(function);
42 if (composite)
43 extractFunctionNames(composite, names);
44 else
45 names.emplace_back(function->name());
46}
47
48void extractConvolvedNames(const IFunction_sptr &function, std::vector<std::string> &names);
49
50void extractConvolvedNames(const CompositeFunction_sptr &composite, std::vector<std::string> &names) {
51 for (auto i = 0u; i < composite->nFunctions(); ++i)
52 extractConvolvedNames(composite->getFunction(i), names);
53}
54
55void extractConvolvedNames(const IFunction_sptr &function, std::vector<std::string> &names) {
56 auto composite = std::dynamic_pointer_cast<CompositeFunction>(function);
57 if (composite) {
58 if (composite->name() == "Convolution" && composite->nFunctions() > 1 &&
59 composite->getFunction(0)->name() == "Resolution")
60 extractFunctionNames(composite->getFunction(1), names);
61 else
62 extractConvolvedNames(composite, names);
63 }
64}
65
66MatrixWorkspace_sptr convertSpectrumAxis(const MatrixWorkspace_sptr &inputWorkspace) {
67 auto convSpec = AlgorithmManager::Instance().create("ConvertSpectrumAxis");
68 convSpec->setLogging(false);
69 convSpec->setChild(true);
70 convSpec->setProperty("InputWorkspace", inputWorkspace);
71 convSpec->setProperty("OutputWorkspace", "__converted");
72 convSpec->setProperty("Target", "ElasticQ");
73 convSpec->setProperty("EMode", "Indirect");
74 convSpec->execute();
75 return convSpec->getProperty("OutputWorkspace");
76}
77
78MatrixWorkspace_sptr convertToElasticQ(const MatrixWorkspace_sptr &inputWorkspace, bool doThrow) {
79 auto axis = inputWorkspace->getAxis(1);
80 if (axis->isSpectra())
81 return convertSpectrumAxis(inputWorkspace);
82 else if (axis->isNumeric()) {
83 if (axis->unit()->unitID() != "MomentumTransfer" && doThrow)
84 throw std::runtime_error("Input must have axis values of Q");
85 return inputWorkspace->clone();
86 } else if (doThrow)
87 throw std::runtime_error("Input workspace must have either spectra or numeric axis.");
88 return inputWorkspace->clone();
89}
90
91struct ElasticQAppender {
92 explicit ElasticQAppender(std::vector<MatrixWorkspace_sptr> &elasticInput)
93 : m_elasticInput(elasticInput), m_converted() {}
94
95 void operator()(const MatrixWorkspace_sptr &workspace, bool doThrow) {
96 auto it = m_converted.find(workspace.get());
97 if (it != m_converted.end())
98 m_elasticInput.emplace_back(it->second);
99 else {
100 auto elasticQ = convertToElasticQ(workspace, doThrow);
101 m_elasticInput.emplace_back(elasticQ);
102 m_converted[workspace.get()] = elasticQ;
103 }
104 }
105
106private:
107 std::vector<MatrixWorkspace_sptr> &m_elasticInput;
108 std::unordered_map<MatrixWorkspace *, MatrixWorkspace_sptr> m_converted;
109};
110
111std::vector<MatrixWorkspace_sptr> convertToElasticQ(const std::vector<MatrixWorkspace_sptr> &workspaces, bool doThrow) {
112 std::vector<MatrixWorkspace_sptr> elasticInput;
113 auto appendElasticQWorkspace = ElasticQAppender(elasticInput);
114 appendElasticQWorkspace(workspaces[0], doThrow);
115
116 for (auto i = 1u; i < workspaces.size(); ++i)
117 appendElasticQWorkspace(workspaces[i], doThrow);
118 return elasticInput;
119}
120
121std::string shortParameterName(const std::string &longName) {
122 return longName.substr(longName.rfind('.') + 1, longName.size());
123}
124
126 const std::string &suffix) {
127 fit.setProperty("InputWorkspace" + suffix, workspace);
128
129 int workspaceIndex = qensFit.getProperty("WorkspaceIndex" + suffix);
130 fit.setProperty("WorkspaceIndex" + suffix, workspaceIndex);
131
132 double startX = qensFit.getProperty("StartX" + suffix);
133 double endX = qensFit.getProperty("EndX" + suffix);
134 fit.setProperty("StartX" + suffix, startX);
135 fit.setProperty("EndX" + suffix, endX);
136
137 std::vector<double> exclude = qensFit.getProperty("Exclude" + suffix);
138 fit.setProperty("Exclude" + suffix, exclude);
139}
140
141void setMultiDataProperties(const IAlgorithm &qensFit, IAlgorithm &fit,
142 const std::vector<MatrixWorkspace_sptr> &workspaces) {
143 setMultiDataProperties(qensFit, fit, workspaces[0], "");
144
145 for (auto i = 1u; i < workspaces.size(); ++i)
146 setMultiDataProperties(qensFit, fit, workspaces[i], "_" + std::to_string(i));
147}
148
149IFunction_sptr convertToSingleDomain(IFunction_sptr function) {
150 auto composite = std::dynamic_pointer_cast<CompositeFunction>(function);
151 if (composite && composite->getNumberDomains() > 1)
152 return composite->getFunction(0);
153 return function;
154}
155
157 auto group = std::dynamic_pointer_cast<WorkspaceGroup>(workspace);
158 if (group)
159 return group;
161 group->addWorkspace(workspace);
162 return group;
163}
164
165ITableWorkspace_sptr transposeFitTable(const ITableWorkspace_sptr &table, const IFunction &function,
166 const std::string &yAxisType) {
167 auto transposed = WorkspaceFactory::Instance().createTable();
168 transposed->addColumn(yAxisType, "axis-1");
169
170 auto parameters = function.getParameterNames();
171 for (const auto &parameter : parameters) {
172 transposed->addColumn("double", parameter);
173 transposed->addColumn("double", parameter + "_Err");
174 }
175
176 auto numberOfParameters = parameters.size();
177 for (std::size_t i = 0; i < table->rowCount() - 1; i += numberOfParameters) {
178 auto row = transposed->appendRow().m_row;
179
180 for (auto j = 0u; j < numberOfParameters; ++j) {
181 auto column = 1 + j * 2;
182 transposed->Double(row, column) = table->Double(i + j, 1);
183 transposed->Double(row, column + 1) = table->Double(i + j, 2);
184 }
185 }
186 return transposed;
187}
188
189std::string getAxisType(const MatrixWorkspace &workspace, std::size_t axisIndex) {
190 return workspace.getAxis(axisIndex)->isNumeric() ? "double" : "str";
191}
192
193NumericAxis const *getNumericAxis(const MatrixWorkspace &workspace, std::size_t axisIndex) {
194 return dynamic_cast<NumericAxis const *>(workspace.getAxis(axisIndex));
195}
196
197TextAxis const *getTextAxis(const MatrixWorkspace &workspace, std::size_t axisIndex) {
198 return dynamic_cast<TextAxis const *>(workspace.getAxis(axisIndex));
199}
200
201std::vector<std::string> getUniqueWorkspaceNames(std::vector<std::string> &&workspaceNames) {
202 std::set<std::string> uniqueNames(workspaceNames.begin(), workspaceNames.end());
203 workspaceNames.assign(uniqueNames.begin(), uniqueNames.end());
204 return std::move(workspaceNames);
205}
206
207auto getNumericAxisValueReader(std::size_t axisIndex) {
208 return [axisIndex](const MatrixWorkspace &workspace, std::size_t index) {
209 if (auto const axis = getNumericAxis(workspace, axisIndex))
210 return axis->getValue(index);
211 return 0.0;
212 };
213}
214
215auto getTextAxisValueReader(std::size_t axisIndex) {
216 return [axisIndex](const MatrixWorkspace &workspace, std::size_t index) {
217 if (auto const axis = getTextAxis(workspace, axisIndex))
218 return axis->label(index);
219 return std::string();
220 };
221}
222
223template <typename T, typename GetValue>
224void addValuesToColumn(Column &column, const std::vector<MatrixWorkspace_sptr> &workspaces,
225 const Mantid::API::Algorithm &indexProperties, const GetValue &getValue) {
226 const std::string prefix = "WorkspaceIndex";
227
228 int index = indexProperties.getProperty(prefix);
229 column.cell<T>(0) = getValue(*workspaces.front(), static_cast<std::size_t>(index));
230
231 for (auto i = 1u; i < workspaces.size(); ++i) {
232 const auto indexName = prefix + "_" + std::to_string(i);
233 index = indexProperties.getProperty(indexName);
234 column.cell<T>(i) = getValue(*workspaces[i], static_cast<std::size_t>(index));
235 }
236}
237
238void addValuesToTableColumn(ITableWorkspace &table, const std::vector<MatrixWorkspace_sptr> &workspaces,
239 const Mantid::API::Algorithm &indexProperties, std::size_t columnIndex) {
240 if (workspaces.empty())
241 return;
242
243 const auto column = table.getColumn(columnIndex);
244 if (getNumericAxis(*workspaces.front(), 1))
245 addValuesToColumn<double>(*column, workspaces, indexProperties, getNumericAxisValueReader(1));
246 else if (getTextAxis(*workspaces.front(), 1))
247 addValuesToColumn<std::string>(*column, workspaces, indexProperties, getTextAxisValueReader(1));
248}
249
250std::vector<std::size_t> createDatasetGrouping(const std::vector<MatrixWorkspace_sptr> &workspaces) {
251 std::vector<std::size_t> grouping;
252 grouping.emplace_back(0);
253 for (auto i = 1u; i < workspaces.size(); ++i) {
254 if (workspaces[i] != workspaces[i - 1])
255 grouping.emplace_back(i);
256 }
257 grouping.emplace_back(workspaces.size());
258 return grouping;
259}
260
261WorkspaceGroup_sptr createGroup(const std::vector<MatrixWorkspace_sptr> &workspaces) {
263 for (auto &&workspace : workspaces)
264 group->addWorkspace(workspace);
265 return group;
266}
267
268WorkspaceGroup_sptr runParameterProcessingWithGrouping(IAlgorithm &processingAlgorithm,
269 const std::vector<std::size_t> &grouping) {
270 std::vector<MatrixWorkspace_sptr> results;
271 results.reserve(grouping.size() - 1);
272 for (auto i = 0u; i < grouping.size() - 1; ++i) {
273 processingAlgorithm.setProperty("StartRowIndex", static_cast<int>(grouping[i]));
274 processingAlgorithm.setProperty("EndRowIndex", static_cast<int>(grouping[i + 1]) - 1);
275 processingAlgorithm.setProperty("OutputWorkspace", "__Result");
276 processingAlgorithm.execute();
277 results.emplace_back(processingAlgorithm.getProperty("OutputWorkspace"));
278 }
279 return createGroup(results);
280}
281} // namespace
282
284
285using namespace API;
286using namespace Kernel;
287
288// Register the algorithm into the AlgorithmFactory
289DECLARE_ALGORITHM(QENSFitSimultaneous)
290
291
292const std::string QENSFitSimultaneous::name() const { return "QENSFitSimultaneous"; }
293
295int QENSFitSimultaneous::version() const { return 1; }
296
298const std::string QENSFitSimultaneous::category() const { return "Workflow\\MIDAS"; }
299
301const std::string QENSFitSimultaneous::summary() const { return "Performs a simultaneous QENS fit"; }
302
304const std::vector<std::string> QENSFitSimultaneous::seeAlso() const {
305 return {"ConvolutionFitSimultaneous", "IqtFitSimultaneous", "Fit"};
306}
307
308void QENSFitSimultaneous::initConcrete() {
310 getPointerToProperty("Ties")->setDocumentation("Math expressions defining ties between parameters of "
311 "the fitting function.");
312 declareProperty("Constraints", "", Kernel::Direction::Input);
313 getPointerToProperty("Constraints")->setDocumentation("List of constraints");
314 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<int>>();
315 mustBePositive->setLower(0);
316 declareProperty("MaxIterations", 500, mustBePositive->clone(),
317 "Stop after this number of iterations if a good fit is not found");
318
319 std::vector<std::string> minimizerOptions = API::FuncMinimizerFactory::Instance().getKeys();
320 Kernel::IValidator_sptr minimizerValidator = std::make_shared<Kernel::StartsWithValidator>(minimizerOptions);
321
322 declareProperty("Minimizer", "Levenberg-Marquardt", minimizerValidator, "Minimizer to use for fitting.");
323 declareProperty("CalcErrors", false,
324 "Set to true to calcuate errors when output isn't created "
325 "(default is false).");
326 declareProperty("ExtractMembers", false,
327 "If true, then each member of the fit will be extracted"
328 ", into their own workspace. These workspaces will have a histogram"
329 " for each spectrum (Q-value) and will be grouped.",
331 declareProperty(std::make_unique<Kernel::PropertyWithValue<bool>>("ConvolveMembers", false),
332 "If true members of any "
333 "Convolution are output convolved\n"
334 "with corresponding resolution");
335 declareProperty("OutputCompositeMembers", false,
336 "If true and CreateOutput is true then the value of each "
337 "member of a Composite Function is also output.");
338
339 std::vector<std::string> unitOptions = UnitFactory::Instance().getKeys();
340 unitOptions.emplace_back("");
341 declareProperty("ResultXAxisUnit", "MomentumTransfer", std::make_shared<StringListValidator>(unitOptions),
342 "The unit to assign to the X Axis of the result workspace, "
343 "defaults to MomentumTransfer");
344
345 declareProperty(std::make_unique<WorkspaceProperty<WorkspaceGroup>>("OutputWorkspace", "", Direction::Output),
346 "The output result workspace(s)");
347 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("OutputParameterWorkspace", "",
349 "The output parameter workspace");
350 declareProperty(std::make_unique<WorkspaceProperty<WorkspaceGroup>>("OutputWorkspaceGroup", "", Direction::Output,
352 "The output group workspace");
353
354 declareProperty("OutputFitStatus", true,
355 "Flag to output fit status information, which consists of the fit "
356 "OutputStatus and the OutputChiSquared");
357
358 std::vector<std::string> costFuncOptions = API::CostFunctionFactory::Instance().getKeys();
359 // select only CostFuncFitting variety
360 for (auto &costFuncOption : costFuncOptions) {
361 auto costFunc = std::dynamic_pointer_cast<CostFunctions::CostFuncFitting>(
363 if (!costFunc) {
364 costFuncOption = "";
365 }
366 }
367 Kernel::IValidator_sptr costFuncValidator = std::make_shared<Kernel::ListValidator<std::string>>(costFuncOptions);
368 declareProperty("CostFunction", "Least squares", costFuncValidator,
369 "The cost function to be used for the fit, default is Least squares", Kernel::Direction::InOut);
370}
371
372void QENSFitSimultaneous::execConcrete() {
373 const auto outputBaseName = getOutputBaseName();
374
375 if (!outputBaseName.empty()) {
376 if (getPropertyValue("OutputParameterWorkspace").empty())
377 setProperty("OutputParameterWorkspace", outputBaseName + "_Parameters");
378
379 if (getPropertyValue("OutputWorkspaceGroup").empty())
380 setProperty("OutputWorkspaceGroup", outputBaseName + "_Workspaces");
381 }
382
383 const auto inputWorkspaces = getWorkspaces();
384 const auto workspaces = convertInputToElasticQ(inputWorkspaces);
385 const auto singleDomainFunction = convertToSingleDomain(getProperty("Function"));
386
387 const auto fitResult = performFit(inputWorkspaces, outputBaseName);
388 const auto yAxisType = getAxisType(*workspaces.front(), 1);
389 auto transposedTable = transposeFitTable(fitResult.first, *singleDomainFunction, yAxisType);
390 addValuesToTableColumn(*transposedTable, workspaces, *this, 0);
391 const auto parameterWs = processParameterTable(transposedTable);
392 const auto groupWs = makeGroup(fitResult.second);
393 const auto resultWs = processIndirectFitParameters(parameterWs, createDatasetGrouping(workspaces));
394 AnalysisDataService::Instance().addOrReplace(getPropertyValue("OutputWorkspace"), resultWs);
395
396 if (containsMultipleData(workspaces)) {
397 renameWorkspaces(groupWs, getWorkspaceIndices(), outputBaseName, "_Workspace", getWorkspaceNames());
398 auto inputWorkspaceNames = getUniqueWorkspaceNames(getWorkspaceNames());
399 renameWorkspaces(resultWs, std::vector<std::string>(inputWorkspaceNames.size(), ""), outputBaseName, "_Result",
400 inputWorkspaceNames);
401 } else {
402 renameWorkspaces(resultWs, std::vector<std::string>({""}), outputBaseName, "_Result");
403 }
404
405 copyLogs(resultWs, workspaces);
406
407 const bool doExtractMembers = getProperty("ExtractMembers");
408 if (doExtractMembers)
409 extractMembers(groupWs, workspaces, outputBaseName + "_Members");
410
411 addAdditionalLogs(resultWs);
412 copyLogs(std::dynamic_pointer_cast<MatrixWorkspace>(resultWs->getItem(0)), groupWs);
413
414 setProperty("OutputWorkspace", resultWs);
415 setProperty("OutputParameterWorkspace", parameterWs);
416 setProperty("OutputWorkspaceGroup", groupWs);
417}
418
419std::pair<API::ITableWorkspace_sptr, API::Workspace_sptr>
420QENSFitSimultaneous::performFit(const std::vector<MatrixWorkspace_sptr> &workspaces, const std::string &output) {
421 IFunction_sptr function = getProperty("Function");
422 const bool convolveMembers = getProperty("ConvolveMembers");
423 const bool outputCompositeMembers = getProperty("OutputCompositeMembers");
424 const bool ignoreInvalidData = getProperty("IgnoreInvalidData");
425 const bool calcErrors = getProperty("CalcErrors");
426
427 auto fit = createChildAlgorithm("Fit", 0.05, 0.90, true);
428 fit->setProperty("Function", function);
429 setMultiDataProperties(*this, *fit, workspaces);
430 fit->setProperty("IgnoreInvalidData", ignoreInvalidData);
431 fit->setProperty("DomainType", getPropertyValue("DomainType"));
432 fit->setProperty("EvaluationType", getPropertyValue("EvaluationType"));
433 fit->setPropertyValue("PeakRadius", getPropertyValue("PeakRadius"));
434 fit->setProperty("Ties", getPropertyValue("Ties"));
435 fit->setProperty("Constraints", getPropertyValue("Constraints"));
436 fit->setPropertyValue("MaxIterations", getPropertyValue("MaxIterations"));
437 fit->setProperty("Minimizer", getPropertyValue("Minimizer"));
438 fit->setProperty("CostFunction", getPropertyValue("CostFunction"));
439 fit->setProperty("CalcErrors", calcErrors);
440 fit->setProperty("OutputCompositeMembers", outputCompositeMembers);
441 fit->setProperty("ConvolveMembers", convolveMembers);
442 fit->setProperty("CreateOutput", true);
443 fit->setProperty("Output", output);
444 fit->executeAsChildAlg();
445
446 std::string status = fit->getProperty("OutputStatus");
447 double chiSquared = fit->getProperty("OutputChi2overDoF");
448
449 const bool outputFitStatus = getProperty("OutputFitStatus");
450 if (outputFitStatus) {
451 declareProperty("OutputStatus", "", Direction::Output);
452 declareProperty("OutputChiSquared", 0.0, Direction::Output);
453 setProperty("OutputStatus", status);
454 setProperty("OutputChiSquared", chiSquared);
455 }
456
457 if (workspaces.size() == 1) {
458 MatrixWorkspace_sptr outputWS = fit->getProperty("OutputWorkspace");
459 return {fit->getProperty("OutputParameters"), outputWS};
460 }
461
462 WorkspaceGroup_sptr outputWS = fit->getProperty("OutputWorkspace");
463 return {fit->getProperty("OutputParameters"), outputWS};
464}
465
466WorkspaceGroup_sptr QENSFitSimultaneous::processIndirectFitParameters(const ITableWorkspace_sptr &parameterWorkspace,
467 const std::vector<std::size_t> &grouping) {
468 std::string const xAxisUnit = getProperty("ResultXAxisUnit");
469 auto pifp = createChildAlgorithm("ProcessIndirectFitParameters", 0.91, 0.95, false);
470 pifp->setAlwaysStoreInADS(false);
471 pifp->setProperty("InputWorkspace", parameterWorkspace);
472 pifp->setProperty("ColumnX", "axis-1");
473 pifp->setProperty("XAxisUnit", xAxisUnit);
474 pifp->setProperty("ParameterNames", getFitParameterNames());
475 pifp->setProperty("IncludeChiSquared", true);
476 return runParameterProcessingWithGrouping(*pifp, grouping);
477}
478
479void QENSFitSimultaneous::copyLogs(const WorkspaceGroup_sptr &resultWorkspace,
480 const std::vector<MatrixWorkspace_sptr> &workspaces) {
481 auto logCopier = createChildAlgorithm("CopyLogs", -1.0, -1.0, false);
482 for (auto &&result : *resultWorkspace) {
483 logCopier->setProperty("OutputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(result));
484 for (const auto &workspace : workspaces) {
485 logCopier->setProperty("InputWorkspace", workspace);
486 logCopier->executeAsChildAlg();
487 }
488 }
489}
490
491void QENSFitSimultaneous::copyLogs(const MatrixWorkspace_sptr &resultWorkspace,
492 const WorkspaceGroup_sptr &resultGroup) {
493 auto logCopier = createChildAlgorithm("CopyLogs", -1.0, -1.0, false);
494 logCopier->setProperty("InputWorkspace", resultWorkspace);
495
496 for (const auto &workspace : *resultGroup) {
497 logCopier->setProperty("OutputWorkspace", std::dynamic_pointer_cast<MatrixWorkspace>(workspace));
498 logCopier->executeAsChildAlg();
499 }
500}
501
502void QENSFitSimultaneous::extractMembers(const WorkspaceGroup_sptr &resultGroupWs,
503 const std::vector<MatrixWorkspace_sptr> &workspaces,
504 const std::string &outputWsName) {
505 std::vector<std::string> workspaceNames;
506 for (auto i = 0u; i < workspaces.size(); ++i) {
507 auto name = "__result_members_" + std::to_string(i);
508 AnalysisDataService::Instance().addOrReplace(name, workspaces[i]);
509 workspaceNames.emplace_back(name);
510 }
511
512 auto extractAlgorithm = extractMembersAlgorithm(resultGroupWs, outputWsName);
513 extractAlgorithm->setProperty("InputWorkspaces", workspaceNames);
514 extractAlgorithm->execute();
515
516 for (const auto &workspaceName : workspaceNames)
517 AnalysisDataService::Instance().remove(workspaceName);
518}
519
520void QENSFitSimultaneous::addAdditionalLogs(const API::WorkspaceGroup_sptr &group) {
521 for (auto &&workspace : *group)
523}
524
525void QENSFitSimultaneous::addAdditionalLogs(const Workspace_sptr &resultWorkspace) {
526 auto logAdder = createChildAlgorithm("AddSampleLog", -1.0, -1.0, false);
527 logAdder->setProperty("Workspace", resultWorkspace);
528
529 Progress logAdderProg(this, 0.99, 1.00, 6);
530 logAdder->setProperty("LogType", "String");
531 for (const auto &log : getAdditionalLogStrings()) {
532 logAdder->setProperty("LogName", log.first);
533 logAdder->setProperty("LogText", log.second);
534 logAdder->executeAsChildAlg();
535 logAdderProg.report("Add text logs");
536 }
537
538 logAdder->setProperty("LogType", "Number");
539 for (const auto &log : getAdditionalLogNumbers()) {
540 logAdder->setProperty("LogName", log.first);
541 logAdder->setProperty("LogText", log.second);
542 logAdder->executeAsChildAlg();
543 logAdderProg.report("Add number logs");
544 }
545}
546
547IAlgorithm_sptr QENSFitSimultaneous::extractMembersAlgorithm(const WorkspaceGroup_sptr &resultGroupWs,
548 const std::string &outputWsName) const {
549 const bool convolved = getProperty("ConvolveMembers");
550 std::vector<std::string> convolvedMembers;
551 IFunction_sptr function = getProperty("Function");
552
553 if (convolved)
554 extractConvolvedNames(function, convolvedMembers);
555
556 auto extractMembersAlg = AlgorithmManager::Instance().create("ExtractQENSMembers");
557 extractMembersAlg->setProperty("ResultWorkspace", resultGroupWs);
558 extractMembersAlg->setProperty("OutputWorkspace", outputWsName);
559 extractMembersAlg->setProperty("RenameConvolvedMembers", convolved);
560 extractMembersAlg->setProperty("ConvolvedMembers", convolvedMembers);
561 return extractMembersAlg;
562}
563
564std::vector<MatrixWorkspace_sptr> QENSFitSimultaneous::getWorkspaces() const {
565 std::vector<MatrixWorkspace_sptr> workspaces;
566 workspaces.reserve(m_workspacePropertyNames.size());
567 for (const auto &propertyName : m_workspacePropertyNames) {
568 Workspace_sptr workspace = getProperty(propertyName);
569 workspaces.emplace_back(std::dynamic_pointer_cast<MatrixWorkspace>(workspace));
570 }
571 return workspaces;
572}
573
574std::vector<std::string> QENSFitSimultaneous::getWorkspaceIndices() const {
575 std::vector<std::string> workspaceIndices;
576 workspaceIndices.reserve(m_workspaceIndexPropertyNames.size());
577 for (const auto &propertName : m_workspaceIndexPropertyNames) {
578 std::string workspaceIndex = getPropertyValue(propertName);
579 workspaceIndices.emplace_back(workspaceIndex);
580 }
581 return workspaceIndices;
582}
583
584std::vector<std::string> QENSFitSimultaneous::getWorkspaceNames() const {
585 std::vector<std::string> workspaceNames;
586 workspaceNames.reserve(m_workspacePropertyNames.size());
587 for (const auto &propertName : m_workspacePropertyNames) {
588 std::string workspaceName = getPropertyValue(propertName);
589 workspaceNames.emplace_back(workspaceName);
590 }
591 return workspaceNames;
592}
593
594std::vector<MatrixWorkspace_sptr>
595QENSFitSimultaneous::convertInputToElasticQ(const std::vector<MatrixWorkspace_sptr> &workspaces) const {
596 return convertToElasticQ(workspaces, throwIfElasticQConversionFails());
597}
598
599std::string QENSFitSimultaneous::getOutputBaseName() const {
600 const auto base = getPropertyValue("OutputWorkspace");
601 auto position = base.rfind("_Result");
602 if (position != std::string::npos)
603 return base.substr(0, position);
604 return base;
605}
606
607bool QENSFitSimultaneous::throwIfElasticQConversionFails() const { return false; }
608
609bool QENSFitSimultaneous::isFitParameter(const std::string & /*unused*/) const { return true; }
610
611std::vector<std::string> QENSFitSimultaneous::getFitParameterNames() const {
612 const auto uniqueParameters = getUniqueParameterNames();
613 std::vector<std::string> parameters;
614 parameters.reserve(uniqueParameters.size());
615 std::copy_if(uniqueParameters.begin(), uniqueParameters.end(), std::back_inserter(parameters),
616 [&](const std::string &parameter) { return isFitParameter(parameter); });
617 return parameters;
618}
619
620std::set<std::string> QENSFitSimultaneous::getUniqueParameterNames() const {
621 IFunction_sptr function = getProperty("Function");
622 std::set<std::string> nameSet;
623 for (auto i = 0u; i < function->nParams(); ++i)
624 nameSet.insert(shortParameterName(function->parameterName(i)));
625 return nameSet;
626}
627
628std::map<std::string, std::string> QENSFitSimultaneous::getAdditionalLogStrings() const {
629 const bool convolve = getProperty("ConvolveMembers");
630 auto fitProgram = name();
631 fitProgram = fitProgram.substr(0, fitProgram.rfind("Simultaneous"));
632
633 auto logs = std::map<std::string, std::string>();
634 logs["convolve_members"] = convolve ? "true" : "false";
635 logs["fit_program"] = fitProgram;
636 logs["fit_mode"] = "Simultaneous";
637 return logs;
638}
639
640std::map<std::string, std::string> QENSFitSimultaneous::getAdditionalLogNumbers() const {
641 return std::map<std::string, std::string>();
642}
643
644ITableWorkspace_sptr QENSFitSimultaneous::processParameterTable(ITableWorkspace_sptr parameterTable) {
645 return parameterTable;
646}
647
648void QENSFitSimultaneous::renameWorkspaces(const API::WorkspaceGroup_sptr &outputGroup,
649 std::vector<std::string> const &spectra, std::string const &outputBaseName,
650 std::string const &endOfSuffix,
651 std::vector<std::string> const &inputWorkspaceNames) {
652 auto rename = createChildAlgorithm("RenameWorkspace", -1.0, -1.0, false);
653 const auto getNameSuffix = [&](std::size_t i) {
654 std::string workspaceName = inputWorkspaceNames[i] + "_" + spectra[i] + endOfSuffix;
655 return workspaceName;
656 };
657 return renameWorkspacesInQENSFit(this, rename, outputGroup, outputBaseName, endOfSuffix + "s", getNameSuffix);
658}
659
660void QENSFitSimultaneous::renameWorkspaces(const API::WorkspaceGroup_sptr &outputGroup,
661 std::vector<std::string> const &spectra, std::string const &outputBaseName,
662 std::string const &endOfSuffix) {
663 auto rename = createChildAlgorithm("RenameWorkspace", -1.0, -1.0, false);
664 auto getNameSuffix = [&](std::size_t i) { return spectra[i] + endOfSuffix; };
665 return renameWorkspacesInQENSFit(this, rename, outputGroup, outputBaseName, endOfSuffix + "s", getNameSuffix);
666}
667
668} // namespace Mantid::CurveFitting::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
double position
Definition: GetAllEi.cpp:154
IPeaksWorkspace_sptr workspace
Definition: IndexPeaks.cpp:114
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
Kernel::Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
Definition: Algorithm.cpp:2033
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Definition: Algorithm.cpp:842
Column is the base class for columns of TableWorkspace.
Definition: Column.h:35
T & cell(size_t index)
Templated method for returning a value. No type checks are done.
Definition: Column.h:127
IAlgorithm is the interface implemented by the Algorithm base class.
Definition: IAlgorithm.h:45
virtual void executeAsChildAlg()=0
Execute as a Child Algorithm, with try/catch.
virtual bool execute()=0
System execution.
This is an interface to a fitting function - a semi-abstarct class.
Definition: IFunction.h:163
std::vector< std::string > getParameterNames() const
Return a vector with all parameter names.
Definition: IFunction.cpp:551
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
virtual Column_sptr getColumn(const std::string &name)=0
Gets the shared pointer to a column by name.
Base MatrixWorkspace Abstract Class.
Class to represent a numeric axis of a workspace.
Definition: NumericAxis.h:29
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
Class to represent a text axis of a workspace.
Definition: TextAxis.h:36
Class to hold a set of workspaces.
A property class for workspaces.
QENSFitSimultaneous - Algorithm for performing a simultaneous QENS fit.
void copyLogs(const API::WorkspaceGroup_sptr &resultWorkspace, const std::vector< API::MatrixWorkspace_sptr > &workspaces)
void renameWorkspaces(const API::WorkspaceGroup_sptr &outputGroup, std::vector< std::string > const &spectra, std::string const &outputBaseName, std::string const &endOfSuffix, std::vector< std::string > const &inputWorkspaceNames)
std::vector< API::MatrixWorkspace_sptr > convertInputToElasticQ(const std::vector< API::MatrixWorkspace_sptr > &workspaces) const
virtual std::vector< std::string > getFitParameterNames() const
void addAdditionalLogs(const API::WorkspaceGroup_sptr &group)
std::pair< API::ITableWorkspace_sptr, API::Workspace_sptr > performFit(const std::vector< API::MatrixWorkspace_sptr > &workspaces, const std::string &output)
virtual std::vector< API::MatrixWorkspace_sptr > getWorkspaces() const
void extractMembers(const API::WorkspaceGroup_sptr &resultGroupWs, const std::vector< API::MatrixWorkspace_sptr > &workspaces, const std::string &outputWsName)
virtual std::map< std::string, std::string > getAdditionalLogStrings() const
virtual std::map< std::string, std::string > getAdditionalLogNumbers() const
API::IAlgorithm_sptr extractMembersAlgorithm(const API::WorkspaceGroup_sptr &resultGroupWs, const std::string &outputWsName) const
const std::string name() const override
Algorithms name for identification.
API::WorkspaceGroup_sptr processIndirectFitParameters(const API::ITableWorkspace_sptr &parameterWorkspace, const std::vector< std::size_t > &grouping)
virtual API::ITableWorkspace_sptr processParameterTable(API::ITableWorkspace_sptr parameterTable)
std::vector< std::string > m_workspacePropertyNames
std::vector< std::string > m_workspaceIndexPropertyNames
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 TypedValue getProperty(const std::string &name) const =0
Get the value of a property.
The Logger class is in charge of the publishing messages from the framework through various channels.
Definition: Logger.h:52
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
The concrete, templated class for properties.
void setDocumentation(const std::string &documentation)
Sets the user level description of the property.
Definition: Property.cpp:134
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
void renameWorkspacesInQENSFit(Algorithm *qensFit, IAlgorithm_sptr renameAlgorithm, const WorkspaceGroup_sptr &outputGroup, std::string const &outputBaseName, std::string const &groupSuffix, std::function< std::string(std::size_t)> const &getNameSuffix)
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
Kernel::Logger g_log("ExperimentInfo")
static logger object
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
bool containsMultipleData(const std::vector< MatrixWorkspace_sptr > &workspaces)
std::shared_ptr< CompositeFunction > CompositeFunction_sptr
shared pointer to the composite function base class
void setMultiDataProperties(const Mantid::API::IAlgorithm &fittingAlgorithm, Mantid::API::IAlgorithm &fit, const Mantid::API::MatrixWorkspace_sptr &workspace, const std::string &suffix)
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
Mantid::API::NumericAxis * getNumericAxis(int const &numberOfLabels, std::vector< double > const &values)
Mantid::API::TextAxis * getTextAxis(int const &numberOfSpectra, std::vector< std::string > const &labels)
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition: IValidator.h:26
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54