26#include <boost/math/distributions/students_t.hpp>
33using namespace Kernel;
43constexpr auto PXD{
"PXD"};
73 std::string funcStr =
"name=ExpDecay,";
74 const std::string params =
77 return FunctionFactory::Instance().createInitialized(funcStr);
81 const auto efficiencyFunc =
"name=UserFunction,Formula=(1 + tanh(" +
std::to_string(
mu) +
"*phe*x))/2";
82 return FunctionFactory::Instance().createInitializedMultiDomainFunction(efficiencyFunc, numberOfDomains);
86 const std::vector<double> &HePolarization,
87 const std::vector<double> &HePolarizationErrors) {
88 const HistogramData::Points xVals(time);
89 const HistogramData::Frequencies yVals(HePolarization);
90 const HistogramData::FrequencyStandardDeviations eVals(
91 HePolarizationErrors.empty() ? std::vector<double>(HePolarization.size()) : HePolarizationErrors);
92 auto retVal = std::make_shared<DataObjects::Workspace2D>();
93 retVal->initialize(1, HistogramData::Histogram(xVals, yVals, eVals));
94 retVal->setPointStandardDeviations(0, timeErrors.empty() ? std::vector<double>(time.size()) : timeErrors);
101constexpr size_t NUM_FIT_PARAMS = 1;
104 const std::string &spinStates) {
105 using namespace PolarizationCorrectionsHelpers;
106 using namespace FlipperConfigurations;
108 const auto t11Ws = workspaceForSpinState(groupWorkspace, spinStates,
ON_ON);
109 const auto t10Ws = workspaceForSpinState(groupWorkspace, spinStates,
ON_OFF);
110 const auto t01Ws = workspaceForSpinState(groupWorkspace, spinStates,
OFF_ON);
111 const auto t00Ws = workspaceForSpinState(groupWorkspace, spinStates,
OFF_OFF);
119 return tnsfWs / (tnsfWs + tsfWs);
123WorkspaceGroup_sptr prepareOutputGroup(
const std::vector<MatrixWorkspace_sptr> &workspaces,
const std::string &baseName,
124 const std::string &suffix =
"") {
128 auto outputName = [&](
const size_t index) -> std::string {
130 : (workspaces.size() > 1 &&
index == workspaces.size() - 1
131 ? baseName + Fitting::OUTPUT_DECAY_FIT + suffix +
"_0"
135 const auto group = std::make_shared<WorkspaceGroup>();
137 AnalysisDataService::Instance().addOrReplace(outputName(
index), workspaces.at(
index));
149 "List of Polarized Transmission Group Workspaces. Each item on the list must be a workspace group "
151 "each one representing a spin state.");
152 const auto spinValidator = std::make_shared<SpinStateValidator>(std::unordered_set<int>{4});
155 "Order of individual spin configurations in the input group workspaces, e.g. \"01,11,00,10\", it is assumed"
156 " that all input workspaces have the same spin order.");
160 const auto mustBePositive = std::make_shared<BoundedValidator<double>>();
161 mustBePositive->setLower(0);
164 "Gas pressure in bar multiplied by cell length in metres");
166 "Error in gas pressure (p x d)");
168 "Initial decay time for He3 Polarization decay fit");
170 "Initial polarization for He3 Polarization decay fit");
172 "Lower boundary of wavelength range to use for fitting helium polarization");
174 "Upper boundary of wavelength range to use for fitting helium polarization");
176 "Whether the algorithm should ignore a poor chi-squared (fit cost value) of greater than 1 and "
177 "therefore not throw an error");
183 "Helium analyzer efficiency as a function of wavelength");
187 "A group workspace containing the fit curves.");
191 "A table workspace containing the fit parameters.");
222 std::map<std::string, std::string> errorList;
224 const auto polSANSValidator = std::make_shared<PolSANSWorkspaceValidator>();
225 for (
const auto &wsName : inputWorkspaces) {
226 const auto ws = AnalysisDataService::Instance().retrieveWS<
WorkspaceGroup>(wsName);
229 }
else if (
const auto polSANSError = polSANSValidator->isValid(ws); !polSANSError.empty()) {
237 if (tables.size() == 1) {
243 combineTableAlg->initialize();
244 combineTableAlg->setProperty(
"LHSWorkspace", tables.at(0));
245 combineTableAlg->setProperty(
"RHSWorkspace", tables.at(1));
246 combineTableAlg->execute();
249 return std::dynamic_pointer_cast<ITableWorkspace>(table);
254 timeDiff->initialize();
255 timeDiff->setProperty(
"InputWorkspaces", wsNames);
260 const auto colThours = table->getColumn(
"hours");
261 const auto colThoursErr = table->getColumn(
"hours_error");
262 auto tHours = colThours->numeric_fill();
263 auto tHoursErr = colThoursErr->numeric_fill();
264 return std::make_pair(tHours, tHoursErr);
275 if (efficiencies.size() > 1) {
280 logger.notice(
"Only one input workspace provided, polarization decay can't be fit as it is a 2 parameter fit.");
288 !outputCurvesBaseName.empty()) {
292 !outputParamsBaseName.empty()) {
300 const std::vector<MatrixWorkspace_sptr> &efficiencies) {
301 const auto numberOfDomains = efficiencies.size();
305 fit->setProperty(
"Function", multiDomainFunc->asString());
315 const auto &fitParameters = std::dynamic_pointer_cast<ITableWorkspace>(
m_outputParameters.at(0));
316 const auto colPhe = fitParameters->getColumn(
"Value");
317 const auto colPheError = fitParameters->getColumn(
"Error");
318 const auto pHe = colPhe->numeric_fill(numberOfDomains);
319 const auto pHeError = colPheError->numeric_fill(numberOfDomains);
320 return std::make_pair(pHe, pHeError);
335 const auto extractParameters =
340 fitAlgorithm->setProperty(
"CreateOutput", extractParameters || extractCurves);
341 fitAlgorithm->setProperty(
"OutputParametersOnly", !extractCurves);
343 fitAlgorithm->execute();
345 if (
const std::string status = fitAlgorithm->getProperty(
"OutputStatus");
346 !ignoreFitQualityError && (!fitAlgorithm->isExecuted() || status !=
"success")) {
347 throw std::runtime_error(
"Failed to fit to data in the fitting of" + fitOutputName +
" : " + status);
350 if (extractParameters) {
359 for (
int i = 0; i < fitCurves->getNumberOfEntries(); i++) {
360 m_outputCurves.push_back(std::dynamic_pointer_cast<MatrixWorkspace>(fitCurves->getItem(i)));
373 if (numberOfBins > NUM_FIT_PARAMS) {
374 const boost::math::students_t dist(
static_cast<double>(numberOfBins) -
static_cast<double>(NUM_FIT_PARAMS));
376 const double alpha = (1 + std::erf(1.0 / sqrt(2))) / 2;
378 tPpf = boost::math::quantile(dist, alpha);
380 logger.warning(
"The number of histogram bins must be greater than " +
std::to_string(NUM_FIT_PARAMS) +
381 " in order to provide an accurate error calculation");
386std::vector<MatrixWorkspace_sptr>
388 const std::string &spinConfiguration) {
389 std::vector<MatrixWorkspace_sptr> efficiencies(workspaceNames.size());
391 const auto inputGroupWs = AnalysisDataService::Instance().retrieveWS<
WorkspaceGroup>(workspaceNames.at(
index));
392 efficiencies.at(
index) = calculateAnalyserEfficiency(inputGroupWs, spinConfiguration);
399 const std::vector<double> &pHeVec,
400 const std::vector<double> &pHeErrorVec,
405 const auto pHe = pHeVec.at(
index);
406 const auto pHeError = pHeErrorVec.at(
index);
407 const auto eff = efficiencies.at(
index);
409 const auto &pointData = eff->histogram(0).points();
410 const auto &binPoints = pointData.rawData();
411 const auto &binBoundaries = eff->x(0);
413 auto &theoreticalEff = eff->mutableY(0);
414 auto &efficiencyErrors = eff->mutableE(0);
418 for (
size_t i = 0; i < binPoints.size(); ++i) {
419 const double lambda = binPoints[i];
420 const double lambdaError = binBoundaries[i + 1] - binBoundaries[i];
422 theoreticalEff[i] = (1 + std::tanh(
mu * pHe *
lambda)) / 2.0;
425 const auto commonTerm = 0.5 / std::pow(std::cosh(
mu *
lambda * pHe), 2);
426 const double de_dpHe =
mu * commonTerm *
lambda;
427 const double de_dmu = pHe * commonTerm *
lambda;
428 const double de_dlambda =
mu * pHe * commonTerm;
430 efficiencyErrors[i] =
431 tCrit * std::sqrt(de_dpHe * de_dpHe * pHeError * pHeError + de_dmu * de_dmu * muError * muError +
432 de_dlambda * de_dlambda * lambdaError * lambdaError);
#define DECLARE_ALGORITHM(classname)
const std::vector< double > * lambda
IPeaksWorkspace_sptr workspace
std::map< DeltaEMode::Type, std::string > index
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
bool isDefault(const std::string &name) const
Class to hold a set of workspaces.
A property class for workspaces.
void fitDecayTime(const MatrixWorkspace_sptr &workspace)
VectorPair getTimeDifferences(const std::vector< std::string > &wsNames)
std::map< std::string, std::string > validateInputs() override
Tests that the inputs are all valid.
void declareOutputProperties()
void init() override
Virtual method - must be overridden by concrete algorithm.
HeliumAnalyserEfficiency()
VectorPair fitHe3Polarization(const double mu, const std::vector< MatrixWorkspace_sptr > &efficiencies)
std::vector< MatrixWorkspace_sptr > calculateEfficiencies(const std::vector< std::string > &workspaceNames, const std::string &spinConfiguration)
ITableWorkspace_sptr prepareOutputTable(const std::vector< ITableWorkspace_sptr > &tables)
void declareFitProperties()
void convertToTheoreticalEfficiencies(const std::vector< MatrixWorkspace_sptr > &efficiencies, const std::vector< double > &pHeVec, const std::vector< double > &pHeErrorVec, const double mu)
void exec() override
Virtual method - must be overridden by concrete algorithm.
void prepareOutputs(const std::vector< MatrixWorkspace_sptr > &efficiencies)
std::vector< ITableWorkspace_sptr > m_outputParameters
std::vector< MatrixWorkspace_sptr > m_outputCurves
void declareInputProperties()
double calculateTCrit(const size_t numberOfBins) const
void makeFit(const Algorithm_sptr &fitAlgorithm, const std::string &fitOutputName)
Support for a property that holds an array of values.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void setPropertyGroup(const std::string &name, const std::string &group)
Set the group for a given property.
The Logger class is in charge of the publishing messages from the framework through various channels.
std::shared_ptr< WorkspaceGroup > WorkspaceGroup_sptr
shared pointer to Mantid::API::WorkspaceGroup
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
constexpr double PXD_ERROR_INITIAL
constexpr double END_WAVELENGTH_INITIAL
std::shared_ptr< IFunction > prepareExpDecayFunction(const double initialDecay, const double initialPolarization)
MatrixWorkspace_sptr createFitDecayWorkspace(const std::vector< double > &time, const std::vector< double > &timeErrors, const std::vector< double > &HePolarization, const std::vector< double > &HePolarizationErrors)
constexpr double DECAY_TIME_INITIAL
constexpr double H3_POLARIZATION_INITIAL
constexpr double PXD_INITIAL
Initial fitting function values.
constexpr auto INPUT_WORKSPACE
constexpr auto OUTPUT_DECAY_FIT
std::shared_ptr< MultiDomainFunction > prepareEfficiencyFunc(const double mu, const size_t numberOfDomains)
constexpr double START_WAVELENGTH_INITIAL
constexpr auto OUTPUT_HE3_FIT
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 OUTPUT_WORKSPACE
constexpr auto H3_POLARIZATION_INITIAL
constexpr auto GROUP_OUTPUTS
constexpr auto IGNORE_FIT_QUALITY_ERROR
constexpr auto INPUT_WORKSPACES
constexpr auto GROUP_FIT_OPTIONS
constexpr auto DECAY_TIME_INITIAL
constexpr auto GROUP_INPUTS
constexpr auto OUTPUT_FIT_PARAMS
constexpr auto SPIN_STATES
constexpr auto OUTPUT_FIT_CURVES
constexpr double LAMBDA_CONVERSION_FACTOR
std::pair< std::vector< double >, std::vector< double > > VectorPair
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Output
An output workspace.