PageRenderTime 57ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/qt/scientific_interfaces/Indirect/IndirectFitOutputOptionsModel.cpp

https://github.com/mantidproject/mantid
C++ | 329 lines | 258 code | 65 blank | 6 comment | 36 complexity | 6424298e36a0e97ac9183b53ab97f8c6 MD5 | raw file
  1. // Mantid Repository : https://github.com/mantidproject/mantid
  2. //
  3. // Copyright © 2019 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 +
  7. #include "IndirectFitOutputOptionsModel.h"
  8. #include <utility>
  9. #include "MantidAPI/AlgorithmManager.h"
  10. #include "MantidAPI/AnalysisDataService.h"
  11. #include "MantidAPI/Axis.h"
  12. #include "MantidAPI/TextAxis.h"
  13. #include "MantidAPI/Workspace.h"
  14. #include <memory>
  15. using namespace Mantid::API;
  16. namespace {
  17. std::string noWorkspaceErrorMessage(std::string const &process) {
  18. return "The " + process + " of a workspace failed:\n\n No workspace found";
  19. }
  20. MatrixWorkspace_sptr convertToMatrixWorkspace(const Workspace_sptr &workspace) {
  21. return std::dynamic_pointer_cast<MatrixWorkspace>(workspace);
  22. }
  23. WorkspaceGroup_sptr convertToGroupWorkspace(const Workspace_sptr &workspace) {
  24. return std::dynamic_pointer_cast<WorkspaceGroup>(workspace);
  25. }
  26. Workspace_sptr getADSWorkspace(std::string const &workspaceName) {
  27. return AnalysisDataService::Instance().retrieveWS<Workspace>(workspaceName);
  28. }
  29. MatrixWorkspace_sptr getADSMatrixWorkspace(std::string const &workspaceName) {
  30. return convertToMatrixWorkspace(getADSWorkspace(workspaceName));
  31. }
  32. WorkspaceGroup_sptr getADSGroupWorkspace(std::string const &workspaceName) {
  33. return convertToGroupWorkspace(getADSWorkspace(workspaceName));
  34. }
  35. std::unordered_map<std::string, std::size_t> extractAxisLabels(Axis *axis) {
  36. auto const *textAxis = static_cast<TextAxis *>(axis);
  37. std::unordered_map<std::string, std::size_t> labels;
  38. for (auto i = 0u; i < textAxis->length(); ++i)
  39. labels[textAxis->label(i)] = i;
  40. return labels;
  41. }
  42. std::unordered_map<std::string, std::size_t> extractAxisLabels(const MatrixWorkspace_const_sptr &workspace,
  43. std::size_t const &axisIndex) {
  44. auto const axis = workspace->getAxis(axisIndex);
  45. if (axis->isText())
  46. return extractAxisLabels(axis);
  47. return std::unordered_map<std::string, std::size_t>();
  48. }
  49. std::vector<std::string> extractParameterNames(Axis *axis) {
  50. auto const *textAxis = boost::static_pointer_cast<TextAxis>(axis);
  51. std::vector<std::string> parameters;
  52. for (auto i = 0u; i < textAxis->length(); ++i)
  53. parameters.emplace_back(textAxis->label(i));
  54. return parameters;
  55. }
  56. std::vector<std::string> extractParameterNames(const MatrixWorkspace_sptr &workspace) {
  57. auto const axis = workspace->getAxis(1);
  58. if (axis->isText())
  59. return extractParameterNames(axis);
  60. return std::vector<std::string>();
  61. }
  62. std::vector<std::string> extractParameterNames(const Workspace_sptr &workspace) {
  63. return extractParameterNames(convertToMatrixWorkspace(workspace));
  64. }
  65. IAlgorithm_sptr saveNexusProcessedAlgorithm(const Workspace_sptr &workspace, std::string const &filename) {
  66. auto saveAlg = AlgorithmManager::Instance().create("SaveNexusProcessed");
  67. saveAlg->setProperty("InputWorkspace", workspace);
  68. saveAlg->setProperty("Filename", filename);
  69. return saveAlg;
  70. }
  71. void saveWorkspace(const Workspace_sptr &workspace) {
  72. auto const filename =
  73. Mantid::Kernel::ConfigService::Instance().getString("defaultsave.directory") + workspace->getName() + ".nxs";
  74. saveNexusProcessedAlgorithm(workspace, filename)->execute();
  75. }
  76. void saveWorkspacesInGroup(const WorkspaceGroup_const_sptr &group) {
  77. for (auto const &workspace : *group)
  78. saveWorkspace(workspace);
  79. }
  80. bool workspaceIsPlottable(const MatrixWorkspace_const_sptr &workspace) { return workspace->y(0).size() > 1; }
  81. bool containsPlottableWorkspace(const WorkspaceGroup_const_sptr &groupWorkspace) {
  82. return std::any_of(groupWorkspace->begin(), groupWorkspace->end(),
  83. [](auto const &workspace) { return workspaceIsPlottable(convertToMatrixWorkspace(workspace)); });
  84. }
  85. std::vector<std::string> validateInputs(std::string const &inputWorkspaceName,
  86. std::string const &singleFitWorkspaceName, std::string const &outputName) {
  87. std::vector<std::string> errors;
  88. if (inputWorkspaceName.empty())
  89. errors.emplace_back("Select a valid input workspace.");
  90. if (singleFitWorkspaceName.empty())
  91. errors.emplace_back("Select a valid Single Fit Result workspace.");
  92. if (outputName.empty())
  93. errors.emplace_back("Enter a valid output workspace name.");
  94. return errors;
  95. }
  96. IAlgorithm_sptr replaceAlgorithm(const MatrixWorkspace_sptr &inputWorkspace,
  97. const MatrixWorkspace_sptr &singleFitWorkspace, std::string const &outputName) {
  98. auto replaceAlg = AlgorithmManager::Instance().create("IndirectReplaceFitResult");
  99. replaceAlg->setProperty("InputWorkspace", inputWorkspace);
  100. replaceAlg->setProperty("SingleFitWorkspace", singleFitWorkspace);
  101. replaceAlg->setProperty("OutputWorkspace", outputName);
  102. return replaceAlg;
  103. }
  104. template <typename Predicate> void removeVectorElements(std::vector<std::string> &strings, Predicate const &filter) {
  105. strings.erase(std::remove_if(strings.begin(), strings.end(), filter), strings.end());
  106. }
  107. bool doesStringEndWith(std::string const &str, std::string const &delimiter) {
  108. if (str.size() > delimiter.size())
  109. return str.substr(str.size() - delimiter.size(), str.size()) == delimiter;
  110. return false;
  111. }
  112. std::vector<std::string> filterByEndSuffix(std::vector<std::string> &strings, std::string const &delimiter) {
  113. removeVectorElements(strings, [&delimiter](std::string const &str) { return !doesStringEndWith(str, delimiter); });
  114. return strings;
  115. }
  116. bool doesGroupContain(std::string const &groupName, const MatrixWorkspace_sptr &workspace) {
  117. auto const adsWorkspace = getADSWorkspace(groupName);
  118. if (adsWorkspace->isGroup()) {
  119. auto const group = std::dynamic_pointer_cast<WorkspaceGroup>(adsWorkspace);
  120. return group->contains(workspace);
  121. }
  122. return false;
  123. }
  124. std::string filterByContents(std::vector<std::string> &strings, MatrixWorkspace_sptr workspace) {
  125. removeVectorElements(strings, [&workspace](std::string const &str) { return !doesGroupContain(str, workspace); });
  126. return !strings.empty() ? strings[0] : "";
  127. }
  128. std::string findGroupWorkspaceContaining(MatrixWorkspace_sptr workspace) {
  129. auto workspaceNames = AnalysisDataService::Instance().getObjectNames();
  130. auto resultGroups = filterByEndSuffix(workspaceNames, "_Results");
  131. return !resultGroups.empty() ? filterByContents(resultGroups, std::move(workspace)) : "";
  132. }
  133. } // namespace
  134. namespace MantidQt::CustomInterfaces::IDA {
  135. IndirectFitOutputOptionsModel::IndirectFitOutputOptionsModel() : m_resultGroup(), m_pdfGroup(), m_spectraToPlot() {}
  136. void IndirectFitOutputOptionsModel::setResultWorkspace(WorkspaceGroup_sptr groupWorkspace) {
  137. m_resultGroup = groupWorkspace;
  138. }
  139. void IndirectFitOutputOptionsModel::setPDFWorkspace(WorkspaceGroup_sptr groupWorkspace) { m_pdfGroup = groupWorkspace; }
  140. WorkspaceGroup_sptr IndirectFitOutputOptionsModel::getResultWorkspace() const { return m_resultGroup; }
  141. WorkspaceGroup_sptr IndirectFitOutputOptionsModel::getPDFWorkspace() const { return m_pdfGroup; }
  142. void IndirectFitOutputOptionsModel::removePDFWorkspace() { m_pdfGroup.reset(); }
  143. bool IndirectFitOutputOptionsModel::isSelectedGroupPlottable(std::string const &selectedGroup) const {
  144. return isResultGroupSelected(selectedGroup) ? isResultGroupPlottable() : isPDFGroupPlottable();
  145. }
  146. bool IndirectFitOutputOptionsModel::isResultGroupPlottable() const {
  147. if (m_resultGroup)
  148. return containsPlottableWorkspace(m_resultGroup);
  149. return false;
  150. }
  151. bool IndirectFitOutputOptionsModel::isPDFGroupPlottable() const {
  152. if (m_pdfGroup)
  153. return containsPlottableWorkspace(m_pdfGroup);
  154. return false;
  155. }
  156. void IndirectFitOutputOptionsModel::clearSpectraToPlot() { m_spectraToPlot.clear(); }
  157. std::vector<SpectrumToPlot> IndirectFitOutputOptionsModel::getSpectraToPlot() const { return m_spectraToPlot; }
  158. void IndirectFitOutputOptionsModel::plotResult(std::string const &plotType) {
  159. if (m_resultGroup)
  160. plotResult(m_resultGroup, plotType);
  161. else
  162. throw std::runtime_error(noWorkspaceErrorMessage("plotting"));
  163. }
  164. void IndirectFitOutputOptionsModel::plotResult(const WorkspaceGroup_const_sptr &groupWorkspace,
  165. std::string const &plotType) {
  166. if (plotType == "All")
  167. plotAll(groupWorkspace);
  168. else
  169. plotParameter(groupWorkspace, plotType);
  170. }
  171. void IndirectFitOutputOptionsModel::plotAll(const WorkspaceGroup_const_sptr &groupWorkspace) {
  172. for (auto const &workspace : *groupWorkspace)
  173. plotAll(convertToMatrixWorkspace(workspace));
  174. }
  175. void IndirectFitOutputOptionsModel::plotAll(const MatrixWorkspace_const_sptr &workspace) {
  176. if (workspaceIsPlottable(workspace))
  177. plotAllSpectra(workspace);
  178. }
  179. void IndirectFitOutputOptionsModel::plotAllSpectra(const MatrixWorkspace_const_sptr &workspace) {
  180. for (auto index = 0u; index < workspace->getNumberHistograms(); ++index) {
  181. auto const plotInfo = std::make_pair(workspace->getName(), index);
  182. m_spectraToPlot.emplace_back(plotInfo);
  183. }
  184. }
  185. void IndirectFitOutputOptionsModel::plotParameter(const WorkspaceGroup_const_sptr &groupWorkspace,
  186. std::string const &parameter) {
  187. for (auto const &workspace : *groupWorkspace)
  188. plotParameter(convertToMatrixWorkspace(workspace), parameter);
  189. }
  190. void IndirectFitOutputOptionsModel::plotParameter(const MatrixWorkspace_const_sptr &workspace,
  191. std::string const &parameter) {
  192. if (workspaceIsPlottable(workspace))
  193. plotParameterSpectrum(workspace, parameter);
  194. }
  195. void IndirectFitOutputOptionsModel::plotParameterSpectrum(const MatrixWorkspace_const_sptr &workspace,
  196. std::string const &parameter) {
  197. auto const parameters = extractAxisLabels(workspace, 1);
  198. auto const iter = parameters.find(parameter);
  199. if (iter != parameters.end()) {
  200. auto const plotInfo = std::make_pair(workspace->getName(), iter->second);
  201. m_spectraToPlot.emplace_back(plotInfo);
  202. }
  203. }
  204. void IndirectFitOutputOptionsModel::plotPDF(std::string const &workspaceName, std::string const &plotType) {
  205. if (m_pdfGroup) {
  206. auto const workspace = m_pdfGroup->getItem(workspaceName);
  207. plotPDF(convertToMatrixWorkspace(workspace), plotType);
  208. } else
  209. throw std::runtime_error(noWorkspaceErrorMessage("plotting"));
  210. }
  211. void IndirectFitOutputOptionsModel::plotPDF(const MatrixWorkspace_const_sptr &workspace, std::string const &plotType) {
  212. if (plotType == "All")
  213. plotAll(workspace);
  214. else
  215. plotParameter(workspace, plotType);
  216. }
  217. void IndirectFitOutputOptionsModel::saveResult() const {
  218. if (m_resultGroup)
  219. saveWorkspacesInGroup(m_resultGroup);
  220. else
  221. throw std::runtime_error(noWorkspaceErrorMessage("saving"));
  222. }
  223. std::vector<std::string> IndirectFitOutputOptionsModel::getWorkspaceParameters(std::string const &selectedGroup) const {
  224. if (isResultGroupSelected(selectedGroup) && m_resultGroup)
  225. return extractParameterNames(m_resultGroup->getItem(0));
  226. else if (!isResultGroupSelected(selectedGroup) && m_pdfGroup)
  227. return extractParameterNames(m_pdfGroup->getItem(0));
  228. return std::vector<std::string>();
  229. }
  230. std::vector<std::string> IndirectFitOutputOptionsModel::getPDFWorkspaceNames() const {
  231. if (m_pdfGroup)
  232. return m_pdfGroup->getNames();
  233. return std::vector<std::string>();
  234. }
  235. bool IndirectFitOutputOptionsModel::isResultGroupSelected(std::string const &selectedGroup) const {
  236. return selectedGroup == "Result Group";
  237. }
  238. void IndirectFitOutputOptionsModel::replaceFitResult(std::string const &inputName, std::string const &singleBinName,
  239. std::string const &outputName) {
  240. auto const errors = validateInputs(inputName, singleBinName, outputName);
  241. if (errors.empty())
  242. replaceFitResult(getADSMatrixWorkspace(inputName), getADSMatrixWorkspace(singleBinName), outputName);
  243. else
  244. throw std::runtime_error(errors[0]);
  245. }
  246. void IndirectFitOutputOptionsModel::replaceFitResult(const MatrixWorkspace_sptr &inputWorkspace,
  247. const MatrixWorkspace_sptr &singleFitWorkspace,
  248. std::string const &outputName) {
  249. auto const replaceAlg = replaceAlgorithm(inputWorkspace, singleFitWorkspace, outputName);
  250. replaceAlg->execute();
  251. setOutputAsResultWorkspace(replaceAlg);
  252. }
  253. void IndirectFitOutputOptionsModel::setOutputAsResultWorkspace(const IAlgorithm_sptr &algorithm) {
  254. auto const outputName = algorithm->getPropertyValue("OutputWorkspace");
  255. auto const output = getADSMatrixWorkspace(outputName);
  256. setResultWorkspace(findGroupWorkspaceContaining(output));
  257. }
  258. void IndirectFitOutputOptionsModel::setResultWorkspace(std::string const &groupName) {
  259. if (!groupName.empty())
  260. setResultWorkspace(getADSGroupWorkspace(groupName));
  261. else
  262. throw std::runtime_error("The result group could not be found in the ADS.");
  263. }
  264. } // namespace MantidQt::CustomInterfaces::IDA