Mantid
Loading...
Searching...
No Matches
SaveIsawDetCal.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 +
11#include "MantidAPI/Run.h"
12#include "MantidAPI/Workspace.h"
17
19
20#include <boost/algorithm/string/trim.hpp>
21#include <filesystem>
22#include <fstream>
23
24using namespace Mantid::Kernel;
25using namespace Mantid::API;
26using namespace Mantid::Geometry;
27using Mantid::Types::Core::DateAndTime;
28using std::string;
29
30namespace Mantid::DataHandling {
31
32// Register the algorithm into the AlgorithmFactory
34
35
37void SaveIsawDetCal::init() {
38 declareProperty(std::make_unique<WorkspaceProperty<Workspace>>("InputWorkspace", "", Direction::Input),
39 "An input workspace.");
40
41 declareProperty(std::make_unique<FileProperty>("Filename", "", FileProperty::Save, ".DetCal"),
42 "Path to an ISAW-style .detcal file to save.");
43
44 declareProperty("TimeOffset", 0.0, "Offsets to be applied to times");
45 declareProperty(std::make_unique<ArrayProperty<string>>("BankNames", Direction::Input),
46 "Optional: Only select the specified banks");
47 declareProperty("AppendFile", false,
48 "Append to file if true.\n"
49 "If false, new file (default).");
50}
51
55 std::string filename = getPropertyValue("Filename");
56 // MatrixWorkspace_sptr ws = getProperty("InputWorkspace");
57
58 Workspace_sptr ws1 = getProperty("InputWorkspace");
59 ExperimentInfo_sptr ws = std::dynamic_pointer_cast<ExperimentInfo>(ws1);
60
61 double T0 = getProperty("TimeOffset");
62 const API::Run &run = ws->run();
63 // Use T0 from workspace if T0 not specified in input
64 if (T0 == 0.0 && run.hasProperty("T0")) {
65 T0 = run.getPropertyValueAsType<double>("T0");
66 if (T0 != 0) {
67 g_log.notice() << "T0 = " << T0 << '\n';
68 }
69 }
70
71 std::vector<std::string> bankNames = getProperty("BankNames");
72
73 inst = ws->getInstrument();
74 if (!inst)
75 throw std::runtime_error("No instrument in the Workspace. Cannot save DetCal file.");
76 // We cannot assume the peaks have bank type detector modules, so we have a
77 // string to check this
78 std::string bankPart = "bank";
79 if (inst->getName() == "WISH")
80 bankPart = "WISHpanel";
81
82 std::set<int> uniqueBanks;
83 if (bankNames.empty()) {
84 // Get all components using ComponentInfo
85 const auto &componentInfo = ws->componentInfo();
86 for (size_t i = 0; i < componentInfo.size(); ++i) {
87 std::string bankName = componentInfo.name(i);
88 boost::trim(bankName);
89 boost::erase_all(bankName, bankPart);
90 int bank = 0;
91 Strings::convert(bankName, bank);
92 if (bank == 0)
93 continue;
94 // Track unique bank numbers
95 uniqueBanks.insert(bank);
96 }
97 } else {
98 for (auto bankName : bankNames) {
99 boost::trim(bankName);
100 boost::erase_all(bankName, bankPart);
101 int bank = 0;
102 Strings::convert(bankName, bank);
103 if (bank == 0)
104 continue;
105 // Track unique bank numbers
106 uniqueBanks.insert(bank);
107 }
108 }
109
110 double l1;
111 V3D beamline;
112 double beamline_norm;
113 V3D samplePos;
114 inst->getInstrumentParameters(l1, beamline, beamline_norm, samplePos);
115
116 std::ofstream out;
117 bool append = getProperty("AppendFile");
118
119 // do not append if file does not exist
120 if (!std::filesystem::exists(std::filesystem::path(filename.c_str())))
121 append = false;
122
123 if (append) {
124 out.open(filename.c_str(), std::ios::app);
125 } else {
126 out.open(filename.c_str());
127 out << "# NEW CALIBRATION FILE FORMAT (in NeXus/SNS coordinates):\n";
128 out << "# Lengths are in centimeters.\n";
129 out << "# Base and up give directions of unit vectors for a local \n";
130 out << "# x,y coordinate system on the face of the detector.\n";
131 out << "#\n";
132 out << "#\n";
133 out << "# " << DateAndTime::getCurrentTime().toISO8601String() << '\n';
134
135 out << "6 L1 T0_SHIFT\n";
136 out << "7 " << std::setw(10);
137 out << std::setprecision(4) << std::fixed << (l1 * 100);
138 out << std::setw(13) << std::setprecision(3) << T0 << '\n';
139
140 out << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD CenterX "
141 " CenterY CenterZ BaseX BaseY BaseZ UpX UpY "
142 " UpZ\n";
143 }
144 // Here would save each detector...
145 const auto &componentInfo = ws->componentInfo();
146 std::set<int>::iterator it;
147 for (it = uniqueBanks.begin(); it != uniqueBanks.end(); ++it) {
148 // Build up the bank name
149 int bank = *it;
150 std::ostringstream mess;
151 if (bankPart == "WISHpanel" && bank < 10)
152 mess << bankPart << "0" << bank;
153 else
154 mess << bankPart << bank;
155
156 std::string bankName = mess.str();
157 // Retrieve it
158 std::shared_ptr<const IComponent> det = inst->getComponentByName(bankName);
159 if (inst->getName() == "CORELLI") // for Corelli with sixteenpack under bank
160 {
161 const size_t bankIndex = componentInfo.indexOfAny(bankName);
162 const auto children = componentInfo.children(bankIndex);
163 if (!children.empty()) {
164 det = IComponent_const_sptr(componentInfo.componentID(children[0]), NoDeleting());
165 }
166 }
167 if (det) {
168 // Center of the detector
169 V3D center = det->getPos();
170
171 // Distance to center of detector
172 double detd = (center - inst->getSample()->getPos()).norm();
173 int NCOLS, NROWS;
174 double xsize, ysize;
175 sizeBanks(bankName, NCOLS, NROWS, xsize, ysize, componentInfo);
176 // Base unit vector (along the horizontal, X axis)
177 // Since WISH banks are curved use center and increment 2 for tubedown
178 int midX = NCOLS / 2;
179 int midY = NROWS / 2;
180 V3D base =
181 findPixelPos(bankName, midX + 2, midY, componentInfo) - findPixelPos(bankName, midX, midY, componentInfo);
182 base.normalize();
183
184 // Up unit vector (along the vertical, Y axis)
185 V3D up =
186 findPixelPos(bankName, midX, midY + 1, componentInfo) - findPixelPos(bankName, midX, midY, componentInfo);
187 up.normalize();
188
189 // Write the line
190 out << "5 " << std::setw(6) << std::right << bank << " " << std::setw(6) << std::right << NROWS << " "
191 << std::setw(6) << std::right << NCOLS << " " << std::setw(7) << std::right << std::fixed
192 << std::setprecision(4) << 100.0 * xsize << " " << std::setw(7) << std::right << std::fixed
193 << std::setprecision(4) << 100.0 * ysize << " "
194 << " 0.2000 " << std::setw(6) << std::right << std::fixed << std::setprecision(2) << 100.0 * detd << " "
195 << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0 * center.X() << " "
196 << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0 * center.Y() << " "
197 << std::setw(9) << std::right << std::fixed << std::setprecision(4) << 100.0 * center.Z() << " "
198 << std::setw(8) << std::right << std::fixed << std::setprecision(5) << base.X() << " " << std::setw(8)
199 << std::right << std::fixed << std::setprecision(5) << base.Y() << " " << std::setw(8) << std::right
200 << std::fixed << std::setprecision(5) << base.Z() << " " << std::setw(8) << std::right << std::fixed
201 << std::setprecision(5) << up.X() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5)
202 << up.Y() << " " << std::setw(8) << std::right << std::fixed << std::setprecision(5) << up.Z() << " \n";
203
204 } else
205 g_log.warning() << "Information about detector module " << bankName << " not found and recognised\n";
206 }
207
208 out.close();
209}
210
211V3D SaveIsawDetCal::findPixelPos(const std::string &bankName, int col, int row, const ComponentInfo &componentInfo) {
212 std::shared_ptr<const IComponent> parent = inst->getComponentByName(bankName);
213 if (parent->type() == "RectangularDetector") {
214 std::shared_ptr<const RectangularDetector> RDet = std::dynamic_pointer_cast<const RectangularDetector>(parent);
215
216 std::shared_ptr<Detector> pixel = RDet->getAtXY(col, row);
217 return pixel->getPos();
218 } else {
219 const size_t parentIndex = componentInfo.indexOfAny(bankName);
220 auto children = componentInfo.children(parentIndex);
221 if (!children.empty() && componentInfo.name(children[0]) == "sixteenpack") {
222 children = componentInfo.children(children[0]);
223 }
224 int col0 = col - 1;
225 // WISH detectors are in bank in this order in instrument
226 if (inst->getName() == "WISH")
227 col0 = (col % 2 == 0 ? col / 2 + 75 : (col - 1) / 2);
228 const auto grandchildren = componentInfo.children(children[col0]);
229 return componentInfo.position(grandchildren[row - 1]);
230 }
231}
232
233void SaveIsawDetCal::sizeBanks(const std::string &bankName, int &NCOLS, int &NROWS, double &xsize, double &ysize,
234 const ComponentInfo &componentInfo) {
235 if (bankName == "None")
236 return;
237 std::shared_ptr<const IComponent> parent = inst->getComponentByName(bankName);
238 if (parent->type() == "RectangularDetector") {
239 std::shared_ptr<const RectangularDetector> RDet = std::dynamic_pointer_cast<const RectangularDetector>(parent);
240
241 NCOLS = RDet->xpixels();
242 NROWS = RDet->ypixels();
243 xsize = RDet->xsize();
244 ysize = RDet->ysize();
245 } else {
246 const size_t parentIndex = componentInfo.indexOfAny(bankName);
247 auto children = componentInfo.children(parentIndex);
248 if (!children.empty() && componentInfo.name(children[0]) == "sixteenpack") {
249 children = componentInfo.children(children[0]);
250 }
251 const auto grandchildren = componentInfo.children(children[0]);
252 NROWS = static_cast<int>(grandchildren.size());
253 NCOLS = static_cast<int>(children.size());
254 const auto &first = componentInfo.componentID(children[0]);
255 const auto &last = componentInfo.componentID(children[NCOLS - 1]);
256 xsize = first->getDistance(*last);
257 const auto &firstGrand = componentInfo.componentID(grandchildren[0]);
258 const auto &lastGrand = componentInfo.componentID(grandchildren[NROWS - 1]);
259 ysize = firstGrand->getDistance(*lastGrand);
260 }
261}
262} // namespace Mantid::DataHandling
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:538
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Kernel::Logger & g_log
Definition Algorithm.h:422
@ Save
to specify a file to write to, the file may or may not exist
bool hasProperty(const std::string &name) const
Does the property exist on the object.
HeldType getPropertyValueAsType(const std::string &name) const
Get the value of a property as the given TYPE.
This class stores information regarding an experimental run as a series of log entries.
Definition Run.h:35
A property class for workspaces.
Saves an instrument with RectangularDetectors to an ISAW .DetCal file.
Kernel::V3D findPixelPos(const std::string &bankName, int col, int row, const Geometry::ComponentInfo &componentInfo)
find position for rectangular and non-rectangular
void sizeBanks(const std::string &bankName, int &NCOLS, int &NROWS, double &xsize, double &ysize, const Geometry::ComponentInfo &componentInfo)
void exec() override
Run the algorithm.
Geometry::Instrument_const_sptr inst
ComponentInfo : Provides a component centric view on to the instrument.
size_t indexOfAny(const std::string &name) const
Kernel::V3D position(const size_t componentIndex) const
const std::vector< size_t > & children(size_t componentIndex) const
const IComponent * componentID(const size_t componentIndex) const
const std::string & name(const size_t componentIndex) const
virtual double getDistance(const IComponent &) const =0
Get the distance to another IComponent.
Support for a property that holds an array of values.
void notice(const std::string &msg)
Logs at notice level.
Definition Logger.cpp:126
void warning(const std::string &msg)
Logs at warning level.
Definition Logger.cpp:117
Class for 3D vectors.
Definition V3D.h:34
constexpr double X() const noexcept
Get x.
Definition V3D.h:238
double normalize()
Make a normalized vector (return norm value)
Definition V3D.cpp:129
constexpr double Y() const noexcept
Get y.
Definition V3D.h:239
constexpr double Z() const noexcept
Get z.
Definition V3D.h:240
This functor is used as the deleter object of a shared_ptr to effectively erase ownership Raw pointer...
Definition IComponent.h:173
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< ExperimentInfo > ExperimentInfo_sptr
Shared pointer to ExperimentInfo.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:167
int convert(const std::string &A, T &out)
Convert a string into a number.
Definition Strings.cpp:696
@ Input
An input workspace.
Definition Property.h:53