Mantid
Loading...
Searching...
No Matches
MagFormFactorCorrection.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 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 +
9#include "MantidAPI/Axis.h"
14#include "MantidHistogramData/Histogram.h"
15#include "MantidHistogramData/HistogramBuilder.h"
18#include "MantidKernel/Unit.h"
20using namespace Mantid::PhysicalConstants;
21
22namespace Mantid::Algorithms {
23
24// Register the algorithm into the AlgorithmFactory
25DECLARE_ALGORITHM(MagFormFactorCorrection)
26
27using namespace Kernel;
28using namespace API;
29using namespace PhysicalConstants;
30using namespace Mantid::DataObjects;
31using namespace Mantid::HistogramData;
32
34 declareProperty(std::make_unique<WorkspaceProperty<>>("InputWorkspace", "", Direction::Input),
35 "Workspace must have one axis with units of Q");
36 declareProperty(std::make_unique<WorkspaceProperty<>>("OutputWorkspace", "", Direction::Output),
37 "Output workspace name.");
38 std::vector<std::string> keys = getMagneticIonList();
39 declareProperty("IonName", "Cu2", std::make_shared<StringListValidator>(keys),
40 "The name of the ion: an element symbol with a number "
41 "indicating the valence, e.g. Fe2 for Fe2+ / Fe(II)");
43 std::make_unique<WorkspaceProperty<>>("FormFactorWorkspace", "", Direction::Output, PropertyMode::Optional),
44 "If specified the algorithm will create a 1D workspace with "
45 "the form factor vs Q with a name given by this field.");
46}
47
49 MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
50 const std::string ionNameStr = getProperty("IonName");
51 const std::string ffwsStr = getProperty("FormFactorWorkspace");
52 const bool isHist = inputWS->isHistogramData();
53 const int64_t numHists = inputWS->getNumberHistograms();
54 const int64_t specSize = inputWS->blocksize();
55
56 // Checks that there is a |Q| axis.
57 int64_t numAxes = inputWS->axes();
58 bool hasQ = false;
59 std::vector<double> Qvals;
60 int64_t iax;
61 for (iax = 0; iax < numAxes; iax++) {
62 Axis *QAxis = inputWS->getAxis(iax);
63 std::string unitID = QAxis->unit()->unitID();
64 if (unitID == "MomentumTransfer") {
65 hasQ = true;
66 // Gets the list of Q values
67 if (isHist || iax > 0) {
68 int64_t nQ = QAxis->length() - 1;
69 for (int64_t iQ = 0; iQ < nQ; iQ++) {
70 Qvals.emplace_back(0.5 *
71 (QAxis->getValue(static_cast<size_t>(iQ)) + QAxis->getValue(static_cast<size_t>(iQ + 1))));
72 }
73 } else {
74 int64_t nQ = QAxis->length();
75 for (int64_t iQ = 0; iQ < nQ; iQ++) {
76 Qvals.emplace_back(QAxis->getValue(static_cast<size_t>(iQ)));
77 }
78 }
79 break;
80 }
81 }
82 if (!hasQ) {
83 throw std::runtime_error("Expected a MatrixWorkspace with a "
84 "MomentumTransfer axis. Cannot apply form factor "
85 "without knowing Q.");
86 }
87
88 // Parses the ion name and get handle to MagneticIon object
89 const MagneticIon &ion = getMagneticIon(ionNameStr);
90 // Gets the vector of form factor values
91 std::vector<double> FF;
92 FF.reserve(Qvals.size());
93
94 std::transform(Qvals.begin(), Qvals.end(), std::back_inserter(FF),
95 [&ion](double qval) { return ion.analyticalFormFactor(qval * qval); });
96
97 if (!ffwsStr.empty()) {
98 HistogramBuilder builder;
99 builder.setX(Qvals.size());
100 builder.setY(FF.size());
101 MatrixWorkspace_sptr ffws = create<Workspace2D>(1, builder.build());
102 ffws->mutableX(0).assign(Qvals.begin(), Qvals.end());
103 ffws->mutableY(0).assign(FF.begin(), FF.end());
104 ffws->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer");
105 ffws->setYUnitLabel("F(Q)");
106 setProperty("FormFactorWorkspace", ffws);
107 }
108
109 // Does the actual scaling.
110 MatrixWorkspace_sptr outputWS = inputWS->clone();
111 for (int64_t i = 0; i < numHists; i++) {
112 auto &Y = outputWS->mutableY(i);
113 auto &E = outputWS->mutableE(i);
114 for (int64_t j = 0; j < specSize; j++) {
115 double ff = (iax == 0) ? FF[j] : FF[i];
116 // Sometimes ff can be negative due to analytical approximation to the
117 // exact calculation. Catch these, and also case of ff=0 (where there
118 // should be no magnetic scattering).
119 if (ff < 0.01) {
120 Y[j] = NAN;
121 E[j] = NAN;
122 } else {
123 Y[j] /= (ff * ff); // Magnetic intensity proportional |F(Q)|^2
124 E[j] /= (ff * ff);
125 }
126 }
127 }
128
129 setProperty("OutputWorkspace", outputWS);
130}
131
132} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Class to represent the axis of a workspace.
Definition: Axis.h:30
virtual std::size_t length() const =0
Get the length of the axis.
const std::shared_ptr< Kernel::Unit > & unit() const
The unit for this axis.
Definition: Axis.cpp:28
double getValue(const std::size_t &index, const std::size_t &verticalIndex=0) const
Gets the value at the specified index.
Definition: Axis.cpp:51
A property class for workspaces.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
A namespace containing physical constants that are required by algorithms and unit routines.
Definition: Atom.h:14
MANTID_KERNEL_DLL std::vector< std::string > getMagneticIonList()
Returns a list of all ions.
MANTID_KERNEL_DLL const MagneticIon & getMagneticIon(const std::string &symbol, const uint16_t charge)
Returns the magnetic ion for the given symbol and charge.
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54
Struture to hold information about magnetic form factor for 3d, 4d, rare earth, and actinide atoms an...
Definition: MagneticIon.h:25