28#include <boost/algorithm/string/trim.hpp>
39using namespace Kernel;
41using namespace Geometry;
42using namespace DataObjects;
48 std::make_shared<InstrumentValidator>()),
49 "The workspace containing the geometry to be calibrated.");
51 const auto exts = std::vector<std::string>({
".DetCal",
".detcal",
".peaks",
".integrate"});
52 declareProperty(std::make_unique<API::MultipleFileProperty>(
"Filename", exts),
53 "The input filename of the ISAW DetCal file (Two files "
54 "allowed for SNAP) ");
57 "The input filename of the second ISAW DetCal file (West "
64const constexpr double DegreesPerRadian = 180.0 / M_PI;
66std::string getBankName(
const std::string &bankPart,
const int idnum) {
67 if (bankPart ==
"WISHpanel" && idnum < 10) {
77 return matrixWksp->getInstrument()->getName();
82 return peaksWksp->getInstrument()->getName();
85 throw std::runtime_error(
"Failed to determine instrument name");
90 std::map<std::string, std::string> result;
94 if (filenames.empty()) {
95 result[
"Filename"] =
"Must supply .detcal file";
96 }
else if (filenames.size() == 2) {
98 const auto instname = getInstName(wksp);
100 if (instname !=
"SNAP") {
101 result[
"Filename"] =
"Two files is only valid for SNAP";
103 }
else if (filenames.size() > 2) {
104 result[
"Filename"] =
"Supply at most two .detcal files";
122 std::string instname = inst->getName();
128 double width,
height, depth, detd,
x,
y,
z, base_x, base_y, base_z, up_x, up_y, up_z;
129 std::ifstream input(filenames[0].c_str(), std::ios_base::in);
133 std::vector<std::shared_ptr<RectangularDetector>> detList;
134 for (
int i = 0; i < inst->nelements(); i++) {
135 std::shared_ptr<RectangularDetector> det;
136 std::shared_ptr<ICompAssembly> assem;
137 std::shared_ptr<ICompAssembly> assem2;
139 det = std::dynamic_pointer_cast<RectangularDetector>((*inst)[i]);
141 detList.emplace_back(det);
146 assem = std::dynamic_pointer_cast<ICompAssembly>((*inst)[i]);
148 for (
int j = 0; j < assem->nelements(); j++) {
149 det = std::dynamic_pointer_cast<RectangularDetector>((*assem)[j]);
151 detList.emplace_back(det);
158 assem2 = std::dynamic_pointer_cast<ICompAssembly>((*assem)[j]);
160 for (
int k = 0; k < assem2->nelements(); k++) {
161 det = std::dynamic_pointer_cast<RectangularDetector>((*assem2)[k]);
163 detList.emplace_back(det);
172 std::unordered_set<int> uniqueBanks;
173 std::string bankPart =
"bank";
174 if (instname ==
"WISH")
175 bankPart =
"WISHpanel";
176 if (detList.empty()) {
178 std::vector<IComponent_const_sptr> comps;
179 inst->getChildren(comps,
true);
181 for (
auto &comp : comps) {
182 std::string bankName = comp->getName();
183 boost::trim(bankName);
184 boost::erase_all(bankName, bankPart);
190 uniqueBanks.insert(bank);
194 auto expInfoWS = std::dynamic_pointer_cast<ExperimentInfo>(ws);
195 auto &componentInfo = expInfoWS->mutableComponentInfo();
196 std::vector<ComponentScaling> rectangularDetectorScalings;
198 while (std::getline(input, line)) {
199 if (line[0] ==
'7') {
201 std::stringstream(line) >>
count >> mL1 >> mT0;
204 if (instname ==
"WISH")
205 center(0.0, 0.0, -mL1,
"undulator", ws, componentInfo);
207 center(0.0, 0.0, -mL1,
"moderator", ws, componentInfo);
211 API::Run &run = inputW->mutableRun();
218 alg1->setProperty(
"Offset", mT0 - T0IDF);
220 alg1->setProperty(
"Offset", mT0);
222 alg1->executeAsChildAlg();
223 inputW = alg1->getProperty(
"OutputWorkspace");
228 API::Run &run = inputP->mutableRun();
238 base_x >> base_y >> base_z >> up_x >> up_y >> up_z;
239 if (
id == 10 && filenames.size() == 2 && instname ==
"SNAP") {
241 input.open(filenames[1].c_str());
242 while (std::getline(input, line)) {
247 base_x >> base_y >> base_z >> up_x >> up_y >> up_z;
252 std::shared_ptr<RectangularDetector> det;
253 std::string bankName = getBankName(bankPart,
id);
254 auto matchingDetector =
255 std::find_if(detList.begin(), detList.end(), [&bankName](
const std::shared_ptr<RectangularDetector> &detector) {
256 return detector->getName() == bankName;
258 if (matchingDetector != detList.end()) {
259 det = *matchingDetector;
262 V3D rX(base_x, base_y, base_z);
263 V3D rY(up_x, up_y, up_z);
266 detname = det->getName();
267 center(
x,
y,
z, detname, ws, componentInfo);
278 auto oldscalex =
pmap.getDouble(detname, std::string(
"scalex"));
279 auto oldscaley =
pmap.getDouble(detname, std::string(
"scaley"));
280 if (!oldscalex.empty())
281 detScaling.
scaleX *= oldscalex[0];
282 if (!oldscaley.empty())
283 detScaling.
scaleY *= oldscaley[0];
287 auto oldscalex =
pmap.getDouble(detname, std::string(
"scalex"));
288 auto oldscaley =
pmap.getDouble(detname, std::string(
"scaley"));
289 if (!oldscalex.empty())
290 detScaling.
scaleX *= oldscalex[0];
291 if (!oldscaley.empty())
292 detScaling.
scaleY *= oldscaley[0];
295 rectangularDetectorScalings.emplace_back(detScaling);
299 auto bank = uniqueBanks.find(
id);
300 if (bank == uniqueBanks.end())
304 bankName = getBankName(bankPart, idnum);
306 auto comp = inst->getComponentByName(bankName);
308 if (instname ==
"CORELLI") {
309 std::vector<Geometry::IComponent_const_sptr> children;
310 std::shared_ptr<const Geometry::ICompAssembly> asmb =
311 std::dynamic_pointer_cast<const Geometry::ICompAssembly>(inst->getComponentByName(bankName));
312 asmb->getChildren(children,
false);
317 detname = comp->getFullName();
318 center(
x,
y,
z, detname, ws, componentInfo);
320 bool doWishCorrection = (instname ==
"WISH");
321 doRotation(rX, rY, componentInfo, comp, doWishCorrection);
347 if (comp ==
nullptr) {
348 throw std::runtime_error(
"Component with name " + detname +
" was not found.");
353 const auto componentIndex = componentInfo.
indexOf(comp->getComponentID());
373 inst = std::const_pointer_cast<Instrument>(inputW->getInstrument());
375 throw std::runtime_error(
"Could not get a valid instrument from the "
376 "MatrixWorkspace provided as input");
378 inst = std::const_pointer_cast<Instrument>(inputP->getInstrument());
380 throw std::runtime_error(
"Could not get a valid instrument from the "
381 "PeaksWorkspace provided as input");
383 throw std::runtime_error(
"Could not get a valid instrument from the "
384 "workspace which does not seem to be valid as "
385 "input (must be either MatrixWorkspace or "
393 std::vector<std::string> filenamesFromPropertyUnraveld;
394 std::vector<std::vector<std::string>> filenamesFromProperty = this->
getProperty(
"Filename");
395 for (
const auto &outer : filenamesFromProperty) {
396 std::copy(outer.begin(), outer.end(), std::back_inserter(filenamesFromPropertyUnraveld));
400 const std::string filename2 = this->
getProperty(
"Filename2");
401 if (!filename2.empty())
402 filenamesFromPropertyUnraveld.emplace_back(filename2);
404 return filenamesFromPropertyUnraveld;
417 const std::shared_ptr<const IComponent> &comp,
bool doWishCorrection) {
423 constexpr V3D oX(1., 0., 0.);
424 constexpr V3D oY(0., 1., 0.);
431 double angle1 = oX.
angle(rX) * DegreesPerRadian;
432 if (doWishCorrection)
445 const double angle2 = roY.
angle(rY) * DegreesPerRadian;
449 const Quat Rot = Q2 * Q1;
452 const auto componentIndex = componentInfo.
indexOf(comp->getComponentID());
467 const std::vector<ComponentScaling> &rectangularDetectorScalings) {
469 for (
const auto &scaling : rectangularDetectorScalings) {
472 alg1->setProperty(
"ComponentName", scaling.componentName);
473 alg1->setProperty(
"ScaleX", scaling.scaleX);
474 alg1->setProperty(
"ScaleY", scaling.scaleY);
475 alg1->executeAsChildAlg();
#define DECLARE_ALGORITHM(classname)
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
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.
@ OptionalLoad
to specify a file to read but the file doesn't have to exist
bool hasProperty(const std::string &name) const
Does the property exist on the object.
void addProperty(Kernel::Property *prop, bool overwrite=false)
Add data to the object in the form of a property.
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.
A property class for workspaces.
std::vector< std::string > getFilenames()
Geometry::Instrument_sptr getCheckInst(const API::Workspace_sptr &ws)
Gets the instrument of the workspace, checking that the workspace and the instrument are as expected.
void init() override
Initialisation method.
void doRotation(Kernel::V3D rX, Kernel::V3D rY, Geometry::ComponentInfo &componentInfo, const std::shared_ptr< const Geometry::IComponent > &comp, bool doWishCorrection=false)
Perform the rotation for the calibration.
std::map< std::string, std::string > validateInputs() override
Perform validation of ALL the input properties of the algorithm.
void center(const double x, const double y, const double z, const std::string &detname, const API::Workspace_sptr &ws, Geometry::ComponentInfo &componentInfo)
Set the center of the supplied detector name.
void applyScalings(API::Workspace_sptr &ws, const std::vector< ComponentScaling > &rectangularDetectorScalings)
Apply the scalings from the calibration file.
void exec() override
Executes the algorithm.
ComponentInfo : Provides a component centric view on to the instrument.
void setRotation(size_t componentIndex, const Kernel::Quat &newRotation)
size_t indexOf(Geometry::IComponent *id) const
void setPosition(size_t componentIndex, const Kernel::V3D &newPosition)
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void rotate(V3D &) const
Rotate a vector.
void setAngleAxis(const double _deg, const V3D &_axis)
Constructor from an angle and axis.
double normalize()
Make a normalized vector (return norm value)
constexpr V3D cross_prod(const V3D &v) const noexcept
Cross product (this * argument)
double angle(const V3D &) const
Angle between this and another vector.
bool nullVector(const double tolerance=1e-3) const noexcept
Determine if the point is null.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const Workspace > Workspace_const_sptr
shared pointer to Mantid::API::Workspace (const version)
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< const PeaksWorkspace > PeaksWorkspace_const_sptr
Typedef for a shared pointer to a const peaks workspace.
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
std::shared_ptr< Instrument > Instrument_sptr
Shared pointer to an instrument object.
int convert(const std::string &A, T &out)
Convert a string into a number.
Generate a tableworkspace to store the calibration results.
std::string to_string(const wide_integer< Bits, Signed > &n)
std::string componentName
@ InOut
Both an input & output workspace.
@ Output
An output workspace.