Mantid
Loading...
Searching...
No Matches
DiffractionEventCalibrateDetectors.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/IFunction.h"
13#include "MantidAPI/TableRow.h"
14#include "MantidAPI/TextAxis.h"
27
28#include <cmath>
29#include <fstream>
30#include <numeric>
31#include <sstream>
32
33namespace Mantid::Algorithms {
34
35// Register the class into the algorithm factory
36DECLARE_ALGORITHM(DiffractionEventCalibrateDetectors)
37
38using namespace Kernel;
39using namespace API;
40using namespace Geometry;
41using namespace DataObjects;
42using Types::Core::DateAndTime;
43
50static double gsl_costFunction(const gsl_vector *v, void *params) {
51 double x, y, z, rotx, roty, rotz;
52 std::string detname, inname, outname, peakOpt, rb_param, groupWSName;
53 auto const *p = reinterpret_cast<std::string *>(params);
54 detname = p[0];
55 inname = p[1];
56 outname = p[2];
57 peakOpt = p[3];
58 rb_param = p[4];
59 groupWSName = p[5];
60 x = gsl_vector_get(v, 0);
61 y = gsl_vector_get(v, 1);
62 z = gsl_vector_get(v, 2);
63 rotx = gsl_vector_get(v, 3);
64 roty = gsl_vector_get(v, 4);
65 rotz = gsl_vector_get(v, 5);
67 return u.intensity(x, y, z, rotx, roty, rotz, detname, inname, outname, peakOpt, rb_param, groupWSName);
68}
69
82void DiffractionEventCalibrateDetectors::movedetector(double x, double y, double z, double rotx, double roty,
83 double rotz, const std::string &detname,
84 const EventWorkspace_sptr &inputW) {
85
86 auto alg1 = createChildAlgorithm("MoveInstrumentComponent");
87 alg1->setProperty<EventWorkspace_sptr>("Workspace", inputW);
88 alg1->setPropertyValue("ComponentName", detname);
89 // Move in cm for small shifts
90 alg1->setProperty("X", x * 0.01);
91 alg1->setProperty("Y", y * 0.01);
92 alg1->setProperty("Z", z * 0.01);
93 alg1->setPropertyValue("RelativePosition", "1");
94 alg1->executeAsChildAlg();
95
96 auto algx = createChildAlgorithm("RotateInstrumentComponent");
97 algx->setProperty<EventWorkspace_sptr>("Workspace", inputW);
98 algx->setPropertyValue("ComponentName", detname);
99 algx->setProperty("X", 1.0);
100 algx->setProperty("Y", 0.0);
101 algx->setProperty("Z", 0.0);
102 algx->setProperty("Angle", rotx);
103 algx->setPropertyValue("RelativeRotation", "1");
104 algx->executeAsChildAlg();
105
106 auto algy = createChildAlgorithm("RotateInstrumentComponent");
107 algy->setProperty<EventWorkspace_sptr>("Workspace", inputW);
108 algy->setPropertyValue("ComponentName", detname);
109 algy->setProperty("X", 0.0);
110 algy->setProperty("Y", 1.0);
111 algy->setProperty("Z", 0.0);
112 algy->setProperty("Angle", roty);
113 algy->setPropertyValue("RelativeRotation", "1");
114 algy->executeAsChildAlg();
115
116 auto algz = createChildAlgorithm("RotateInstrumentComponent");
117 algz->setProperty<EventWorkspace_sptr>("Workspace", inputW);
118 algz->setPropertyValue("ComponentName", detname);
119 algz->setProperty("X", 0.0);
120 algz->setProperty("Y", 0.0);
121 algz->setProperty("Z", 1.0);
122 algz->setProperty("Angle", rotz);
123 algz->setPropertyValue("RelativeRotation", "1");
124 algz->executeAsChildAlg();
125}
143double DiffractionEventCalibrateDetectors::intensity(double x, double y, double z, double rotx, double roty,
144 double rotz, const std::string &detname, const std::string &inname,
145 const std::string &outname, const std::string &peakOpt,
146 const std::string &rb_param, const std::string &groupWSName) {
147
148 EventWorkspace_sptr inputW =
149 std::dynamic_pointer_cast<EventWorkspace>(AnalysisDataService::Instance().retrieve(inname));
150
151 CPUTimer tim;
152
153 movedetector(x, y, z, rotx, roty, rotz, detname, inputW);
154 g_log.debug() << tim << " to movedetector()\n";
155
156 auto alg3 = createChildAlgorithm("ConvertUnits");
157 alg3->setProperty<EventWorkspace_sptr>("InputWorkspace", inputW);
158 alg3->setPropertyValue("OutputWorkspace", outname);
159 alg3->setPropertyValue("Target", "dSpacing");
160 alg3->executeAsChildAlg();
161 MatrixWorkspace_sptr outputW = alg3->getProperty("OutputWorkspace");
162
163 g_log.debug() << tim << " to ConvertUnits\n";
164
165 auto alg4 = createChildAlgorithm("DiffractionFocussing");
166 alg4->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputW);
167 alg4->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputW);
168 alg4->setPropertyValue("GroupingFileName", "");
169 alg4->setPropertyValue("GroupingWorkspace", groupWSName);
170 alg4->executeAsChildAlg();
171 outputW = alg4->getProperty("OutputWorkspace");
172
173 // Remove file
174 g_log.debug() << tim << " to DiffractionFocussing\n";
175
176 auto alg5 = createChildAlgorithm("Rebin");
177 alg5->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputW);
178 alg5->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputW);
179 alg5->setPropertyValue("Params", rb_param);
180 alg5->executeAsChildAlg();
181 outputW = alg5->getProperty("OutputWorkspace");
182
183 g_log.debug() << tim << " to Rebin\n";
184
185 // Find point of peak centre
186 Mantid::HistogramData::HistogramY const &yValues = outputW->y(0);
187 auto it = std::max_element(yValues.begin(), yValues.end());
188 double peakHeight = *it;
189 if (peakHeight == 0)
190 return -0.000;
191 double peakLoc = outputW->x(0)[it - yValues.begin()];
192
193 IAlgorithm_sptr fit_alg;
194 try {
195 // set the ChildAlgorithm no to log as this will be run once per spectra
196 fit_alg = createChildAlgorithm("Fit", -1, -1, false);
197 } catch (Exception::NotFoundError &) {
198 g_log.error("Can't locate Fit algorithm");
199 throw;
200 }
201 std::ostringstream fun_str;
202 fun_str << "name=Gaussian,Height=" << peakHeight << ",Sigma=0.01,PeakCentre=" << peakLoc;
203 fit_alg->setProperty("Function", fun_str.str());
204 fit_alg->setProperty("InputWorkspace", outputW);
205 fit_alg->setProperty("WorkspaceIndex", 0);
206 fit_alg->setProperty("StartX", outputW->x(0)[0]);
207 fit_alg->setProperty("EndX", outputW->x(0)[outputW->blocksize()]);
208 fit_alg->setProperty("MaxIterations", 200);
209 fit_alg->setProperty("Output", "fit");
210 fit_alg->executeAsChildAlg();
211
212 g_log.debug() << tim << " to Fit\n";
213
214 std::vector<double> params; // = fit_alg->getProperty("Parameters");
215 Mantid::API::IFunction_sptr fun_res = fit_alg->getProperty("Function");
216 for (size_t i = 0; i < fun_res->nParams(); ++i) {
217 params.emplace_back(fun_res->getParameter(i));
218 }
219 peakHeight = params[0];
220 peakLoc = params[1];
221
222 movedetector(-x, -y, -z, -rotx, -roty, -rotz, detname, inputW);
223
224 g_log.debug() << tim << " to movedetector()\n";
225
226 // Optimize C/peakheight + |peakLoc-peakOpt| where C is scaled by number of
227 // events
228 EventWorkspace_const_sptr inputE = std::dynamic_pointer_cast<const EventWorkspace>(inputW);
229 return (static_cast<int>(inputE->getNumberEvents()) / 1.e6) / peakHeight +
230 std::fabs(peakLoc - boost::lexical_cast<double>(peakOpt));
231}
232
236 declareProperty(std::make_unique<WorkspaceProperty<EventWorkspace>>("InputWorkspace", "", Direction::Input,
237 std::make_shared<InstrumentValidator>()),
238 "The workspace containing the geometry to be calibrated.");
239
240 declareProperty("Params", "",
241 "A comma separated list of first bin boundary, width, last "
242 "bin boundary. Optionally "
243 "this can be followed by a comma and more widths and last "
244 "boundary pairs. "
245 "Use bin boundaries close to peak you wish to maximize. "
246 "Negative width values indicate logarithmic binning.");
247
248 auto mustBePositive = std::make_shared<BoundedValidator<int>>();
249 declareProperty("MaxIterations", 10, mustBePositive,
250 "Stop after this number of iterations if a good fit is not found");
251
252 auto dblmustBePositive = std::make_shared<BoundedValidator<double>>();
253 declareProperty("LocationOfPeakToOptimize", 2.0308, dblmustBePositive,
254 "Optimize this location of peak by moving detectors");
255
256 declareProperty(std::make_unique<API::FileProperty>("DetCalFilename", "", API::FileProperty::Save, ".DetCal"),
257 "The output filename of the ISAW DetCal file");
258
259 declareProperty(std::make_unique<PropertyWithValue<std::string>>("BankName", "", Direction::Input),
260 "Optional: To only calibrate one bank. Any bank whose name does not "
261 "match the given string will have no events.");
262
263 // Disable default gsl error handler (which is to call abort!)
264 gsl_set_error_handler_off();
265}
266
272 // Try to retrieve optional properties
273 const int maxIterations = getProperty("MaxIterations");
274 const double peakOpt = getProperty("LocationOfPeakToOptimize");
275
276 // Get the input workspace
277 EventWorkspace_sptr inputW = getProperty("InputWorkspace");
278
279 // retrieve the properties
280 const std::string rb_params = getProperty("Params");
281
282 // Get some stuff from the input workspace
283 // We make a copy of the instrument since we will be moving detectors in
284 // `inputW` but want to access original positions (etc.) via `detList` below.
285 const auto &dummyW = create<EventWorkspace>(*inputW, 1, inputW->binEdges(0));
286 Instrument_const_sptr inst = dummyW->getInstrument();
287 const auto &componentInfo = dummyW->componentInfo();
288
289 // Build a list of Rectangular/Grid Detectors (as component indices)
290 std::vector<size_t> detList;
291 // --------- Loading only one bank ----------------------------------
292 std::string onebank = getProperty("BankName");
293 bool doOneBank = (!onebank.empty());
294 for (size_t i = 0; i < componentInfo.size(); ++i) {
295 if (componentInfo.isGridDetector(i) && (!doOneBank || componentInfo.name(i) == onebank)) {
296 detList.emplace_back(i);
297 }
298 }
299
300 // set-up minimizer
301
302 std::string inname = getProperty("InputWorkspace");
303 std::string outname = inname + "2"; // getProperty("OutputWorkspace");
304
305 auto algS = createChildAlgorithm("SortEvents");
306 algS->setProperty("InputWorkspace", inputW);
307 algS->setPropertyValue("SortBy", "X Value");
308 algS->executeAsChildAlg();
309
310 // Write DetCal File
311 std::string filename = getProperty("DetCalFilename");
312 std::fstream outfile;
313 outfile.open(filename.c_str(), std::ios::out);
314
315 if (detList.size() > 1) {
316 outfile << "#\n";
317 outfile << "# Mantid Optimized .DetCal file for SNAP with TWO detector "
318 "panels\n";
319 outfile << "# Old Panel, nominal size and distance at -90 degrees.\n";
320 outfile << "# New Panel, nominal size and distance at +90 degrees.\n";
321 outfile << "#\n";
322 outfile << "# Lengths are in centimeters.\n";
323 outfile << "# Base and up give directions of unit vectors for a local\n";
324 outfile << "# x,y coordinate system on the face of the detector.\n";
325 outfile << "#\n";
326 outfile << "# " << DateAndTime::getCurrentTime().toFormattedString("%c") << "\n";
327 outfile << "#\n";
328 outfile << "6 L1 T0_SHIFT\n";
329 IComponent_const_sptr source = inst->getSource();
330 IComponent_const_sptr sample = inst->getSample();
331 outfile << "7 " << source->getDistance(*sample) * 100 << " 0\n";
332 outfile << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD "
333 "CenterX CenterY CenterZ BaseX BaseY BaseZ "
334 "UpX UpY UpZ\n";
335 }
336
337 Progress prog(this, 0.0, 1.0, detList.size());
338 for (int det = 0; det < static_cast<int>(detList.size()); det++) {
339 const size_t bankIndex = detList[det];
340 const std::string bankName = componentInfo.name(bankIndex);
341 std::string par[6];
342 par[0] = bankName;
343 par[1] = inname;
344 par[2] = outname;
345 std::ostringstream strpeakOpt;
346 strpeakOpt << peakOpt;
347 par[3] = strpeakOpt.str();
348 par[4] = rb_params;
349
350 // --- Create a GroupingWorkspace for this detector name ------
351 CPUTimer tim;
352 auto alg2 = AlgorithmFactory::Instance().create("CreateGroupingWorkspace", 1);
353 alg2->initialize();
354 alg2->setProperty("InputWorkspace", inputW);
355 alg2->setPropertyValue("GroupNames", bankName);
356 std::string groupWSName = "group_" + bankName;
357 alg2->setPropertyValue("OutputWorkspace", groupWSName);
358 alg2->executeAsChildAlg();
359 par[5] = groupWSName;
360 std::cout << tim << " to CreateGroupingWorkspace\n";
361
362 const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
363 gsl_vector *ss, *x;
364 gsl_multimin_function minex_func;
365
366 // finally do the fitting
367
368 int nopt = 6;
369 int iter = 0;
370 int status = 0;
371
372 /* Starting point */
373 x = gsl_vector_alloc(nopt);
374 gsl_vector_set(x, 0, 0.0);
375 gsl_vector_set(x, 1, 0.0);
376 gsl_vector_set(x, 2, 0.0);
377 gsl_vector_set(x, 3, 0.0);
378 gsl_vector_set(x, 4, 0.0);
379 gsl_vector_set(x, 5, 0.0);
380
381 /* Set initial step sizes to 0.1 */
382 ss = gsl_vector_alloc(nopt);
383 gsl_vector_set_all(ss, 0.1);
384
385 /* Initialize method and iterate */
386 minex_func.n = nopt;
388 minex_func.params = &par;
389
390 gsl_multimin_fminimizer *s = gsl_multimin_fminimizer_alloc(T, nopt);
391 gsl_multimin_fminimizer_set(s, &minex_func, x, ss);
392
393 do {
394 iter++;
395 status = gsl_multimin_fminimizer_iterate(s);
396
397 if (status)
398 break;
399
400 double size = gsl_multimin_fminimizer_size(s);
401 status = gsl_multimin_test_size(size, 1e-2);
402
403 } while (status == GSL_CONTINUE && iter < maxIterations && s->fval != -0.000);
404
405 // Output summary to log file
406 if (s->fval != -0.000)
407 movedetector(gsl_vector_get(s->x, 0), gsl_vector_get(s->x, 1), gsl_vector_get(s->x, 2), gsl_vector_get(s->x, 3),
408 gsl_vector_get(s->x, 4), gsl_vector_get(s->x, 5), par[0], getProperty("InputWorkspace"));
409 else {
410 gsl_vector_set(s->x, 0, 0.0);
411 gsl_vector_set(s->x, 1, 0.0);
412 gsl_vector_set(s->x, 2, 0.0);
413 gsl_vector_set(s->x, 3, 0.0);
414 gsl_vector_set(s->x, 4, 0.0);
415 gsl_vector_set(s->x, 5, 0.0);
416 }
417
418 std::string reportOfDiffractionEventCalibrateDetectors = gsl_strerror(status);
419 if (s->fval == -0.000)
420 reportOfDiffractionEventCalibrateDetectors = "No events";
421
422 g_log.information() << "Detector = " << det << "\n"
423 << "Method used = "
424 << "Simplex"
425 << "\n"
426 << "Iteration = " << iter << "\n"
427 << "Status = " << reportOfDiffractionEventCalibrateDetectors << "\n"
428 << "Minimize PeakLoc-" << peakOpt << " = " << s->fval << "\n";
429 // Move in cm for small shifts
430 g_log.information() << "Move (X) = " << gsl_vector_get(s->x, 0) * 0.01 << " \n";
431 g_log.information() << "Move (Y) = " << gsl_vector_get(s->x, 1) * 0.01 << " \n";
432 g_log.information() << "Move (Z) = " << gsl_vector_get(s->x, 2) * 0.01 << " \n";
433 g_log.information() << "Rotate (X) = " << gsl_vector_get(s->x, 3) << " \n";
434 g_log.information() << "Rotate (Y) = " << gsl_vector_get(s->x, 4) << " \n";
435 g_log.information() << "Rotate (Z) = " << gsl_vector_get(s->x, 5) << " \n";
436
437 Kernel::V3D CalCenter =
438 V3D(gsl_vector_get(s->x, 0) * 0.01, gsl_vector_get(s->x, 1) * 0.01, gsl_vector_get(s->x, 2) * 0.01);
439 const auto grid = componentInfo.pixelGridComponent(bankIndex);
440 Kernel::V3D Center = componentInfo.position(bankIndex) + CalCenter;
441 int pixmax = grid.nX - 1;
442 int pixmid = (grid.nY - 1) / 2;
443 BoundingBox box = componentInfo.boundingBox(componentInfo.detectorIndexAtXYZ(bankIndex, pixmax, pixmid, 0));
444 double baseX = box.xMax();
445 double baseY = box.yMax();
446 double baseZ = box.zMax();
447 Kernel::V3D Base = V3D(baseX, baseY, baseZ) + CalCenter;
448 pixmid = (grid.nX - 1) / 2;
449 pixmax = grid.nY - 1;
450 box = componentInfo.boundingBox(componentInfo.detectorIndexAtXYZ(bankIndex, pixmid, pixmax, 0));
451 double upX = box.xMax();
452 double upY = box.yMax();
453 double upZ = box.zMax();
454 Kernel::V3D Up = V3D(upX, upY, upZ) + CalCenter;
455 Base -= Center;
456 Up -= Center;
457 // Rotate around x
458 baseX = Base[0];
459 baseY = Base[1];
460 baseZ = Base[2];
461 double deg2rad = M_PI / 180.0;
462 double angle = gsl_vector_get(s->x, 3) * deg2rad;
463 Base = V3D(baseX, baseY * cos(angle) - baseZ * sin(angle), baseY * sin(angle) + baseZ * cos(angle));
464 upX = Up[0];
465 upY = Up[1];
466 upZ = Up[2];
467 Up = V3D(upX, upY * cos(angle) - upZ * sin(angle), upY * sin(angle) + upZ * cos(angle));
468 // Rotate around y
469 baseX = Base[0];
470 baseY = Base[1];
471 baseZ = Base[2];
472 angle = gsl_vector_get(s->x, 4) * deg2rad;
473 Base = V3D(baseZ * sin(angle) + baseX * cos(angle), baseY, baseZ * cos(angle) - baseX * sin(angle));
474 upX = Up[0];
475 upY = Up[1];
476 upZ = Up[2];
477 Up = V3D(upZ * cos(angle) - upX * sin(angle), upY, upZ * sin(angle) + upX * cos(angle));
478 // Rotate around z
479 baseX = Base[0];
480 baseY = Base[1];
481 baseZ = Base[2];
482 angle = gsl_vector_get(s->x, 5) * deg2rad;
483 Base = V3D(baseX * cos(angle) - baseY * sin(angle), baseX * sin(angle) + baseY * cos(angle), baseZ);
484 upX = Up[0];
485 upY = Up[1];
486 upZ = Up[2];
487 Up = V3D(upX * cos(angle) - upY * sin(angle), upX * sin(angle) + upY * cos(angle), upZ);
488 Base.normalize();
489 Up.normalize();
490 Center *= 100.0;
491 // << det+1 << " "
492 outfile << "5 " << bankName.substr(4) << " " << grid.nX << " " << grid.nY << " "
493 << 100.0 * (grid.nX * grid.xStep) << " " << 100.0 * (grid.nY * grid.yStep) << " "
494 << "0.2000"
495 << " " << Center.norm() << " ";
496 Center.write(outfile);
497 outfile << " ";
498 Base.write(outfile);
499 outfile << " ";
500 Up.write(outfile);
501 outfile << "\n";
502
503 // clean up dynamically allocated gsl stuff
504 gsl_vector_free(x);
505 gsl_vector_free(ss);
506 gsl_multimin_fminimizer_free(s);
507
508 // Remove the now-unneeded grouping workspace
509 AnalysisDataService::Instance().remove(groupWSName);
510 prog.report(bankName);
511 }
512
513 // Closing
514 outfile.close();
515}
516
517} // namespace Mantid::Algorithms
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
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.
Kernel::Logger & g_log
Definition Algorithm.h:423
@ Save
to specify a file to write to, the file may or may not exist
Helper class for reporting progress from algorithms.
Definition Progress.h:25
A property class for workspaces.
void movedetector(double x, double y, double z, double rotx, double roty, double rotz, const std::string &detname, const Mantid::DataObjects::EventWorkspace_sptr &inputW)
The movedetector function changes detector position and angles.
double intensity(double x, double y, double z, double rotx, double roty, double rotz, const std::string &detname, const std::string &inname, const std::string &outname, const std::string &peakOpt, const std::string &rb_param, const std::string &groupWSName)
Function to optimize.
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
double xMax() const
Return the maximum value of X.
Definition BoundingBox.h:79
double zMax() const
Return the maximum value of Z.
Definition BoundingBox.h:87
double yMax() const
Return the maximum value of Y.
Definition BoundingBox.h:83
CPUTimer : Timer that uses the CPU time, rather than wall-clock time to measure execution time.
Definition CPUTimer.h:24
Exception for when an item is not found in a collection.
Definition Exception.h:145
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
The concrete, templated class for properties.
Class for 3D vectors.
Definition V3D.h:34
double normalize()
Make a normalized vector (return norm value)
Definition V3D.cpp:129
double norm() const noexcept
Definition V3D.h:269
void write(std::ostream &) const
Write out the point values.
Definition V3D.cpp:322
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition IFunction.h:748
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
static double gsl_costFunction(const gsl_vector *v, void *params)
The gsl_costFunction is optimized by GSL simplex.
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
constexpr double deg2rad
Defines units/enum for Crystal work.
Definition AngleUnits.h:20
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:165
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
@ Input
An input workspace.
Definition Property.h:53