/qt/widgets/mplcpp/src/Plot.cpp

https://github.com/mantidproject/mantid · C++ · 161 lines · 114 code · 19 blank · 28 comment · 14 complexity · 80b18362d99ed46930d0781156387123 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 "MantidQtWidgets/MplCpp/Plot.h"
  8. #include "MantidAPI/MatrixWorkspace_fwd.h"
  9. #include "MantidPythonInterface/core/CallMethod.h"
  10. #include "MantidPythonInterface/core/Converters/ToPyList.h"
  11. #include "MantidPythonInterface/core/GlobalInterpreterLock.h"
  12. #include "MantidQtWidgets/Common/Python/Object.h"
  13. #include "MantidQtWidgets/Common/Python/QHashToDict.h"
  14. #include "MantidQtWidgets/Common/Python/Sip.h"
  15. #include "MantidQtWidgets/MplCpp/Plot.h"
  16. #include <utility>
  17. using Mantid::API::MatrixWorkspace_sptr;
  18. using namespace Mantid::PythonInterface;
  19. using namespace MantidQt::Widgets::Common;
  20. namespace MantidQt::Widgets::MplCpp {
  21. namespace {
  22. /**
  23. * @returns The mantidqt.plotting.functions module
  24. */
  25. Python::Object functionsModule() { return Python::NewRef(PyImport_ImportModule("mantidqt.plotting.functions")); }
  26. /**
  27. * Construct a Python list from a vector of strings
  28. * @param workspaces A strings
  29. * @return A new Python list object
  30. */
  31. Python::Object constructArgs(const std::vector<std::string> &workspaces) {
  32. return Python::NewRef(Py_BuildValue("(O)", Converters::ToPyList<std::string>()(workspaces).ptr()));
  33. }
  34. /**
  35. * Construct a Python list from a vector of workspace pointers
  36. * @param workspaces A list of MatrixWorkspace_sptr
  37. * @return A new Python list object
  38. */
  39. Python::Object constructArgs(const std::vector<MatrixWorkspace_sptr> &workspaces) {
  40. return Python::NewRef(Py_BuildValue("(O)", Converters::ToPyList<MatrixWorkspace_sptr>()(workspaces).ptr()));
  41. }
  42. /**
  43. * Construct a Python list from a QStringList
  44. * @param workspaces A list of strings
  45. * @return A new Python list object
  46. */
  47. Python::Object constructArgs(const QStringList &workspaces) {
  48. const auto sipAPI = Python::Detail::sipAPI();
  49. const auto copy = new QStringList(workspaces);
  50. const auto *sobj = sipAPI->api_convert_from_new_type(copy, sipAPI->api_find_type("QStringList"), Py_None);
  51. return Python::NewRef(Py_BuildValue("(O)", sobj));
  52. }
  53. /**
  54. * Construct kwargs list for the plot function
  55. */
  56. Python::Object constructKwargs(boost::optional<std::vector<int>> spectrumNums,
  57. boost::optional<std::vector<int>> wkspIndices, boost::optional<Python::Object> fig,
  58. boost::optional<QHash<QString, QVariant>> plotKwargs,
  59. boost::optional<QHash<QString, QVariant>> axProperties,
  60. boost::optional<std::string> windowTitle, boost::optional<bool> errors,
  61. boost::optional<bool> overplot, boost::optional<bool> tiled) {
  62. // Make sure to decide whether spectrum numbers or workspace indices
  63. Python::Dict kwargs;
  64. if (spectrumNums && !wkspIndices) {
  65. kwargs["spectrum_nums"] = Converters::ToPyList<int>()(spectrumNums.get());
  66. } else if (wkspIndices && !spectrumNums) {
  67. kwargs["wksp_indices"] = Converters::ToPyList<int>()(wkspIndices.get());
  68. } else {
  69. throw std::invalid_argument("Passed spectrum numbers and workspace indices, please only pass one, "
  70. "with the other being boost::none.");
  71. }
  72. if (errors)
  73. kwargs["errors"] = errors.get();
  74. if (overplot)
  75. kwargs["overplot"] = overplot.get();
  76. if (tiled)
  77. kwargs["tiled"] = tiled.get();
  78. if (fig)
  79. kwargs["fig"] = fig.get();
  80. if (plotKwargs)
  81. kwargs["plot_kwargs"] = Python::qHashToDict(plotKwargs.get());
  82. if (axProperties)
  83. kwargs["ax_properties"] = Python::qHashToDict(axProperties.get());
  84. if (windowTitle)
  85. kwargs["window_title"] = windowTitle.get();
  86. return std::move(kwargs);
  87. }
  88. Python::Object plot(const Python::Object &args, boost::optional<std::vector<int>> spectrumNums,
  89. boost::optional<std::vector<int>> wkspIndices, boost::optional<Python::Object> fig,
  90. boost::optional<QHash<QString, QVariant>> plotKwargs,
  91. boost::optional<QHash<QString, QVariant>> axProperties, boost::optional<std::string> windowTitle,
  92. bool errors, bool overplot, bool tiled) {
  93. const auto kwargs =
  94. constructKwargs(std::move(spectrumNums), std::move(wkspIndices), std::move(fig), std::move(plotKwargs),
  95. std::move(axProperties), std::move(windowTitle), errors, overplot, tiled);
  96. try {
  97. return functionsModule().attr("plot")(*args, **kwargs);
  98. } catch (Python::ErrorAlreadySet &) {
  99. throw PythonException();
  100. }
  101. }
  102. } // namespace
  103. Python::Object plot(const std::vector<std::string> &workspaces, boost::optional<std::vector<int>> spectrumNums,
  104. boost::optional<std::vector<int>> wkspIndices, boost::optional<Python::Object> fig,
  105. boost::optional<QHash<QString, QVariant>> plotKwargs,
  106. boost::optional<QHash<QString, QVariant>> axProperties, boost::optional<std::string> windowTitle,
  107. bool errors, bool overplot, bool tiled) {
  108. GlobalInterpreterLock lock;
  109. return plot(constructArgs(workspaces), std::move(spectrumNums), std::move(wkspIndices), std::move(fig),
  110. std::move(plotKwargs), std::move(axProperties), std::move(windowTitle), errors, overplot, tiled);
  111. }
  112. Python::Object plot(const QStringList &workspaces, boost::optional<std::vector<int>> spectrumNums,
  113. boost::optional<std::vector<int>> wkspIndices, boost::optional<Python::Object> fig,
  114. boost::optional<QHash<QString, QVariant>> plotKwargs,
  115. boost::optional<QHash<QString, QVariant>> axProperties, boost::optional<std::string> windowTitle,
  116. bool errors, bool overplot, bool tiled) {
  117. GlobalInterpreterLock lock;
  118. return plot(constructArgs(workspaces), std::move(spectrumNums), std::move(wkspIndices), std::move(fig),
  119. std::move(plotKwargs), std::move(axProperties), std::move(windowTitle), errors, overplot, tiled);
  120. }
  121. Python::Object plot(const std::vector<MatrixWorkspace_sptr> &workspaces, boost::optional<std::vector<int>> spectrumNums,
  122. boost::optional<std::vector<int>> wkspIndices, boost::optional<Python::Object> fig,
  123. boost::optional<QHash<QString, QVariant>> plotKwargs,
  124. boost::optional<QHash<QString, QVariant>> axProperties, boost::optional<std::string> windowTitle,
  125. bool errors, bool overplot, bool tiled) {
  126. GlobalInterpreterLock lock;
  127. return plot(constructArgs(workspaces), std::move(spectrumNums), std::move(wkspIndices), std::move(fig),
  128. std::move(plotKwargs), std::move(axProperties), std::move(windowTitle), errors, overplot, tiled);
  129. }
  130. Python::Object pcolormesh(const QStringList &workspaces, boost::optional<Python::Object> fig) {
  131. GlobalInterpreterLock lock;
  132. try {
  133. const auto args = constructArgs(workspaces);
  134. Python::Dict kwargs;
  135. if (fig)
  136. kwargs["fig"] = fig.get();
  137. return functionsModule().attr("pcolormesh")(*args, **kwargs);
  138. } catch (Python::ErrorAlreadySet &) {
  139. throw PythonException();
  140. }
  141. }
  142. } // namespace MantidQt::Widgets::MplCpp