Mantid
Loading...
Searching...
No Matches
LoadDspacemap.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 +
19#include "MantidKernel/V3D.h"
20
21using namespace Mantid::Kernel;
22using namespace Mantid::API;
23using namespace Mantid::Geometry;
24using namespace Mantid::DataObjects;
25
26namespace Mantid::DataHandling {
27
28// Register the algorithm into the AlgorithmFactory
30
31//----------------------------------------------------------------------------------------------
34void LoadDspacemap::init() {
35 // 3 properties for getting the right instrument
37
38 const std::vector<std::string> exts{".dat", ".bin"};
39 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Load, exts),
40 "The DspacemapFile containing the d-space mapping.");
41
42 std::vector<std::string> propOptions{"POWGEN", "VULCAN-ASCII", "VULCAN-Binary"};
43 declareProperty("FileType", "POWGEN", std::make_shared<StringListValidator>(propOptions),
44 "The type of file being read.");
45
46 declareProperty(std::make_unique<WorkspaceProperty<OffsetsWorkspace>>("OutputWorkspace", "", Direction::Output),
47 "An output OffsetsWorkspace.");
48}
49
50//----------------------------------------------------------------------------------------------
54 // Get the instrument
56
57 // Read in the calibration data
58 const std::string DFileName = getProperty("Filename");
59
60 // Create the blank output
61 OffsetsWorkspace_sptr offsetsWS(new OffsetsWorkspace(inst));
62 setProperty("OutputWorkspace", offsetsWS);
63
64 std::string type = this->getPropertyValue("FileType");
65 if (type == "POWGEN") {
66 // generate map of the tof->d conversion factors
67 CalculateOffsetsFromDSpacemapFile(DFileName, offsetsWS);
68 } else {
69 // Map of udet:funny vulcan correction factor.
70 std::map<detid_t, double> vulcan;
71 if (type == "VULCAN-ASCII") {
72 readVulcanAsciiFile(DFileName, vulcan);
73 } else if (type == "VULCAN-Binary") {
74 readVulcanBinaryFile(DFileName, vulcan);
75 } else
76 throw std::invalid_argument("Unexpected FileType property value received.");
77
78 // Now that we have loaded the vulcan file (either type), convert it out.
79 this->CalculateOffsetsFromVulcanFactors(vulcan, offsetsWS);
80 }
81}
82
83//-----------------------------------------------------------------------
91void LoadDspacemap::CalculateOffsetsFromDSpacemapFile(const std::string &DFileName,
93 // Get a pointer to the instrument contained in the workspace
94
95 const auto &detectorInfo = offsetsWS->detectorInfo();
96 const double l1 = detectorInfo.l1();
97 // Read in the POWGEN-style Dspace mapping file
98 const char *filename = DFileName.c_str();
99 std::ifstream fin(filename, std::ios_base::in | std::ios_base::binary);
100
101 std::vector<double> dspace;
102 double read;
103 while (!fin.eof()) {
104 fin.read(reinterpret_cast<char *>(&read), sizeof read);
105 // Factor of 10 between ISAW and Mantid
106 read *= 10.;
107 dspace.emplace_back(read);
108 }
109
110 const auto &detectorIds = detectorInfo.detectorIDs();
111
112 for (size_t detectorIndex = 0; detectorIndex < detectorInfo.size(); ++detectorIndex) {
113 const auto detectorId = detectorIds[detectorIndex];
114
115 // Compute the factor
116 double offset = 0.0;
117 if (!detectorInfo.isMonitor(detectorIndex)) {
118 double factor = Geometry::Conversion::tofToDSpacingFactor(l1, detectorInfo.l2(detectorIndex),
119 detectorInfo.twoTheta(detectorIndex), offset);
120 offset = dspace[detectorId] / factor - 1.0;
121 }
122 // Save in the map
123 try {
124 offsetsWS->setValue(detectorId, offset);
125 } catch (std::invalid_argument &) {
126 }
127 }
128}
129
130const double CONSTANT = (PhysicalConstants::h * 1e10) / (2.0 * PhysicalConstants::NeutronMass * 1e6);
131
132//-----------------------------------------------------------------------
141void LoadDspacemap::CalculateOffsetsFromVulcanFactors(std::map<detid_t, double> &vulcan,
143 // Get a pointer to the instrument contained in the workspace
144 // At this point, instrument VULCAN has been created?
145 Instrument_const_sptr instrument = offsetsWS->getInstrument();
146
147 g_log.notice() << "Name of instrument = " << instrument->getName() << '\n';
148 g_log.notice() << "Input map (dict): size = " << vulcan.size() << '\n';
149
150 // To get all the detector ID's
151 detid2det_map allDetectors;
152 instrument->getDetectors(allDetectors);
153
154 detid2det_map::const_iterator it;
155 int numfinds = 0;
156 g_log.notice() << "Input number of detectors = " << allDetectors.size() << '\n';
157
158 // Get detector information
159 double l1, beamline_norm;
160 Kernel::V3D beamline, samplePos;
161 instrument->getInstrumentParameters(l1, beamline, beamline_norm, samplePos);
162
163 /*** A survey of parent detector
164 std::map<detid_t, bool> parents;
165 for (it = allDetectors.begin(); it != allDetectors.end(); it++){
166 int32_t detid = it->first;
167
168 // def std::shared_ptr<const Mantid::Geometry::IDetector>
169 IDetector_const_sptr;
170
171 std::string parentname =
172 it->second->getParent()->getComponentID()->getName();
173 g_log.notice() << "Name = " << parentname << '\n';
174 // parents.insert(parentid, true);
175 }
176 ***/
177
178 /*** Here some special configuration for VULCAN is hard-coded here!
179 * Including (1) Super-Parent Information
180 ***/
181 Kernel::V3D referencePos;
182 detid_t anydetinrefmodule = 21 * 1250 + 5;
183
184 auto det_iter = allDetectors.find(anydetinrefmodule);
185
186 if (det_iter == allDetectors.end()) {
187 throw std::invalid_argument("Any Detector ID is Instrument's detector");
188 }
189 referencePos = det_iter->second->getParent()->getPos();
190 double refl2 = referencePos.norm();
191 double halfcosTwoThetaRef = referencePos.scalar_prod(beamline) / (refl2 * beamline_norm);
192 double sinThetaRef = sqrt(0.5 - halfcosTwoThetaRef);
193 double difcRef = sinThetaRef * (l1 + refl2) / CONSTANT;
194
195 // Loop over all detectors in instrument to find the offset
196 for (it = allDetectors.begin(); it != allDetectors.end(); ++it) {
197 int detectorID = it->first;
198 Geometry::IDetector_const_sptr det = it->second;
199 double offset = 0.0;
200
201 // Find the vulcan factor;
202 double vulcan_factor = 0.0;
203 std::map<detid_t, double>::const_iterator vulcan_iter = vulcan.find(detectorID);
204 if (vulcan_iter != vulcan.end()) {
205 vulcan_factor = vulcan_iter->second;
206 numfinds++;
207 }
208
209 // g_log.notice() << "Selected Detector with ID = " << detectorID << " ID2
210 // = " << id2 << '\n'; proved to be same
211
212 double intermoduleoffset = 0;
213 double interstackoffset = 0;
214
215 detid_t intermoduleid = detid_t(detectorID / 1250) * 1250 + 1250 - 2;
216 vulcan_iter = vulcan.find(intermoduleid);
217 if (vulcan_iter == vulcan.end()) {
218 g_log.error() << "Cannot find inter-module offset ID = " << intermoduleid << '\n';
219 } else {
220 intermoduleoffset = vulcan_iter->second;
221 }
222
223 detid_t interstackid = detid_t(detectorID / 1250) * 1250 + 1250 - 1;
224 vulcan_iter = vulcan.find(interstackid);
225 if (vulcan_iter == vulcan.end()) {
226 g_log.error() << "Cannot find inter-module offset ID = " << intermoduleid << '\n';
227 } else {
228 interstackoffset = vulcan_iter->second;
229 }
230
231 /*** This is the previous way to correct upon DIFC[module center pixel]
232 // The actual factor is 10^(-value_in_the_file)
233 vulcan_factor = pow(10.0,-vulcan_factor);
234 // At this point, tof_corrected = vulcan_factor * tof_input
235 // So this is the offset
236 offset = vulcan_factor - 1.0;
237 ***/
238
239 /*** New approach to correct based on DIFC of each pixel
240 * Equation: offset = DIFC^(pixel)/DIFC^(parent)*(1+vulcan_offset)-1
241 * offset should be close to 0
242 ***/
243 // 1. calculate DIFC
244 Kernel::V3D detPos;
245 detPos = det->getPos();
246
247 // Now detPos will be set with respect to samplePos
248 detPos -= samplePos;
249 double l2 = detPos.norm();
250 double halfcosTwoTheta = detPos.scalar_prod(beamline) / (l2 * beamline_norm);
251 double sinTheta = sqrt(0.5 - halfcosTwoTheta);
252 double difc_pixel = sinTheta * (l1 + l2) / CONSTANT;
253
254 // Kernel::V3D parentPos = det->getParent()->getPos();
255 // parentPos -= samplePos;
256 // double l2parent = parentPos.norm();
257 // double halfcosTwoThetaParent = parentPos.scalar_prod(beamline)/(l2 *
258 // beamline_norm);
259 // double sinThetaParent = sqrt(0.5 - halfcosTwoThetaParent);
260 // double difc_parent = sinThetaParent*(l1+l2parent)/CONSTANT;
261
262 /*** Offset Replicate Previous Result
263 offset = difc_pixel/difc_parent*(pow(10.0, -vulcan_factor))-1.0;
264 ***/
265
266 offset = difc_pixel / difcRef * (pow(10.0, -(vulcan_factor + intermoduleoffset + interstackoffset))) - 1.0;
267
268 // Save in the map
269 try {
270 offsetsWS->setValue(detectorID, offset);
271
272 if (intermoduleid != 27498 && intermoduleid != 28748 && intermoduleid != 29998 && intermoduleid != 33748 &&
273 intermoduleid != 34998 && intermoduleid != 36248) {
274 g_log.error() << "Detector ID = " << detectorID << " Inter-Module ID = " << intermoduleid << '\n';
275 throw std::invalid_argument("Indexing error!");
276 }
277
278 } catch (std::invalid_argument &) {
279 g_log.notice() << "Misses Detector ID = " << detectorID << '\n';
280 }
281 } // for
282
283 g_log.notice() << "Number of matched detectors =" << numfinds << '\n';
284}
285
286//-----------------------------------------------------------------------
297void LoadDspacemap::readVulcanAsciiFile(const std::string &fileName, std::map<detid_t, double> &vulcan) {
298 std::ifstream grFile(fileName.c_str());
299 if (!grFile) {
300 g_log.error() << "Unable to open vulcan file " << fileName << '\n';
301 return;
302 }
303 vulcan.clear();
304 std::string str;
305 int numentries = 0;
306 while (getline(grFile, str)) {
307 if (str.empty() || str[0] == '#')
308 continue;
309 std::istringstream istr(str);
310 int32_t udet;
311 double correction;
312 istr >> udet >> correction;
313 vulcan.emplace(udet, correction);
314 numentries++;
315 }
316
317 g_log.notice() << "Read Vulcan ASCII File: # Entry = " << numentries << '\n';
318}
319
323 double pixelID;
325 double factor;
326};
327
328//-----------------------------------------------------------------------
339void LoadDspacemap::readVulcanBinaryFile(const std::string &fileName, std::map<detid_t, double> &vulcan) {
341 std::vector<VulcanCorrectionFactor> results = file.loadAll();
342 for (auto &result : results) {
343 vulcan[static_cast<detid_t>(result.pixelID)] = result.factor;
344 }
345}
346
347} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
IntArray detectorIndex
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
Definition: Algorithm.cpp:2026
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
Kernel::Logger & g_log
Definition: Algorithm.h:451
@ Load
allowed here which will be passed to the algorithm
Definition: FileProperty.h:52
A property class for workspaces.
static void getInstrument3WaysInit(Mantid::API::Algorithm *alg)
For use by getInstrument3Ways, initializes the properties.
Definition: LoadCalFile.cpp:35
static Geometry::Instrument_const_sptr getInstrument3Ways(API::Algorithm *alg)
Get a pointer to an instrument in one of 3 ways: InputWorkspace, InstrumentName, InstrumentFilename.
Definition: LoadCalFile.cpp:73
Loads a Dspacemap file (POWGEN binary, VULCAN binary or ascii format) into an OffsetsWorkspace.
Definition: LoadDspacemap.h:25
void CalculateOffsetsFromVulcanFactors(std::map< detid_t, double > &vulcan, const Mantid::DataObjects::OffsetsWorkspace_sptr &offsetsWS)
Make a map of the conversion factors between tof and D-spacing for all pixel IDs in a workspace.
void CalculateOffsetsFromDSpacemapFile(const std::string &DFileName, const Mantid::DataObjects::OffsetsWorkspace_sptr &offsetsWS)
Make a map of the conversion factors between tof and D-spacing for all pixel IDs in a workspace.
void readVulcanAsciiFile(const std::string &fileName, std::map< detid_t, double > &vulcan)
Reads an ASCII VULCAN filename where:
void readVulcanBinaryFile(const std::string &fileName, std::map< detid_t, double > &vulcan)
Reads a Binary VULCAN filename where:
void exec() override
Run the algorithm.
An OffsetsWorkspace is a specialized Workspace2D where the Y value at each pixel is the offset to be ...
The BinaryFile template is a helper function for loading simple binary files.
Definition: BinaryFile.h:44
std::vector< T > loadAll()
Loads the entire contents of the file into a pointer to a std::vector.
Definition: BinaryFile.h:109
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
Class for 3D vectors.
Definition: V3D.h:34
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
Definition: V3D.h:274
double norm() const noexcept
Definition: V3D.h:263
std::shared_ptr< OffsetsWorkspace > OffsetsWorkspace_sptr
shared pointer to the OffsetsWorkspace class
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 Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
Definition: IDetector.h:102
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
static constexpr double NeutronMass
Mass of the neutron in kg.
static constexpr double h
Planck constant in J*s.
int32_t detid_t
Typedef for a detector ID.
Definition: SpectrumInfo.h:21
std::map< detid_t, Geometry::IDetector_const_sptr > detid2det_map
Typedef of a map from detector ID to detector shared pointer.
Definition: Instrument.h:27
Structure of the vulcan binary file.
double factor
Correction factor for pixel.
@ Output
An output workspace.
Definition: Property.h:54