13#include "MantidAlgorithms/DllConfig.h"
23#include <unsupported/Eigen/AutoDiff>
27namespace PolarizationCorrectionsHelpers {
29 const std::string &spinStateOrder,
30 const std::string &targetSpinState);
33namespace FlipperConfigurations {
34static const std::string
OFF_ON =
"01";
35static const std::string
ON_OFF =
"10";
37static const std::string
ON_ON =
"11";
38static const std::string
OFF =
"0";
39static const std::string
ON =
"1";
42namespace SpinStateConfigurationsFredrikze {
47static const std::string
PARA =
"p";
48static const std::string
ANTI =
"a";
51namespace SpinStateConfigurationsWildes {
56static const std::string
MINUS =
"-";
57static const std::string
PLUS =
"+";
60namespace SpinStatesORSO {
64static const std::string
PP =
"pp";
65static const std::string
PM =
"pm";
66static const std::string
MP =
"mp";
67static const std::string
MM =
"mm";
68static const std::string
PO =
"po";
69static const std::string
MO =
"mo";
71static const std::string
LOG_NAME =
"spin_state_ORSO";
75 const std::string &spinState);
80template <
typename Prov
ider,
typename InputArray,
typename CovarianceMatrix>
82 std::invocable<Provider, const InputArray &, const InputArray &> &&
83 std::convertible_to<std::invoke_result_t<Provider, const InputArray &, const InputArray &>, CovarianceMatrix>;
87 using DerType = Eigen::Matrix<double, N, 1>;
89 using ADScalar = Eigen::AutoDiffScalar<DerType>;
95 static_assert(
sizeof...(DependentFuncs) == DependentVars,
"Number of dependent functions must match DependentVars");
97 static constexpr size_t TotalVars = IndependentVars + DependentVars;
102 using ADScalar =
typename IndependentTypes::ADScalar;
110 CovarianceMatrix covariance = inputErrors.array().square().matrix().asDiagonal();
112 const auto derivatives =
dependentDerivatives(functionInputs, std::make_index_sequence<DependentVars>{});
114 for (
size_t dep = 0; dep < DependentVars; ++dep) {
115 const size_t depIndex = IndependentVars + dep;
116 for (
size_t independent = 0; independent < IndependentVars; ++independent) {
117 const double covarianceWithIndependent =
118 derivatives[dep][independent] * inputErrors[independent] * inputErrors[independent];
119 covariance(independent, depIndex) = covarianceWithIndependent;
120 covariance(depIndex, independent) = covarianceWithIndependent;
125 for (
size_t depA = 0; depA < DependentVars; ++depA) {
126 const size_t depAIndex = IndependentVars + depA;
127 for (
size_t depB = depA + 1; depB < DependentVars; ++depB) {
128 const size_t depBIndex = IndependentVars + depB;
129 double covarianceBetweenDependents = 0.0;
130 for (
size_t independent = 0; independent < IndependentVars; ++independent) {
131 covarianceBetweenDependents += derivatives[depA][independent] * derivatives[depB][independent] *
132 inputErrors[independent] * inputErrors[independent];
134 covariance(depAIndex, depBIndex) = covarianceBetweenDependents;
135 covariance(depBIndex, depAIndex) = covarianceBetweenDependents;
145 for (
size_t i = 0; i < IndependentVars; ++i) {
146 functionInputs[i] =
ADScalar(inputValues[i], IndependentDerType::Unit(IndependentVars, i));
148 for (
size_t i = IndependentVars; i <
TotalVars; ++i) {
149 functionInputs[i] =
ADScalar(inputValues[i], IndependentDerType::Zero());
151 return functionInputs;
154 template <
typename Func>
156 static_assert(std::invocable<Func, const FunctionInput &>,
157 "Dependent functions must accept the covariance provider input values");
158 return func(functionInputs);
161 template <
size_t... Indices>
163 std::index_sequence<Indices...>)
const {
175template <
size_t IndependentVars,
size_t DependentVars,
typename... DependentFuncs>
178 std::forward<DependentFuncs>(dependentFuncs)...);
201 std::array<ADScalar, N>
x;
202 for (
size_t i = 0; i < N; ++i) {
203 x[i] =
ADScalar(values[i], DerType::Unit(N, i));
206 const auto &derivatives =
y.derivatives();
209 const double variance = derivatives.dot(covariance * derivatives);
210 return {
y.value(), std::sqrt(std::max(variance, 0.0)), derivatives};
213 template <std::same_as<API::MatrixWorkspace_sptr>... Ts>
216 std::forward<Ts>(args)...);
219 template <std::same_as<API::MatrixWorkspace_sptr>... Ts>
224 template <
typename Prov
ider, std::same_as<API::MatrixWorkspace_sptr>... Ts>
227 Provider covarianceMatrixProvider, Ts... args)
const {
228 return evaluateWorkspacesImpl(outputWorkspaceDistribution, covarianceMatrixProvider, std::forward<Ts>(args)...);
231 template <
typename Prov
ider, std::same_as<API::MatrixWorkspace_sptr>... Ts>
240 return errors.array().square().matrix().asDiagonal();
250 template <
typename Prov
ider, std::same_as<API::MatrixWorkspace_sptr>... Ts>
253 Provider covarianceMatrixProvider, Ts... args)
const {
254 const auto firstWs = std::get<0>(std::forward_as_tuple(args...));
257 if (outWs->id() ==
"EventWorkspace") {
261 const size_t numSpec = outWs->getNumberHistograms();
262 const size_t specSize = outWs->blocksize();
267 const bool specOverBins = numSpec > specSize;
270 for (int64_t i = 0; i < static_cast<int64_t>(numSpec); i++) {
271 auto &yOut = outWs->mutableY(i);
272 auto &eOut = outWs->mutableE(i);
275 for (int64_t j = 0; j < static_cast<int64_t>(specSize); ++j) {
278 const CovarianceMatrix covariance = covarianceMatrixProvider(values, errors);
280 yOut[j] = result.value;
281 eOut[j] = result.error;
285 if (outputWorkspaceDistribution.has_value()) {
286 outWs->setDistribution(outputWorkspaceDistribution.value());
292 const std::string &algName)
const {
293 auto conversionAlg = API::AlgorithmManager::Instance().create(algName);
294 conversionAlg->initialize();
295 conversionAlg->setChild(
true);
296 conversionAlg->setProperty(
"InputWorkspace",
workspace);
297 conversionAlg->setProperty(
"OutputWorkspace",
workspace->getName());
298 conversionAlg->execute();
299 return conversionAlg->getProperty(
"OutputWorkspace");
IPeaksWorkspace_sptr workspace
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
typename IndependentTypes::DerType IndependentDerType
FunctionInput makeFunctionInput(const InputArray &inputValues) const
static constexpr size_t TotalVars
typename IndependentTypes::ADScalar ADScalar
CovarianceMatrix operator()(const InputArray &inputValues, const InputArray &inputErrors) const
std::array< ADScalar, TotalVars > FunctionInput
ErrorTypeHelper< TotalVars > Types
CovarianceMatrixProvider(DependentFuncs... dependentFuncs)
ErrorTypeHelper< IndependentVars > IndependentTypes
typename Types::InputArray InputArray
ADScalar evaluateDependentFunction(Func const &func, const FunctionInput &functionInputs) const
std::tuple< DependentFuncs... > m_dependentFuncs
typename Types::CovarianceMatrix CovarianceMatrix
std::array< IndependentDerType, DependentVars > dependentDerivatives(const FunctionInput &functionInputs, std::index_sequence< Indices... >) const
API::MatrixWorkspace_sptr evaluateWorkspacesWithCovariance(const bool outputWorkspaceDistribution, Provider covarianceMatrixProvider, Ts... args) const
AutoDevResult evaluate(const InputArray &values, const InputArray &errors) const
API::MatrixWorkspace_sptr runWorkspaceConversionAlg(const API::MatrixWorkspace_sptr &workspace, const std::string &algName) const
AutoDevResult evaluateWithCovariance(const InputArray &values, const CovarianceMatrix &covariance) const
API::MatrixWorkspace_sptr evaluateWorkspaces(Ts... args) const
API::MatrixWorkspace_sptr evaluateWorkspacesWithCovariance(Provider covarianceMatrixProvider, Ts... args) const
Types::InputArray InputArray
ErrorTypeHelper< N > Types
API::MatrixWorkspace_sptr evaluateWorkspaces(const bool outputWorkspaceDistribution, Ts... args) const
Types::CovarianceMatrix CovarianceMatrix
ErrorPropagation(Func func)
API::MatrixWorkspace_sptr evaluateWorkspacesImpl(std::optional< bool > outputWorkspaceDistribution, Provider covarianceMatrixProvider, Ts... args) const
static CovarianceMatrix independentCovarianceMatrixProvider(const InputArray &, const InputArray &errors)
static CovarianceMatrix covarianceMatrixFromErrors(const InputArray &errors)
API::MatrixWorkspace_sptr convertToWorkspace2D(const API::MatrixWorkspace_sptr &workspace) const
Eigen::Matrix< double, N, 1 > DerType
Eigen::AutoDiffScalar< DerType > ADScalar
Eigen::Matrix< double, N, N > CovarianceMatrix
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
auto makeCovarianceMatrixProvider(DependentFuncs &&...dependentFuncs)
auto makeErrorPropagation(Func &&func)
static const std::string ON_OFF
static const std::string OFF_ON
static const std::string OFF_OFF
static const std::string ON_ON
static const std::string OFF
static const std::string ON
MANTID_ALGORITHMS_DLL API::MatrixWorkspace_sptr workspaceForSpinState(const API::WorkspaceGroup_sptr &group, const std::string &spinStateOrder, const std::string &targetSpinState)
Returns the workspace in the group associated with the given targetSpinState according to the order d...
static const std::string PARA_PARA
static const std::string ANTI
static const std::string PARA_ANTI
static const std::string ANTI_ANTI
static const std::string PARA
static const std::string ANTI_PARA
static const std::string MINUS_MINUS
static const std::string PLUS_MINUS
static const std::string PLUS_PLUS
static const std::string MINUS_PLUS
static const std::string PLUS
static const std::string MINUS
static const std::string LOG_NAME
static const std::string MO
static const std::string PO
static const std::string PM
MANTID_ALGORITHMS_DLL void addORSOLogForSpinState(const Mantid::API::MatrixWorkspace_sptr &ws, const std::string &spinState)
static const std::string MM
MANTID_ALGORITHMS_DLL const std::string & getORSONotationForSpinState(const std::string &spinState)
static const std::string PP
static const std::string MP
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
Eigen::Array< double, N, 1 > derivatives