-
Notifications
You must be signed in to change notification settings - Fork 122
/
SpecularReflectionPositionCorrect2.cpp
135 lines (109 loc) · 5.16 KB
/
SpecularReflectionPositionCorrect2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "MantidAlgorithms/SpecularReflectionPositionCorrect2.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidGeometry/Instrument.h"
#include "MantidGeometry/Instrument/ReferenceFrame.h"
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/CompositeValidator.h"
#include "MantidKernel/MandatoryValidator.h"
using namespace Mantid::API;
using namespace Mantid::Geometry;
using namespace Mantid::Kernel;
namespace Mantid {
namespace Algorithms {
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(SpecularReflectionPositionCorrect2)
//----------------------------------------------------------------------------------------------
/// Algorithm's name for identification. @see Algorithm::name
const std::string SpecularReflectionPositionCorrect2::name() const {
return "SpecularReflectionPositionCorrect";
}
/// Algorithm's summary. @see Algorithm::summary
const std::string SpecularReflectionPositionCorrect2::summary() const {
return "Corrects a detector component vertically based on TwoTheta.";
}
/// Algorithm's version for identification. @see Algorithm::version
int SpecularReflectionPositionCorrect2::version() const { return 2; }
/// Algorithm's category for identification. @see Algorithm::category
const std::string SpecularReflectionPositionCorrect2::category() const {
return "Reflectometry";
}
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void SpecularReflectionPositionCorrect2::init() {
declareProperty(make_unique<WorkspaceProperty<MatrixWorkspace>>(
"InputWorkspace", "", Direction::Input),
"An input workspace to correct.");
auto thetaValidator = boost::make_shared<CompositeValidator>();
thetaValidator->add(boost::make_shared<MandatoryValidator<double>>());
thetaValidator->add(
boost::make_shared<BoundedValidator<double>>(0, 90, true));
declareProperty(
make_unique<PropertyWithValue<double>>("TwoTheta", Mantid::EMPTY_DBL(),
thetaValidator, Direction::Input),
"Angle used to correct the detector component.");
declareProperty(
Mantid::Kernel::make_unique<PropertyWithValue<std::string>>(
"DetectorComponentName", "",
boost::make_shared<MandatoryValidator<std::string>>(),
Direction::Input),
"Name of the detector component to correct, i.e. point-detector");
declareProperty(
Mantid::Kernel::make_unique<PropertyWithValue<std::string>>(
"SampleComponentName", "some-surface-holder", Direction::Input),
"Name of the sample component, i.e. some-surface-holder");
declareProperty(
Mantid::Kernel::make_unique<WorkspaceProperty<MatrixWorkspace>>(
"OutputWorkspace", "", Direction::Output),
"An output workspace.");
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void SpecularReflectionPositionCorrect2::exec() {
MatrixWorkspace_sptr inWS = this->getProperty("InputWorkspace");
auto cloneWS = createChildAlgorithm("CloneWorkspace");
cloneWS->initialize();
cloneWS->setProperty("InputWorkspace", inWS);
cloneWS->execute();
Workspace_sptr tmp = cloneWS->getProperty("OutputWorkspace");
MatrixWorkspace_sptr outWS =
boost::dynamic_pointer_cast<MatrixWorkspace>(tmp);
const double twoThetaIn = getProperty("TwoTheta");
const double twoThetaInRad = twoThetaIn * (M_PI / 180.0);
auto inst = outWS->getInstrument();
// Detector
const std::string detectorName = getProperty("DetectorComponentName");
IComponent_const_sptr detector = inst->getComponentByName(detectorName);
const V3D detectorPosition = detector->getPos();
// Sample
const std::string sampleName = getProperty("SampleComponentName");
IComponent_const_sptr sample = inst->getComponentByName(sampleName);
const V3D samplePosition = sample->getPos();
// Sample-to-detector
const V3D sampleToDetector = detectorPosition - samplePosition;
// Reference frame
auto referenceFrame = inst->getReferenceFrame();
auto beamAxis = referenceFrame->pointingAlongBeamAxis();
auto horizontalAxis = referenceFrame->pointingHorizontalAxis();
auto upAxis = referenceFrame->pointingUpAxis();
// We just recalculate beam offset.
const double beamOffset =
sampleToDetector.scalar_prod(referenceFrame->vecPointingAlongBeam());
// We only correct vertical position
const double upOffset = (beamOffset * std::tan(twoThetaInRad));
auto moveAlg = createChildAlgorithm("MoveInstrumentComponent");
moveAlg->initialize();
moveAlg->setProperty("Workspace", outWS);
moveAlg->setProperty("ComponentName", detectorName);
moveAlg->setProperty("RelativePosition", false);
moveAlg->setProperty(beamAxis, detectorPosition.scalar_prod(
referenceFrame->vecPointingAlongBeam()));
moveAlg->setProperty(horizontalAxis, 0.0);
moveAlg->setProperty(upAxis, upOffset);
moveAlg->execute();
setProperty("OutputWorkspace", outWS);
}
} // namespace Algorithms
} // namespace Mantid