Mantid
Loading...
Searching...
No Matches
ConvertDiffCal.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 +
10#include "MantidAPI/TableRow.h"
16
17namespace Mantid::Algorithms {
18
30
31// Register the algorithm into the AlgorithmFactory
32DECLARE_ALGORITHM(ConvertDiffCal)
33
34//----------------------------------------------------------------------------------------------
35
36
37const std::string ConvertDiffCal::name() const { return "ConvertDiffCal"; }
38
40int ConvertDiffCal::version() const { return 1; }
41
43const std::string ConvertDiffCal::category() const { return "Diffraction\\Utility"; }
44
46const std::string ConvertDiffCal::summary() const { return "Convert diffraction calibration from old to new style"; }
47
48//----------------------------------------------------------------------------------------------
52 declareProperty(std::make_unique<WorkspaceProperty<OffsetsWorkspace>>("OffsetsWorkspace", "", Direction::Input),
53 "OffsetsWorkspace containing the calibration offsets.");
54
55 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("PreviousCalibration", "", Direction::Input,
57 "A calibration table used as a cache for creating the OutputWorkspace. "
58 "Effectively, this algorithm applies partial updates to this table and "
59 "returns it as the OutputWorkspace");
60
61 declareProperty(std::make_unique<WorkspaceProperty<ITableWorkspace>>("OutputWorkspace", "", Direction::Output),
62 "An output workspace.");
63}
64
72detid_t getDetID(const OffsetsWorkspace_const_sptr &offsetsWS, const size_t index) {
73 auto detIDs = offsetsWS->getSpectrum(index).getDetectorIDs();
74 if (detIDs.size() != 1) {
75 std::stringstream msg;
76 msg << "Encountered spectrum with multiple detector ids (size=" << detIDs.size() << ")";
77 throw std::logic_error(msg.str());
78 }
79 return (*(detIDs.begin()));
80}
81
88double getOffset(const OffsetsWorkspace_const_sptr &offsetsWS, const detid_t detid) {
89 const double offset = offsetsWS->getValue(detid, 0.0);
90 if (offset <= -1.) { // non-physical
91 std::stringstream msg;
92 msg << "Encountered offset of " << offset << " which converts data to negative d-spacing for detectorID " << detid
93 << "\n";
94 throw std::logic_error(msg.str());
95 }
96 return offset;
97}
98
105double calculateDIFC(const OffsetsWorkspace_const_sptr &offsetsWS, const size_t index,
106 const Mantid::API::SpectrumInfo &spectrumInfo) {
107 const detid_t detid = getDetID(offsetsWS, index);
108 const double offset = getOffset(offsetsWS, detid);
109 double twotheta;
110 try {
111 twotheta = spectrumInfo.twoTheta(index);
112 } catch (std::runtime_error &) {
113 // Choose an arbitrary angle if detector 2theta determination fails.
114 twotheta = 0.;
115 }
116 // the factor returned is what is needed to convert TOF->d-spacing
117 // the table is supposed to be filled with DIFC which goes the other way
118 const double factor =
119 Mantid::Geometry::Conversion::tofToDSpacingFactor(spectrumInfo.l1(), spectrumInfo.l2(index), twotheta, offset);
120 return 1. / factor;
121}
122
123//----------------------------------------------------------------------------------------------
127 OffsetsWorkspace_const_sptr offsetsWS = getProperty("OffsetsWorkspace");
128
129 /* If a previous calibration is provided, initialize the output calibration table
130 * with it */
131 ITableWorkspace_sptr configWksp;
132
133 ITableWorkspace_sptr previous_calibration = getProperty("PreviousCalibration");
134
135 std::vector<std::string> correct_columns{"detid", "difc", "difa", "tzero"};
136 if (previous_calibration) {
137 /* validate correct format */
138 std::vector<std::string> column_names = previous_calibration->getColumnNames();
139 if (column_names != correct_columns) {
140 throw std::runtime_error("PreviousCalibration table's column names do not match expected "
141 "format");
142 }
143
144 configWksp = previous_calibration->clone();
145 }
146
147 else {
148 // initial setup of new style config
149 configWksp = std::make_shared<TableWorkspace>();
150
151 configWksp->addColumn("int", correct_columns[0]);
152 configWksp->addColumn("double", correct_columns[1]);
153 configWksp->addColumn("double", correct_columns[2]);
154 configWksp->addColumn("double", correct_columns[3]);
155 }
156
157 /* obtain detector ids from the previous calibration workspace */
158 std::unordered_map<int, int> id_to_row;
159 if (previous_calibration) {
160 std::vector<int> previous_calibration_ids = previous_calibration->getColumn(0)->numeric_fill<int>();
161
162 int row = 0;
163
164 for (auto id : previous_calibration_ids) {
165 id_to_row[id] = row++;
166 }
167 }
168
169 // create values in the table
170 const size_t numberOfSpectra = offsetsWS->getNumberHistograms();
171 Progress progress(this, 0.0, 1.0, numberOfSpectra);
172
173 const Mantid::API::SpectrumInfo &spectrumInfo = offsetsWS->spectrumInfo();
174 Mantid::Geometry::DetectorInfo const &d_info = offsetsWS->detectorInfo();
175 for (size_t i = 0; i < numberOfSpectra; ++i) {
176
177 /* obtain detector id for this spectra */
178 detid_t detector_id = getDetID(offsetsWS, i);
179 size_t internal_index = d_info.indexOf(detector_id);
180 /* obtain the mask */
181 if (!d_info.isMasked(internal_index)) {
182 /* find the detector id's offset value in the offset workspace */
183 double new_offset_value = offsetsWS->getValue(detector_id);
184
185 /* search for it in the table */
186 auto iter = id_to_row.find(detector_id);
187
188 /* if it is found, update the correct row in the output table */
189 if (iter != id_to_row.end()) {
190 /* Get the row and update the difc value in the first column */
191 int row_to_update = iter->second;
192
193 double &difc_value_to_update = configWksp->cell<double>(row_to_update, 1);
194
195 difc_value_to_update = difc_value_to_update / (1 + new_offset_value);
196 }
197
198 /* value was not found in PreviousCalibration - calculate from experiment's geometry */
199 else {
200 API::TableRow newrow = configWksp->appendRow();
201 newrow << static_cast<int>(detector_id);
202 newrow << calculateDIFC(offsetsWS, i, spectrumInfo);
203 newrow << 0.; // difa
204 newrow << 0.; // tzero
205 }
206 }
207
208 progress.report();
209 }
210
211 // sort the results
212 auto sortTable = createChildAlgorithm("SortTableWorkspace");
213 sortTable->setProperty("InputWorkspace", configWksp);
214 sortTable->setProperty("OutputWorkspace", configWksp);
215 sortTable->setPropertyValue("Columns", "detid");
216 sortTable->executeAsChildAlg();
217
218 // copy over the results
219 configWksp = sortTable->getProperty("OutputWorkspace");
220 setProperty("OutputWorkspace", configWksp);
221}
222
223} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
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
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.
Definition: Algorithm.cpp:842
void progress(double p, const std::string &msg="", double estimatedTime=0.0, int progressPrecision=0)
Sends ProgressNotification.
Definition: Algorithm.cpp:231
ITableWorkspace is an implementation of Workspace in which the data are organised in columns of same ...
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
API::SpectrumInfo is an intermediate step towards a SpectrumInfo that is part of Instrument-2....
Definition: SpectrumInfo.h:53
double twoTheta(const size_t index) const
Returns the scattering angle 2 theta in radians (angle w.r.t.
double l2(const size_t index) const
Returns L2 (distance from sample to spectrum).
double l1() const
Returns L1 (distance from source to sample).
TableRow represents a row in a TableWorkspace.
Definition: TableRow.h:39
A property class for workspaces.
ConvertDiffCal : TODO: DESCRIPTION.
const std::string category() const override
Algorithm's category for identification.
int version() const override
Algorithm's version for identification.
const std::string summary() const override
Algorithm's summary for use in the GUI and help.
void exec() override
Execute the algorithm.
void init() override
Initialize the algorithm's properties.
An OffsetsWorkspace is a specialized Workspace2D where the Y value at each pixel is the offset to be ...
TableWorkspace is an implementation of Workspace in which the data are organised in columns of same s...
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
Definition: DetectorInfo.h:49
bool isMasked(const size_t index) const
Returns true if the detector is masked.
size_t indexOf(const detid_t id) const
Returns the index of the detector with the given detector ID.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
double getOffset(const OffsetsWorkspace_const_sptr &offsetsWS, const detid_t detid)
detid_t getDetID(const OffsetsWorkspace_const_sptr &offsetsWS, const size_t index)
double calculateDIFC(const OffsetsWorkspace_const_sptr &offsetsWS, const size_t index, const Mantid::API::SpectrumInfo &spectrumInfo)
std::shared_ptr< const OffsetsWorkspace > OffsetsWorkspace_const_sptr
shared pointer to a const OffsetsWorkspace
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
MANTID_GEOMETRY_DLL double tofToDSpacingFactor(const double l1, const double l2, const double twoTheta, const double offset)
Calculate and return conversion factor from tof to d-spacing.
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21
STL namespace.
Describes the direction (within an algorithm) of a Property.
Definition: Property.h:50
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54