Skip to content

Commit

Permalink
Merge pull request #37643 from cailafinn/35067_wildes_flipper_config
Browse files Browse the repository at this point in the history
Allow Determination of Workspace Order from Output of PolarizationCorrectionWildes
  • Loading branch information
rbauststfc authored Aug 22, 2024
2 parents 2848287 + 0620675 commit e7c101c
Show file tree
Hide file tree
Showing 16 changed files with 329 additions and 149 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ class MANTID_ALGORITHMS_DLL PolarizationCorrectionWildes final : public API::Alg
void threeInputsSolve01(WorkspaceMap &inputs, const EfficiencyMap &efficiencies);
void threeInputsSolve10(WorkspaceMap &inputs, const EfficiencyMap &efficiencies);
void twoInputsSolve01And10(WorkspaceMap &fullInputs, const WorkspaceMap &inputs, const EfficiencyMap &efficiencies);
void addSpinStateOutput(std::vector<std::string> &names, const std::string &spinStateOrder,
const std::string &baseName, const API::MatrixWorkspace_sptr &ws,
const std::string &spinState);
};
} // namespace Algorithms
} // namespace Mantid
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,32 @@ MANTID_ALGORITHMS_DLL std::optional<size_t> indexOfWorkspaceForSpinState(const s
std::string targetSpinState);
MANTID_ALGORITHMS_DLL std::vector<std::string> splitSpinStateString(const std::string &spinStates);
} // namespace PolarizationCorrectionsHelpers

namespace FlipperConfigurations {
auto constexpr OFF_ON = "01";
auto constexpr ON_OFF = "10";
auto constexpr OFF_OFF = "00";
auto constexpr ON_ON = "11";
auto constexpr OFF = "0";
auto constexpr ON = "1";
} // namespace FlipperConfigurations

namespace SpinStateConfigurationsFredrikze {
auto constexpr PARA_ANTI = "pa";
auto constexpr ANTI_PARA = "ap";
auto constexpr PARA_PARA = "pp";
auto constexpr ANTI_ANTI = "aa";
auto constexpr PARA = "p";
auto constexpr ANTI = "a";
} // namespace SpinStateConfigurationsFredrikze

namespace SpinStateConfigurationsWildes {
auto constexpr MINUS_PLUS = "-+";
auto constexpr PLUS_MINUS = "+-";
auto constexpr MINUS_MINUS = "--";
auto constexpr PLUS_PLUS = "++";
auto constexpr MINUS = "-";
auto constexpr PLUS = "+";
} // namespace SpinStateConfigurationsWildes

} // namespace Mantid::Algorithms
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,10 @@ particular ordering.
*/
class MANTID_ALGORITHMS_DLL SpinStateValidator : public Kernel::TypedValidator<std::string> {
public:
SpinStateValidator(std::unordered_set<int> allowedNumbersOfSpins, const bool acceptSingleStates = false);
SpinStateValidator(std::unordered_set<int> allowedNumbersOfSpins, const bool acceptSingleStates = false,
const char paraIndicator = '0', const char antiIndicator = '1', const bool optional = false);
Kernel::IValidator_sptr clone() const override;

static const std::string ZERO_ONE;
static const std::string ONE_ZERO;
static const std::string ZERO_ZERO;
static const std::string ONE_ONE;
static const std::string ZERO;
static const std::string ONE;

static bool anyOfIsInSet(const std::vector<std::string> &anyOf, const std::unordered_set<std::string> &set);
static bool setContains(const std::unordered_set<std::string> &set, const std::string &s) {
return set.find(s) != set.cend();
Expand All @@ -42,6 +36,11 @@ class MANTID_ALGORITHMS_DLL SpinStateValidator : public Kernel::TypedValidator<s
private:
std::string checkValidity(const std::string &input) const override;
std::unordered_set<int> m_allowedNumbersOfSpins = {1, 2, 3, 4};
const std::unordered_set<std::string> getAllowedPairStates() const;
const std::unordered_set<std::string> getAllowedSingleStates() const;
bool m_acceptSingleStates = false;
const std::string m_para;
const std::string m_anti;
bool m_optional = false;
};
} // namespace Mantid::Algorithms
} // namespace Mantid::Algorithms
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ class MANTID_ALGORITHMS_DLL PolarizationEfficiencyCor final : public API::Algori
public:
const std::string name() const override;
int version() const override;
const std::vector<std::string> seeAlso() const override { return {"PolarizationCorrectionFredrikze"}; }
const std::vector<std::string> seeAlso() const override {
return {"PolarizationCorrectionWildes", "PolarizationCorrectionFredrikze"};
}
const std::string category() const override;
const std::string summary() const override;

Expand Down
143 changes: 92 additions & 51 deletions Framework/Algorithms/src/PolarizationCorrectionWildes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,12 @@ namespace {
/// Property names.
namespace Prop {
static const std::string FLIPPERS{"Flippers"};
static const std::string SPIN_STATES{"SpinStates"};
static const std::string EFFICIENCIES{"Efficiencies"};
static const std::string INPUT_WS{"InputWorkspaces"};
static const std::string OUTPUT_WS{"OutputWorkspace"};
} // namespace Prop

/// Flipper configurations.
namespace Flippers {
using namespace Mantid::Algorithms;
static const std::string Off{SpinStateValidator::ZERO};
static const std::string OffOff{SpinStateValidator::ZERO_ZERO};
static const std::string OffOn{SpinStateValidator::ZERO_ONE};
static const std::string On{SpinStateValidator::ONE};
static const std::string OnOff{SpinStateValidator::ONE_ZERO};
static const std::string OnOn{SpinStateValidator::ONE_ONE};
} // namespace Flippers

/**
* Throw if given ws is nullptr.
* @param ws a workspace to check
Expand Down Expand Up @@ -313,8 +303,9 @@ const std::string PolarizationCorrectionWildes::summary() const {
"and analyzer efficiencies.";
}

/// Algorithm's related algorithms. @see Algorithm::seeAlso
const std::vector<std::string> PolarizationCorrectionWildes::seeAlso() const {
return {"PolarizationEfficienciesWildes"};
return {"PolarizationEfficiencyCor", "PolarizationEfficienciesWildes"};
}

/**
Expand All @@ -337,10 +328,14 @@ void PolarizationCorrectionWildes::init() {
std::make_unique<API::WorkspaceProperty<API::WorkspaceGroup>>(Prop::OUTPUT_WS, "", Kernel::Direction::Output),
"A group of polarization efficiency corrected workspaces.");

const auto spinStateValidator = std::make_shared<SpinStateValidator>(std::unordered_set<int>{1, 2, 3, 4}, true);
const auto flipperConfigValidator = std::make_shared<SpinStateValidator>(std::unordered_set<int>{1, 2, 3, 4}, true);
declareProperty(Prop::FLIPPERS,
Flippers::OffOff + ", " + Flippers::OffOn + ", " + Flippers::OnOff + ", " + Flippers::OnOn,
spinStateValidator, "Flipper configurations of the input workspaces.");
std::string(FlipperConfigurations::OFF_OFF) + ", " + FlipperConfigurations::OFF_ON + ", " +
FlipperConfigurations::ON_OFF + ", " + FlipperConfigurations::ON_ON,
flipperConfigValidator, "Flipper configurations of the input workspaces.");
const auto spinStateValidator =
std::make_shared<SpinStateValidator>(std::unordered_set<int>{0, 2, 4}, false, '+', '-', true);
declareProperty(Prop::SPIN_STATES, "", spinStateValidator, "The order of the spin states in the output workspace.");
declareProperty(
std::make_unique<API::WorkspaceProperty<API::MatrixWorkspace>>(Prop::EFFICIENCIES, "", Kernel::Direction::Input),
"A workspace containing the efficiency factors P1, P2, F1 and F2 as "
Expand Down Expand Up @@ -410,12 +405,28 @@ std::map<std::string, std::string> PolarizationCorrectionWildes::validateInputs(
}
}
const std::vector<std::string> inputs = getProperty(Prop::INPUT_WS);
const std::string flipperProperty = getProperty(Prop::FLIPPERS);
const auto flipperCount = PolarizationCorrectionsHelpers::splitSpinStateString(flipperProperty).size();
const auto flipperConfig = PolarizationCorrectionsHelpers::splitSpinStateString(getPropertyValue(Prop::FLIPPERS));
const auto flipperCount = flipperConfig.size();
if (inputs.size() != flipperCount) {
issues[Prop::FLIPPERS] = "The number of flipper configurations (" + std::to_string(flipperCount) +
") does not match the number of input workspaces (" + std::to_string(inputs.size()) + ")";
}
// SpinStates checks.
const auto spinStates = PolarizationCorrectionsHelpers::splitSpinStateString(getPropertyValue(Prop::SPIN_STATES));
if (inputs.size() == 1 && !spinStates.empty()) {
issues[Prop::SPIN_STATES] = "Output workspace order cannot be set for direct beam calculations.";
} else if (!spinStates.empty()) {
if (flipperConfig.front().size() == 1 && spinStates.size() != 2) {
issues[Prop::SPIN_STATES] =
"Incorrect number of workspaces in output configuration: " + std::to_string(spinStates.size()) +
". Only two output workspaces are produced when an analyzer is not used.";
}
if (flipperConfig.front().size() == 2 && spinStates.size() != 4) {
issues[Prop::SPIN_STATES] =
"Incorrect number of workspaces in output configuration: " + std::to_string(spinStates.size()) +
". Four output workspaces are produced by the corrections.";
}
}
return issues;
}

Expand All @@ -438,16 +449,16 @@ void PolarizationCorrectionWildes::checkConsistentNumberHistograms(const Workspa
}
};
if (inputs.mmWS) {
checkNHist(inputs.mmWS, Flippers::OnOn);
checkNHist(inputs.mmWS, FlipperConfigurations::ON_ON);
}
if (inputs.mpWS) {
checkNHist(inputs.mpWS, Flippers::OnOff);
checkNHist(inputs.mpWS, FlipperConfigurations::ON_OFF);
}
if (inputs.pmWS) {
checkNHist(inputs.pmWS, Flippers::OffOn);
checkNHist(inputs.pmWS, FlipperConfigurations::OFF_ON);
}
if (inputs.ppWS) {
checkNHist(inputs.ppWS, Flippers::OffOff);
checkNHist(inputs.ppWS, FlipperConfigurations::OFF_OFF);
}
}

Expand Down Expand Up @@ -484,16 +495,16 @@ void PolarizationCorrectionWildes::checkConsistentX(const WorkspaceMap &inputs,
}
};
if (inputs.mmWS) {
checkWS(inputs.mmWS, Flippers::OnOn);
checkWS(inputs.mmWS, FlipperConfigurations::ON_ON);
}
if (inputs.mpWS) {
checkWS(inputs.mpWS, Flippers::OnOff);
checkWS(inputs.mpWS, FlipperConfigurations::ON_OFF);
}
if (inputs.pmWS) {
checkWS(inputs.pmWS, Flippers::OffOn);
checkWS(inputs.pmWS, FlipperConfigurations::OFF_ON);
}
if (inputs.ppWS) {
checkWS(inputs.ppWS, Flippers::OffOff);
checkWS(inputs.ppWS, FlipperConfigurations::OFF_OFF);
}
}

Expand All @@ -505,24 +516,26 @@ void PolarizationCorrectionWildes::checkConsistentX(const WorkspaceMap &inputs,
* @return a group workspace
*/
API::WorkspaceGroup_sptr PolarizationCorrectionWildes::groupOutput(const WorkspaceMap &outputs) {
const std::string outWSName = getProperty(Prop::OUTPUT_WS);
const auto &outWSName = getPropertyValue(Prop::OUTPUT_WS);
auto spinStateOrder = getPropertyValue(Prop::SPIN_STATES);
std::vector<std::string> names;
if (!spinStateOrder.empty()) {
names.resize(PolarizationCorrectionsHelpers::splitSpinStateString(spinStateOrder).size());
}

if (outputs.ppWS) {
names.emplace_back(outWSName + "_++");
API::AnalysisDataService::Instance().addOrReplace(names.back(), outputs.ppWS);
addSpinStateOutput(names, spinStateOrder, outWSName, outputs.ppWS, SpinStateConfigurationsWildes::PLUS_PLUS);
}
if (outputs.pmWS) {
names.emplace_back(outWSName + "_+-");
API::AnalysisDataService::Instance().addOrReplace(names.back(), outputs.pmWS);
addSpinStateOutput(names, spinStateOrder, outWSName, outputs.pmWS, SpinStateConfigurationsWildes::PLUS_MINUS);
}
if (outputs.mpWS) {
names.emplace_back(outWSName + "_-+");
API::AnalysisDataService::Instance().addOrReplace(names.back(), outputs.mpWS);
addSpinStateOutput(names, spinStateOrder, outWSName, outputs.mpWS, SpinStateConfigurationsWildes::MINUS_PLUS);
}
if (outputs.mmWS) {
names.emplace_back(outWSName + "_--");
API::AnalysisDataService::Instance().addOrReplace(names.back(), outputs.mmWS);
addSpinStateOutput(names, spinStateOrder, outWSName, outputs.mmWS, SpinStateConfigurationsWildes::MINUS_MINUS);
}

auto group = createChildAlgorithm("GroupWorkspaces");
group->initialize();
group->setProperty("InputWorkspaces", names);
Expand All @@ -532,6 +545,34 @@ API::WorkspaceGroup_sptr PolarizationCorrectionWildes::groupOutput(const Workspa
return outWS;
}

/**
* Add an output name in the correct position in the vector and to the ADS.
* @param names A list of the names of the workspaces the algorithm has generated.
* @param spinStateOrder The order the output should be in.
* @param baseName The base name for the output workspaces ("BASENAME_SPINSTATE" e.g "OUTNAME_+-")
* @param ws The workspace to add to the vector and ADS.
* @param spinState The spin state the workspace represents.
*/
void PolarizationCorrectionWildes::addSpinStateOutput(std::vector<std::string> &names,
const std::string &spinStateOrder, const std::string &baseName,
const API::MatrixWorkspace_sptr &ws,
const std::string &spinState) {
if (spinStateOrder.empty()) {
names.emplace_back(baseName + "_" + spinState);
API::AnalysisDataService::Instance().addOrReplace(names.back(), ws);
} else {
const auto &maybeIndex = PolarizationCorrectionsHelpers::indexOfWorkspaceForSpinState(
PolarizationCorrectionsHelpers::splitSpinStateString(spinStateOrder), spinState);
if (!maybeIndex.has_value()) {
throw std::invalid_argument("Required spin state (" + spinState + ") not found in spin state order (" +
spinStateOrder + ").");
}
const auto index = maybeIndex.value();
names[index] = baseName + "_" + spinState;
API::AnalysisDataService::Instance().addOrReplace(names[index], ws);
}
}

/**
* Make a convenience access object to the efficiency factors.
* @return an EfficiencyMap object
Expand Down Expand Up @@ -566,7 +607,7 @@ PolarizationCorrectionWildes::EfficiencyMap PolarizationCorrectionWildes::effici
PolarizationCorrectionWildes::WorkspaceMap
PolarizationCorrectionWildes::directBeamCorrections(const WorkspaceMap &inputs, const EfficiencyMap &efficiencies) {
using namespace boost::math;
checkInputExists(inputs.ppWS, Flippers::Off);
checkInputExists(inputs.ppWS, FlipperConfigurations::OFF);
WorkspaceMap outputs;
outputs.ppWS = createWorkspaceWithHistory(inputs.ppWS);
const size_t nHisto = inputs.ppWS->getNumberHistograms();
Expand Down Expand Up @@ -603,8 +644,8 @@ PolarizationCorrectionWildes::directBeamCorrections(const WorkspaceMap &inputs,
PolarizationCorrectionWildes::WorkspaceMap
PolarizationCorrectionWildes::analyzerlessCorrections(const WorkspaceMap &inputs, const EfficiencyMap &efficiencies) {
using namespace boost::math;
checkInputExists(inputs.mmWS, Flippers::On);
checkInputExists(inputs.ppWS, Flippers::Off);
checkInputExists(inputs.mmWS, FlipperConfigurations::ON);
checkInputExists(inputs.ppWS, FlipperConfigurations::OFF);
WorkspaceMap outputs;
outputs.mmWS = createWorkspaceWithHistory(inputs.mmWS);
outputs.ppWS = createWorkspaceWithHistory(inputs.ppWS);
Expand Down Expand Up @@ -667,8 +708,8 @@ PolarizationCorrectionWildes::analyzerlessCorrections(const WorkspaceMap &inputs
PolarizationCorrectionWildes::WorkspaceMap
PolarizationCorrectionWildes::twoInputCorrections(const WorkspaceMap &inputs, const EfficiencyMap &efficiencies) {
using namespace boost::math;
checkInputExists(inputs.mmWS, Flippers::OnOn);
checkInputExists(inputs.ppWS, Flippers::OffOff);
checkInputExists(inputs.mmWS, FlipperConfigurations::ON_ON);
checkInputExists(inputs.ppWS, FlipperConfigurations::OFF_OFF);
WorkspaceMap fullInputs = inputs;
fullInputs.mpWS = createWorkspaceWithHistory(inputs.mmWS);
fullInputs.pmWS = createWorkspaceWithHistory(inputs.ppWS);
Expand All @@ -688,13 +729,13 @@ PolarizationCorrectionWildes::twoInputCorrections(const WorkspaceMap &inputs, co
PolarizationCorrectionWildes::WorkspaceMap
PolarizationCorrectionWildes::threeInputCorrections(const WorkspaceMap &inputs, const EfficiencyMap &efficiencies) {
WorkspaceMap fullInputs = inputs;
checkInputExists(inputs.mmWS, Flippers::OnOn);
checkInputExists(inputs.ppWS, Flippers::OffOff);
checkInputExists(inputs.mmWS, FlipperConfigurations::ON_ON);
checkInputExists(inputs.ppWS, FlipperConfigurations::OFF_OFF);
if (!inputs.mpWS) {
checkInputExists(inputs.pmWS, Flippers::OffOn);
checkInputExists(inputs.pmWS, FlipperConfigurations::OFF_ON);
threeInputsSolve10(fullInputs, efficiencies);
} else {
checkInputExists(inputs.mpWS, Flippers::OnOff);
checkInputExists(inputs.mpWS, FlipperConfigurations::ON_OFF);
threeInputsSolve01(fullInputs, efficiencies);
}
return fullCorrections(fullInputs, efficiencies);
Expand All @@ -711,10 +752,10 @@ PolarizationCorrectionWildes::threeInputCorrections(const WorkspaceMap &inputs,
PolarizationCorrectionWildes::WorkspaceMap
PolarizationCorrectionWildes::fullCorrections(const WorkspaceMap &inputs, const EfficiencyMap &efficiencies) {
using namespace boost::math;
checkInputExists(inputs.mmWS, Flippers::OnOn);
checkInputExists(inputs.mpWS, Flippers::OnOff);
checkInputExists(inputs.pmWS, Flippers::OffOn);
checkInputExists(inputs.ppWS, Flippers::OffOff);
checkInputExists(inputs.mmWS, FlipperConfigurations::ON_ON);
checkInputExists(inputs.mpWS, FlipperConfigurations::ON_OFF);
checkInputExists(inputs.pmWS, FlipperConfigurations::OFF_ON);
checkInputExists(inputs.ppWS, FlipperConfigurations::OFF_OFF);
WorkspaceMap outputs;
outputs.mmWS = createWorkspaceWithHistory(inputs.mmWS);
outputs.mpWS = createWorkspaceWithHistory(inputs.mpWS);
Expand Down Expand Up @@ -781,13 +822,13 @@ PolarizationCorrectionWildes::mapInputsToDirections(const std::vector<std::strin
throw std::runtime_error("One of the input workspaces doesn't seem to be a MatrixWorkspace.");
}
const auto &f = flippers[i];
if (f == Flippers::OnOn || f == Flippers::On) {
if (f == FlipperConfigurations::ON_ON || f == FlipperConfigurations::ON) {
inputs.mmWS = ws;
} else if (f == Flippers::OnOff) {
} else if (f == FlipperConfigurations::ON_OFF) {
inputs.mpWS = ws;
} else if (f == Flippers::OffOn) {
} else if (f == FlipperConfigurations::OFF_ON) {
inputs.pmWS = ws;
} else if (f == Flippers::OffOff || f == Flippers::Off) {
} else if (f == FlipperConfigurations::OFF_OFF || f == FlipperConfigurations::OFF) {
inputs.ppWS = ws;
} else {
throw std::runtime_error(std::string{"Unknown entry in "} + Prop::FLIPPERS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ void FlipperEfficiency::init() {
"Group workspace containing flipper transmissions for all 4 polarization states.");
auto const spinValidator = std::make_shared<SpinStateValidator>(std::unordered_set<int>{4});
declareProperty(PropNames::SPIN_STATES, INITIAL_SPIN, spinValidator,
"Order of individual spin states in the input group workspace, e.g. \"01,11,00,10\"");
"Order of individual flipper configurations in the input group workspace, e.g. \"01,11,00,10\"");
declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>(PropNames::OUTPUT_WS, "", Direction::Output,
PropertyMode::Optional),
"Workspace containing the wavelength-dependent efficiency for the flipper.");
Expand Down Expand Up @@ -129,10 +129,10 @@ void FlipperEfficiency::exec() {

MatrixWorkspace_sptr FlipperEfficiency::calculateEfficiency(WorkspaceGroup_sptr const &groupWs) {
auto const &spinConfig = getPropertyValue(PropNames::SPIN_STATES);
auto const &t11Ws = workspaceForSpinState(groupWs, spinConfig, SpinStateValidator::ONE_ONE);
auto const &t10Ws = workspaceForSpinState(groupWs, spinConfig, SpinStateValidator::ONE_ZERO);
auto const &t01Ws = workspaceForSpinState(groupWs, spinConfig, SpinStateValidator::ZERO_ONE);
auto const &t00Ws = workspaceForSpinState(groupWs, spinConfig, SpinStateValidator::ZERO_ZERO);
auto const &t11Ws = workspaceForSpinState(groupWs, spinConfig, FlipperConfigurations::ON_ON);
auto const &t10Ws = workspaceForSpinState(groupWs, spinConfig, FlipperConfigurations::ON_OFF);
auto const &t01Ws = workspaceForSpinState(groupWs, spinConfig, FlipperConfigurations::OFF_ON);
auto const &t00Ws = workspaceForSpinState(groupWs, spinConfig, FlipperConfigurations::OFF_OFF);

auto const &numerator = (t11Ws * t00Ws) - (t10Ws * t01Ws);
auto const &denominator = (t11Ws + t10Ws) * (t00Ws - t01Ws);
Expand Down
Loading

0 comments on commit e7c101c

Please sign in to comment.