27#include <boost/container/flat_set.hpp>
28#include <boost/property_tree/ptree.hpp>
29#include <boost/property_tree/xml_parser.hpp>
31#include <boost/math/special_functions/round.hpp>
48Logger logger(
"SCDCalibratePanels2");
60 "Workspace of Indexed Peaks");
63 auto mustBeNonNegative = std::make_shared<BoundedValidator<double>>();
64 mustBeNonNegative->setLower(0.0);
65 declareProperty(
"RecalculateUB",
true,
"Recalculate UB matrix using given lattice constants");
66 declareProperty(
"a",
EMPTY_DBL(), mustBeNonNegative,
67 "Lattice Parameter a (Leave empty to use lattice constants "
68 "in peaks workspace)");
69 declareProperty(
"b",
EMPTY_DBL(), mustBeNonNegative,
70 "Lattice Parameter b (Leave empty to use lattice constants "
71 "in peaks workspace)");
72 declareProperty(
"c",
EMPTY_DBL(), mustBeNonNegative,
73 "Lattice Parameter c (Leave empty to use lattice constants "
74 "in peaks workspace)");
75 declareProperty(
"alpha",
EMPTY_DBL(), mustBeNonNegative,
76 "Lattice Parameter alpha in degrees (Leave empty to use "
77 "lattice constants in peaks workspace)");
78 declareProperty(
"beta",
EMPTY_DBL(), mustBeNonNegative,
79 "Lattice Parameter beta in degrees (Leave empty to use "
80 "lattice constants in peaks workspace)");
81 declareProperty(
"gamma",
EMPTY_DBL(), mustBeNonNegative,
82 "Lattice Parameter gamma in degrees (Leave empty to use "
83 "lattice constants in peaks workspace)");
84 const std::string LATTICE(
"Lattice Constants");
85 setPropertyGroup(
"RecalculateUB", LATTICE);
86 setPropertyGroup(
"a", LATTICE);
87 setPropertyGroup(
"b", LATTICE);
88 setPropertyGroup(
"c", LATTICE);
89 setPropertyGroup(
"alpha", LATTICE);
90 setPropertyGroup(
"beta", LATTICE);
91 setPropertyGroup(
"gamma", LATTICE);
92 setPropertySettings(
"a", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
93 setPropertySettings(
"b", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
94 setPropertySettings(
"c", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
95 setPropertySettings(
"alpha", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
96 setPropertySettings(
"beta", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
97 setPropertySettings(
"gamma", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
99 declareProperty(
"Tolerance", 0.15, mustBeNonNegative,
"Peak indexing tolerance");
101 declareProperty(
"WavelengthFromUB",
false,
102 "If True, compute each peak's wavelength from Bragg's law using the UB matrix and its "
103 "assigned integer HKL, instead of from the measured TOF. Intended for quasi-Laue workflows, "
104 "where a peak's TOF-derived wavelength can be unreliable, but works for standard "
105 "time-of-flight Laue data as well. NOTE: when enabled, CalibrateT0 has no effect, since "
106 "wavelength no longer depends on TOF.");
116 const std::string CALIBRATION(
"Calibration Options");
120 declareProperty(
"CalibrateL1",
true,
"Change the L1(source to sample) distance");
121 declareProperty(
"SearchRadiusL1", 0.1, mustBeNonNegative,
122 "Search radius of delta L1 in meters, which is used to constrain optimization search space"
123 "when calibrating L1");
125 setPropertySettings(
"SearchRadiusL1", std::make_unique<EnabledWhenProperty>(
"CalibrateL1",
IS_EQUAL_TO,
"1"));
127 setPropertyGroup(
"CalibrateL1", CALIBRATION);
128 setPropertyGroup(
"SearchRadiusL1", CALIBRATION);
132 declareProperty(
"CalibrateBanks",
false,
"Calibrate position and orientation of each bank.");
134 "SearchRadiusTransBank", 5e-2, mustBeNonNegative,
135 "This is the search radius (in meter) when calibrating component translations, used to constrain optimization"
136 "search space when calibration translation of banks");
137 declareProperty(
"SearchradiusRotXBank", 1.0, mustBeNonNegative,
138 "This is the search radius (in deg) when calibrating component reorientation, used to constrain "
139 "optimization search space");
140 declareProperty(
"SearchradiusRotYBank", 1.0, mustBeNonNegative,
141 "This is the search radius (in deg) when calibrating component reorientation, used to constrain "
142 "optimization search space");
143 declareProperty(
"SearchradiusRotZBank", 1.0, mustBeNonNegative,
144 "This is the search radius (in deg) when calibrating component reorientation, used to constrain "
145 "optimization search space");
146 declareProperty(
"CalibrateSize",
false,
"Calibrate detector size for each bank.");
147 declareProperty(
"SearchRadiusSize", 0.0, mustBeNonNegative,
148 "This is the search radius (unit less) of scale factor around at value 1.0 "
149 "when calibrating component size if it is a rectangualr detector.");
150 declareProperty(
"FixAspectRatio",
true,
151 "If true, the scaling factor for detector along X- and Y-axis "
152 "must be the same. Otherwise, the 2 scaling factors are free.");
153 declareProperty(
"BankName",
"",
154 "If given, only the specified bank/component will be calibrated."
155 "Otherwise, all banks will be calibrated.");
158 setPropertySettings(
"BankName", std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
159 setPropertySettings(
"SearchRadiusTransBank",
160 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
161 setPropertySettings(
"SearchradiusRotXBank",
162 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
163 setPropertySettings(
"SearchradiusRotYBank",
164 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
165 setPropertySettings(
"SearchradiusRotZBank",
166 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
167 setPropertySettings(
"CalibrateSize", std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
168 setPropertySettings(
"SearchRadiusSize", std::make_unique<EnabledWhenProperty>(
"CalibrateSize",
IS_EQUAL_TO,
"1"));
169 setPropertySettings(
"FixAspectRatio", std::make_unique<EnabledWhenProperty>(
"CalibrateSize",
IS_EQUAL_TO,
"1"));
171 setPropertyGroup(
"CalibrateBanks", CALIBRATION);
172 setPropertyGroup(
"BankName", CALIBRATION);
173 setPropertyGroup(
"SearchRadiusTransBank", CALIBRATION);
174 setPropertyGroup(
"SearchradiusRotXBank", CALIBRATION);
175 setPropertyGroup(
"SearchradiusRotYBank", CALIBRATION);
176 setPropertyGroup(
"SearchradiusRotZBank", CALIBRATION);
177 setPropertyGroup(
"CalibrateSize", CALIBRATION);
178 setPropertyGroup(
"SearchRadiusSize", CALIBRATION);
179 setPropertyGroup(
"FixAspectRatio", CALIBRATION);
184 declareProperty(
"CalibrateT0",
false,
"Calibrate the T0 (initial TOF)");
185 declareProperty(
"SearchRadiusT0", 10.0, mustBeNonNegative,
186 "Search radius of T0 (in ms), used to constrain optimization search space");
188 setPropertySettings(
"SearchRadiusT0", std::make_unique<EnabledWhenProperty>(
"CalibrateT0",
IS_EQUAL_TO,
"1"));
190 setPropertyGroup(
"CalibrateT0", CALIBRATION);
191 setPropertyGroup(
"SearchRadiusT0", CALIBRATION);
195 declareProperty(
"TuneSamplePosition",
false,
"Fine tunning sample position");
196 declareProperty(
"SearchRadiusSamplePos", 0.1, mustBeNonNegative,
197 "Search radius of sample position change (in meters), used to constrain optimization search space");
199 setPropertySettings(
"SearchRadiusSamplePos",
200 std::make_unique<EnabledWhenProperty>(
"TuneSamplePosition",
IS_EQUAL_TO,
"1"));
202 setPropertyGroup(
"TuneSamplePosition", CALIBRATION);
203 setPropertyGroup(
"SearchRadiusSamplePos", CALIBRATION);
207 "The workspace containing the calibration table.");
209 const std::vector<std::string> detcalExts{
".DetCal",
".Det_Cal"};
212 "Path to an ISAW-style .detcal file to save.");
215 "Path to an Mantid .xml description(for LoadParameterFile) file to "
219 "Path to an .csv file which contains the Calibration Table");
221 const std::string OUTPUT(
"Output");
222 setPropertyGroup(
"OutputWorkspace", OUTPUT);
223 setPropertyGroup(
"DetCalFilename", OUTPUT);
224 setPropertyGroup(
"XmlFilename", OUTPUT);
225 setPropertyGroup(
"CSVFilename", OUTPUT);
229 declareProperty(
"VerboseOutput",
false,
"Toggle of child algorithm console output.");
230 declareProperty(
"ProfileL1",
false,
"Perform profiling of objective function with given input for L1");
231 declareProperty(
"ProfileBanks",
false,
"Perform profiling of objective function with given input for Banks");
232 declareProperty(
"ProfileT0",
false,
"Perform profiling of objective function with given input for T0");
233 declareProperty(
"ProfileL1T0",
false,
"Perform profiling of objective function along L1 and T0");
235 const std::string ADVCNTRL(
"Advanced Option");
236 setPropertyGroup(
"VerboseOutput", ADVCNTRL);
237 setPropertyGroup(
"ProfileL1", ADVCNTRL);
238 setPropertyGroup(
"ProfileBanks", ADVCNTRL);
239 setPropertyGroup(
"ProfileT0", ADVCNTRL);
240 setPropertyGroup(
"ProfileL1T0", ADVCNTRL);
243 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<int>>();
244 mustBePositive->setLower(0);
245 declareProperty(
"MaxFitIterations", 500, mustBePositive,
246 "Stop after this number of iterations if a good fit is not found");
255 std::map<std::string, std::string> issues;
268 (!pws->sample().hasOrientedLattice())) {
269 issues[
"RecalculateUB"] =
"Lattice constants are needed for peak "
270 "workspace without a UB mattrix";
278 issues[
"CalibrateT0"] =
"CalibrateT0 has no effect when WavelengthFromUB is enabled, since wavelength no "
279 "longer depends on TOF.";
284 throw std::runtime_error(
"calibrationTableColumnTypes and calibrationTableColumnTypes have different size.");
312 bool calibrateBanks =
getProperty(
"CalibrateBanks");
313 bool tuneSamplePos =
getProperty(
"TuneSamplePosition");
320 const std::string DetCalFilename =
getProperty(
"DetCalFilename");
321 const std::string XmlFilename =
getProperty(
"XmlFilename");
322 const std::string CSVFilename =
getProperty(
"CSVFilename");
326 double sizesearchradius =
getProperty(
"SearchRadiusSize");
327 bool fixdetxyratio =
getProperty(
"FixAspectRatio");
333 std::vector<std::pair<std::string, bool>> criteria{{
"BankName",
true}};
334 m_pws->sort(criteria);
366 g_log.
notice() <<
"** Calibrating L1 (moderator) as requested\n";
370 if (calibrateBanks) {
371 g_log.
notice() <<
"** Calibrating L2 and orientation (bank) as requested\n";
372 optimizeBanks(m_pws, pws_original, docalibsize, sizesearchradius, fixdetxyratio);
375 if (calibrateL1 && calibrateBanks) {
376 g_log.
notice() <<
"** Calibrating L1 (moderator) after bank adjusted\n";
394 if (calibrateT0 && !calibrateL1) {
399 g_log.
notice() <<
"** Calibrating T0 only as requested\n";
403 if (tuneSamplePos && !calibrateL1) {
404 g_log.
notice() <<
"** Tunning sample position only as requested\n";
408 if (calibrateT0 && tuneSamplePos && !calibrateL1) {
409 g_log.
warning() <<
"** You have chosen to calibrate T0 and sample position while ignoring"
410 <<
" L1, which means an iterative search outside this calibration is needed"
411 <<
" in order to find the minimum.\n";
415 g_log.
notice() <<
"-- Generate calibration table\n";
416 Instrument_sptr instCalibrated = std::const_pointer_cast<Geometry::Instrument>(m_pws->getInstrument());
421 if (!XmlFilename.empty()) {
425 if (!DetCalFilename.empty()) {
429 if (!CSVFilename.empty()) {
449 double original_L1 = std::abs(pws->getInstrument()->getSource()->getPos().Z());
452 bool tuneSamplepos =
getProperty(
"TuneSamplePosition");
458 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
460 std::vector<double> tofs =
captureTOF(pws_original);
461 objf->setPeakWorkspace(pws,
"moderator", tofs,
m_waveFromUB);
462 fitL1_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
465 std::ostringstream tie_str;
466 tie_str <<
"DeltaX=0.0,DeltaY=0.0,"
467 <<
"RotX=0.0,RotY=0.0,RotZ=0.0";
468 if (!tuneSamplepos) {
469 tie_str <<
",DeltaSampleX=0.0,DeltaSampleY=0.0,DeltaSampleZ=0.0";
472 tie_str <<
",DeltaT0=" <<
m_T0;
474 std::ostringstream constraint_str;
476 r_L1 = std::abs(r_L1);
477 constraint_str << -r_L1 <<
"<DeltaZ<" << r_L1;
481 r_dT0 = std::abs(r_dT0);
482 constraint_str <<
"," << -r_dT0 <<
"<DeltaT0<" << r_dT0;
485 double r_dsp =
getProperty(
"SearchRadiusSamplePos");
486 r_dsp = std::abs(r_dsp);
487 constraint_str <<
"," << -r_dsp <<
"<DeltaSampleX<" << r_dsp
488 <<
"," << -r_dsp <<
"<DeltaSampleY<" << r_dsp
489 <<
"," << -r_dsp <<
"<DeltaSampleZ<" << r_dsp;
492 fitL1_alg->setProperty(
"Ties", tie_str.str());
493 fitL1_alg->setProperty(
"Constraints", constraint_str.str());
494 fitL1_alg->setProperty(
"InputWorkspace", l1ws);
495 fitL1_alg->setProperty(
"CreateOutput",
true);
496 fitL1_alg->setProperty(
"Output",
"fit");
497 fitL1_alg->executeAsChildAlg();
500 std::ostringstream calilog;
501 double chi2OverDOF = fitL1_alg->getProperty(
"OutputChi2overDoF");
504 double dL1_optimized = rst->getRef<
double>(
"Value", 2);
507 double dT0_optimized = rst->getRef<
double>(
"Value", 6);
513 double dsx_optimized = rst->getRef<
double>(
"Value", 7);
514 double dsy_optimized = rst->getRef<
double>(
"Value", 8);
515 double dsz_optimized = rst->getRef<
double>(
"Value", 9);
519 pws->getInstrument()->getSource()->getName(), pws);
520 m_T0 = dT0_optimized;
522 "sample-position", pws);
524 int npks = pws->getNumberPeaks();
525 calilog <<
"-- Fit L1 results using " << npks <<
" peaks:\n"
526 <<
" dL1: " << dL1_optimized <<
" \n"
527 <<
" L1 " << original_L1 <<
" -> " << -pws->getInstrument()->getSource()->getPos().Z() <<
" \n"
528 <<
" dT0 = " <<
m_T0 <<
" (ms)\n"
529 <<
" dSamplePos = (" << dsx_optimized <<
"," << dsy_optimized <<
"," << dsz_optimized <<
")\n"
530 <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
544 const bool &docalibsize,
const double &sizesearchradius,
545 const bool &fixdetxyratio) {
547 for (
int i = 0; i < static_cast<int>(
m_BankNames.size()); ++i) {
550 const std::string bankname = *std::next(
m_BankNames.begin(), i);
551 const std::string pwsBankiName =
"_pws_" + bankname;
557 std::stringstream ss;
558 ss <<
"i = " << i <<
" m bank name = " << bankname;
560 ss <<
" ... True ...";
562 ss <<
" ... Stop ...";
573 std::vector<double> tofs =
captureTOF(pwsBanki_original);
577 int nBankPeaks = pwsBanki->getNumberPeaks();
580 std::ostringstream msg_npeakCheckFail;
581 msg_npeakCheckFail <<
"-- Bank " << bankname <<
" have only " << nBankPeaks <<
" (<" <<
MINIMUM_PEAKS_PER_BANK
582 <<
") Peaks, skipping\n";
593 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
594 objf->setPeakWorkspace(pwsBanki, bankname, tofs,
m_waveFromUB);
595 fitBank_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
599 double searchRadiusRotX =
getProperty(
"SearchradiusRotXBank");
600 searchRadiusRotX = std::abs(searchRadiusRotX);
601 double searchRadiusRotY =
getProperty(
"SearchradiusRotYBank");
602 searchRadiusRotY = std::abs(searchRadiusRotY);
603 double searchRadiusRotZ =
getProperty(
"SearchradiusRotZBank");
604 searchRadiusRotZ = std::abs(searchRadiusRotZ);
606 double searchRadiusTran =
getProperty(
"SearchRadiusTransBank");
607 searchRadiusTran = std::abs(searchRadiusTran);
609 std::ostringstream tie_str;
610 tie_str <<
"DeltaSampleX=0.0,DeltaSampleY=0.0,DeltaSampleZ=0.0,"
611 <<
"DeltaT0=" <<
m_T0;
612 std::ostringstream constraint_str;
615 tie_str <<
",RotX=0.0";
617 constraint_str << -searchRadiusRotX <<
"<RotX<" << searchRadiusRotX <<
",";
621 tie_str <<
",RotY=0.0";
623 constraint_str << -searchRadiusRotY <<
"<RotY<" << searchRadiusRotY <<
",";
627 tie_str <<
",RotZ=0.0";
629 constraint_str << -searchRadiusRotZ <<
"<RotZ<" << searchRadiusRotZ <<
",";
633 tie_str <<
",DeltaX=0.0,DeltaY=0.0,DeltaZ=0.0";
635 constraint_str << -searchRadiusTran <<
"<DeltaX<" << searchRadiusTran <<
","
636 << -searchRadiusTran <<
"<DeltaY<" << searchRadiusTran <<
","
637 << -searchRadiusTran <<
"<DeltaZ<" << searchRadiusTran;
643 std::shared_ptr<const Geometry::RectangularDetector> rectDet =
644 std::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp);
648 std::ostringstream scaleconstraints;
649 std::ostringstream scaleties;
650 if (rectDet && docalibsize) {
652 scaleconstraints << scales.first - sizesearchradius <<
" <=ScaleX<" << scales.first + sizesearchradius;
654 scaleties <<
"ScaleX=ScaleY";
656 scaleconstraints <<
"," << scales.second - sizesearchradius <<
" <=ScaleY<" << scales.second + sizesearchradius;
660 scaleties <<
"ScaleX=" << scales.first <<
", ScaleY=" << scales.second;
664 std::string fitconstraint{constraint_str.str()};
665 if (scaleconstraints.str() !=
"") {
666 if (fitconstraint ==
"")
667 fitconstraint += scaleconstraints.str();
669 fitconstraint +=
"," + scaleconstraints.str();
671 std::string fittie{tie_str.str()};
672 if (scaleties.str() !=
"") {
674 fittie += scaleties.str();
676 fittie +=
"," + scaleties.str();
679 g_log.
information(
"Fitting " + bankname +
": constraint = " + fitconstraint +
"\n\t tie = " + fittie);
683 fitBank_alg->setProperty(
"Ties", fittie);
684 if (fitconstraint !=
"")
685 fitBank_alg->setProperty(
"Constraints", fitconstraint);
686 fitBank_alg->setProperty(
"InputWorkspace", wsBankCali);
687 fitBank_alg->setProperty(
"CreateOutput",
true);
688 fitBank_alg->setProperty(
"Output",
"fit");
691 fitBank_alg->executeAsChildAlg();
694 double chi2OverDOF = fitBank_alg->getProperty(
"OutputChi2overDoF");
696 double dx = rstFitBank->getRef<
double>(
"Value", 0);
697 double dy = rstFitBank->getRef<
double>(
"Value", 1);
698 double dz = rstFitBank->getRef<
double>(
"Value", 2);
699 double drx = rstFitBank->getRef<
double>(
"Value", 3);
700 double dry = rstFitBank->getRef<
double>(
"Value", 4);
701 double drz = rstFitBank->getRef<
double>(
"Value", 5);
702 double scalex = rstFitBank->getRef<
double>(
"Value", 10);
703 double scaley = rstFitBank->getRef<
double>(
"Value", 11);
706 std::string bn = bankname;
707 std::ostringstream calilog;
708 if (pws->getInstrument()->getName().compare(
"CORELLI") == 0) {
709 bn.append(
"/sixteenpack");
712 if (rectDet && docalibsize) {
721 V3D dtrans(dx, dy, dz);
722 V3D drots(drx, dry, drz);
723 calilog <<
"-- Fit " << bn <<
" results using " << nBankPeaks <<
" peaks:\n"
724 <<
" d(x,y,z) = " << dtrans <<
"\n"
725 <<
" r(x,y,z) = " << drots <<
"\n"
726 <<
" scale(x, y) = " <<
scalex <<
", " <<
scaley <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
761 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
763 std::vector<double> tofs =
captureTOF(pws_original);
764 objf->setPeakWorkspace(pws,
"none", tofs,
m_waveFromUB);
765 fitT0_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
768 std::ostringstream tie_str;
769 tie_str <<
"DeltaX=0.0,DeltaY=0.0,DeltaZ=0.0,"
770 <<
"RotX=0.0,RotY=0.0,RotZ=0.0,"
771 <<
"DeltaSampleX=0.0,DeltaSampleY=0.0,DeltaSampleZ=0.0";
772 std::ostringstream constraint_str;
774 r_dT0 = std::abs(r_dT0);
775 constraint_str << -r_dT0 <<
"<DeltaT0<" << r_dT0;
778 fitT0_alg->setProperty(
"Ties", tie_str.str());
779 fitT0_alg->setProperty(
"Constraints", constraint_str.str());
780 fitT0_alg->setProperty(
"InputWorkspace", t0ws);
781 fitT0_alg->setProperty(
"CreateOutput",
true);
782 fitT0_alg->setProperty(
"Output",
"fit");
783 fitT0_alg->executeAsChildAlg();
786 std::ostringstream calilog;
787 double chi2OverDOF = fitT0_alg->getProperty(
"OutputChi2overDoF");
789 double dT0_optimized = rst->getRef<
double>(
"Value", 6);
792 m_T0 = dT0_optimized;
793 int npks = pws->getNumberPeaks();
795 calilog <<
"-- Fit T0 results using " << npks <<
" peaks:\n"
796 <<
" dT0 = " <<
m_T0 <<
" (ms)\n"
797 <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
814 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
816 std::vector<double> tofs =
captureTOF(pws_original);
817 objf->setPeakWorkspace(pws,
"none", tofs,
m_waveFromUB);
818 fitSamplePos_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
821 std::ostringstream tie_str;
822 tie_str <<
"DeltaX=0.0,DeltaY=0.0,DeltaZ=0.0,"
823 <<
"RotX=0.0,RotY=0.0,RotZ=0.0,"
824 <<
"DeltaT0=" <<
m_T0;
825 std::ostringstream constraint_str;
826 double r_dsp =
getProperty(
"SearchRadiusSamplePos");
827 r_dsp = std::abs(r_dsp);
828 constraint_str << -r_dsp <<
"<DeltaSampleX<" << r_dsp <<
"," << -r_dsp <<
"<DeltaSampleY<" << r_dsp <<
"," << -r_dsp
829 <<
"<DeltaSampleZ<" << r_dsp;
832 fitSamplePos_alg->setProperty(
"Ties", tie_str.str());
833 fitSamplePos_alg->setProperty(
"Constraints", constraint_str.str());
834 fitSamplePos_alg->setProperty(
"InputWorkspace", samplePosws);
835 fitSamplePos_alg->setProperty(
"CreateOutput",
true);
836 fitSamplePos_alg->setProperty(
"Output",
"fit");
837 fitSamplePos_alg->executeAsChildAlg();
840 std::ostringstream calilog;
841 double chi2OverDOF = fitSamplePos_alg->getProperty(
"OutputChi2overDoF");
843 double dsx_optimized = rst->getRef<
double>(
"Value", 7);
844 double dsy_optimized = rst->getRef<
double>(
"Value", 8);
845 double dsz_optimized = rst->getRef<
double>(
"Value", 9);
849 "sample-position", pws);
850 int npks = pws->getNumberPeaks();
852 calilog <<
"-- Tune SamplePos results using " << npks <<
" peaks:\n"
853 <<
" deltaSamplePos = (" << dsx_optimized <<
"," << dsy_optimized <<
"," << dsz_optimized <<
")\n"
854 <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
878 (pws->sample().hasOrientedLattice())) {
898 calcUB_alg->setProperty(
"PeaksWorkspace", pws);
899 calcUB_alg->setProperty(
"a",
m_a);
900 calcUB_alg->setProperty(
"b",
m_b);
901 calcUB_alg->setProperty(
"c",
m_c);
902 calcUB_alg->setProperty(
"alpha",
m_alpha);
903 calcUB_alg->setProperty(
"beta",
m_beta);
904 calcUB_alg->setProperty(
"gamma",
m_gamma);
905 calcUB_alg->executeAsChildAlg();
912 idxpks_alg->setProperty(
"PeaksWorkspace", pws);
913 idxpks_alg->setProperty(
"RoundHKLs",
true);
914 idxpks_alg->setProperty(
"Tolerance", tol);
915 idxpks_alg->executeAsChildAlg();
927 fltpk_alg->setProperty(
"InputWorkspace", pws);
928 fltpk_alg->setProperty(
"FilterVariable",
"h^2+k^2+l^2");
929 fltpk_alg->setProperty(
"Operator",
">");
930 fltpk_alg->setProperty(
"FilterValue", 0.0);
931 fltpk_alg->setProperty(
"OutputWorkspace",
"pws_filtered");
932 fltpk_alg->executeAsChildAlg();
945 std::vector<double> tofs;
947 for (
int i = 0; i < pws->getNumberPeaks(); ++i) {
948 tofs.emplace_back(pws->getPeak(i).getTOF());
960 auto peaksWorkspace = std::dynamic_pointer_cast<DataObjects::PeaksWorkspace>(pws);
962 throw std::invalid_argument(
"a PeaksWorkspace is required to retrieve bank names");
963 int npeaks =
static_cast<int>(pws->getNumberPeaks());
964 for (
int i = 0; i < npeaks; ++i) {
965 std::string bname = peaksWorkspace->getPeak(i).getBankName();
980 const std::string &bankname,
981 const std::string &outputwsn) {
984 fltpk_alg->setProperty(
"InputWorkspace", pws);
985 fltpk_alg->setProperty(
"BankName", bankname);
986 fltpk_alg->setProperty(
"Criterion",
"=");
987 fltpk_alg->setProperty(
"OutputWorkspace", outputwsn);
988 fltpk_alg->executeAsChildAlg();
1002 int npeaks = pws->getNumberPeaks();
1010 auto &spectrum = mws->getSpectrum(0);
1011 auto &xvector = spectrum.mutableX();
1012 auto &yvector = spectrum.mutableY();
1013 auto &evector = spectrum.mutableE();
1016 double totalSigmaInt = 0.0;
1017 for (
int i = 0; i < npeaks; ++i) {
1018 totalSigmaInt += pws->getPeak(i).getSigmaIntensity();
1020 double totalInt = 0.0;
1021 for (
int i = 0; i < npeaks; ++i) {
1022 totalInt += pws->getPeak(i).getIntensity();
1024 double totalCnt = 0.0;
1025 for (
int i = 0; i < npeaks; ++i) {
1026 totalCnt += pws->getPeak(i).getBinCount();
1030 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1031 for (
int i = 0; i < npeaks; ++i) {
1033 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1037 if (totalSigmaInt > 0.0) {
1038 wgt = 1.0 / pws->getPeak(i).getSigmaIntensity();
1039 }
else if (totalInt > 0.0) {
1040 wgt = 1.0 / pws->getPeak(i).getIntensity();
1041 }
else if (totalCnt > 0.0) {
1042 wgt = 1.0 / pws->getPeak(i).getBinCount();
1045 for (
int j = 0; j < 3; ++j) {
1046 xvector[i * 3 + j] = i * 3 + j;
1047 yvector[i * 3 + j] = qv[j];
1048 evector[i * 3 + j] = wgt;
1070 double scalex,
double scaley,
const std::string &cmptName,
1076 mv_alg->setProperty(
"ComponentName", cmptName);
1077 mv_alg->setProperty(
"X", dx);
1078 mv_alg->setProperty(
"Y", dy);
1079 mv_alg->setProperty(
"Z", dz);
1080 mv_alg->setProperty(
"RelativePosition",
true);
1081 mv_alg->executeAsChildAlg();
1088 rot_alg->setProperty(
"ComponentName", cmptName);
1089 rot_alg->setProperty(
"X", 1.0);
1090 rot_alg->setProperty(
"Y", 0.0);
1091 rot_alg->setProperty(
"Z", 0.0);
1092 rot_alg->setProperty(
"Angle", drx);
1093 rot_alg->setProperty(
"RelativeRotation",
true);
1094 rot_alg->executeAsChildAlg();
1097 rot_alg->setProperty(
"ComponentName", cmptName);
1098 rot_alg->setProperty(
"X", 0.0);
1099 rot_alg->setProperty(
"Y", 1.0);
1100 rot_alg->setProperty(
"Z", 0.0);
1101 rot_alg->setProperty(
"Angle", dry);
1102 rot_alg->setProperty(
"RelativeRotation",
true);
1103 rot_alg->executeAsChildAlg();
1106 rot_alg->setProperty(
"ComponentName", cmptName);
1107 rot_alg->setProperty(
"X", 0.0);
1108 rot_alg->setProperty(
"Y", 0.0);
1109 rot_alg->setProperty(
"Z", 1.0);
1110 rot_alg->setProperty(
"Angle", drz);
1111 rot_alg->setProperty(
"RelativeRotation",
true);
1112 rot_alg->executeAsChildAlg();
1117 resizeAlg->initialize();
1118 resizeAlg->setProperty(
"Workspace", pws);
1119 resizeAlg->setProperty(
"ComponentName", cmptName);
1120 resizeAlg->setProperty(
"ScaleX",
scalex);
1121 resizeAlg->setProperty(
"ScaleY",
scaley);
1122 resizeAlg->execute();
1137 g_log.
notice() <<
"Generate a TableWorkspace to store calibration results.\n";
1146 V3D sourceRelPos = source->getRelativePos();
1150 sourceRow << instrument->getSource()->getName() << sourceRelPos.
X() << sourceRelPos.
Y() << sourceRelPos.
Z() << 1.0
1151 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0;
1157 if (instrument->getName().compare(
"CORELLI") == 0)
1158 bankName.append(
"/sixteenpack");
1160 std::shared_ptr<const IComponent> bank = instrument->getComponentByName(bankName);
1162 Quat relRot = bank->getRelativeRot();
1163 V3D pos1 = bank->getRelativePos();
1166 double deg, xAxis, yAxis, zAxis;
1175 bankRow << bankName << pos1.
X() << pos1.
Y() << pos1.
Z() << xAxis << yAxis << zAxis << deg << scales.first
1202 const boost::container::flat_set<std::string> &AllBankNames,
1206 using boost::property_tree::ptree;
1211 parafile.put(
"<xmlattr>.instrument", instrument->getName());
1212 parafile.put(
"<xmlattr>.valid-from", instrument->getValidFromDate().toISO8601String());
1216 ptree src_dx, src_dy, src_dz;
1217 ptree src_dx_val, src_dy_val, src_dz_val;
1220 V3D sourceRelPos = source->getRelativePos();
1222 src_dx_val.put(
"<xmlattr>.val", sourceRelPos.
X());
1223 src_dy_val.put(
"<xmlattr>.val", sourceRelPos.
Y());
1224 src_dz_val.put(
"<xmlattr>.val", sourceRelPos.
Z());
1225 src_dx.put(
"<xmlattr>.name",
"x");
1226 src_dy.put(
"<xmlattr>.name",
"y");
1227 src_dz.put(
"<xmlattr>.name",
"z");
1228 src.put(
"<xmlattr>.name", source->getName());
1230 src_dx.add_child(
"value", src_dx_val);
1231 src_dy.add_child(
"value", src_dy_val);
1232 src_dz.add_child(
"value", src_dz_val);
1233 src.add_child(
"parameter", src_dx);
1234 src.add_child(
"parameter", src_dy);
1235 src.add_child(
"parameter", src_dz);
1237 parafile.add_child(
"component-link", src);
1242 ptree property_root;
1243 property_root.put(
"<xmlattr>.name", instrument->getName());
1246 tof0.put(
"<xmlattr>.name",
"T0");
1247 tof0_val.put(
"<xmlattr>.val",
m_T0);
1248 tof0.add_child(
"value", tof0_val);
1249 property_root.add_child(
"parameter", tof0);
1250 parafile.add_child(
"component-link", property_root);
1254 ptree samplePos_dx, samplePos_dy, samplePos_dz;
1255 ptree samplePos_dx_val, samplePos_dy_val, samplePos_dz_val;
1257 std::shared_ptr<const IComponent> sp = instrument->getComponentByName(
"sample-position");
1258 V3D sppos = sp->getRelativePos();
1259 samplePos_dx_val.put(
"<xmlattr>.val", sppos.
X());
1260 samplePos_dy_val.put(
"<xmlattr>.val", sppos.
Y());
1261 samplePos_dz_val.put(
"<xmlattr>.val", sppos.
Z());
1262 samplePos_dx.put(
"<xmlattr>.name",
"x");
1263 samplePos_dy.put(
"<xmlattr>.name",
"y");
1264 samplePos_dz.put(
"<xmlattr>.name",
"z");
1265 samplePos.put(
"<xmlattr>.name",
"sample-position");
1267 samplePos_dx.add_child(
"value", samplePos_dx_val);
1268 samplePos_dy.add_child(
"value", samplePos_dy_val);
1269 samplePos_dz.add_child(
"value", samplePos_dz_val);
1270 samplePos.add_child(
"parameter", samplePos_dx);
1271 samplePos.add_child(
"parameter", samplePos_dy);
1272 samplePos.add_child(
"parameter", samplePos_dz);
1274 parafile.add_child(
"component-link", samplePos);
1277 for (
auto bankName : AllBankNames) {
1279 if (instrument->getName().compare(
"CORELLI") == 0)
1280 bankName.append(
"/sixteenpack");
1282 std::shared_ptr<const IComponent> bank = instrument->getComponentByName(bankName);
1283 auto bankFullName = bank->getFullName();
1285 Quat relRot = bank->getRelativeRot();
1287 V3D pos1 = bank->getRelativePos();
1292 ptree bank_dx, bank_dy, bank_dz;
1293 ptree bank_dx_val, bank_dy_val, bank_dz_val;
1294 ptree bank_drotx, bank_droty, bank_drotz;
1295 ptree bank_drotx_val, bank_droty_val, bank_drotz_val;
1296 ptree bank_sx, bank_sy;
1297 ptree bank_sx_val, bank_sy_val;
1300 bank_dx_val.put(
"<xmlattr>.val", pos1.
X());
1301 bank_dy_val.put(
"<xmlattr>.val", pos1.
Y());
1302 bank_dz_val.put(
"<xmlattr>.val", pos1.
Z());
1303 bank_dx.put(
"<xmlattr>.name",
"x");
1304 bank_dy.put(
"<xmlattr>.name",
"y");
1305 bank_dz.put(
"<xmlattr>.name",
"z");
1307 bank_drotx_val.put(
"<xmlattr>.val", relRotAngles[0]);
1308 bank_droty_val.put(
"<xmlattr>.val", relRotAngles[1]);
1309 bank_drotz_val.put(
"<xmlattr>.val", relRotAngles[2]);
1310 bank_drotx.put(
"<xmlattr>.name",
"rotx");
1311 bank_droty.put(
"<xmlattr>.name",
"roty");
1312 bank_drotz.put(
"<xmlattr>.name",
"rotz");
1314 bank_sx_val.put(
"<xmlattr>.val", scales.first);
1315 bank_sy_val.put(
"<xmlattr>.val", scales.second);
1316 bank_sx.put(
"<xmlattr>.name",
"scalex");
1317 bank_sy.put(
"<xmlattr>.name",
"scaley");
1319 bank_root.put(
"<xmlattr>.name", bankFullName);
1322 bank_dx.add_child(
"value", bank_dx_val);
1323 bank_dy.add_child(
"value", bank_dy_val);
1324 bank_dz.add_child(
"value", bank_dz_val);
1326 bank_drotx.add_child(
"value", bank_drotx_val);
1327 bank_droty.add_child(
"value", bank_droty_val);
1328 bank_drotz.add_child(
"value", bank_drotz_val);
1330 bank_sx.add_child(
"value", bank_sx_val);
1331 bank_sy.add_child(
"value", bank_sy_val);
1333 bank_root.add_child(
"parameter", bank_drotx);
1335 bank_root.add_child(
"parameter", bank_droty);
1336 bank_root.add_child(
"parameter", bank_drotz);
1337 bank_root.add_child(
"parameter", bank_dx);
1338 bank_root.add_child(
"parameter", bank_dy);
1339 bank_root.add_child(
"parameter", bank_dz);
1340 bank_root.add_child(
"parameter", bank_sx);
1341 bank_root.add_child(
"parameter", bank_sy);
1343 parafile.add_child(
"component-link", bank_root);
1347 root.add_child(
"parameter-file", parafile);
1349 g_log.
notice() <<
"\tSaving parameter file as " << FileName <<
"\n";
1350 boost::property_tree::write_xml(FileName, root, std::locale(),
1351 boost::property_tree::xml_writer_settings<std::string>(
' ', 2));
1365 boost::container::flat_set<std::string> &AllBankName,
1366 std::shared_ptr<Instrument> &instrument,
double T0) {
1367 g_log.
notice() <<
"Saving DetCal file in " << filename <<
"\n";
1369 bool tuneSamplePos =
getProperty(
"TuneSamplePosition");
1370 if (tuneSamplePos) {
1372 <<
"DetCal format cannot retain sample position info, therefore the calibrated "
1373 <<
"sample position will be lost if DetCal format is the only output!\n";
1377 const size_t number_spectra = instrument->getNumberDetectors();
1380 wksp->setInstrument(instrument);
1381 wksp->rebuildSpectraMapping(
true );
1384 std::vector<std::string> banknames(AllBankName.begin(), AllBankName.end());
1388 alg->setProperty(
"InputWorkspace", wksp);
1389 alg->setProperty(
"Filename", filename);
1390 alg->setProperty(
"TimeOffset", T0);
1391 alg->setProperty(
"BankNames", banknames);
1392 alg->executeAsChildAlg();
1404 alg->setProperty(
"InputWorkspace", tws);
1405 alg->setProperty(
"Filename", FileName);
1406 alg->setPropertyValue(
"CommentIndicator",
"#");
1407 alg->setPropertyValue(
"Separator",
"CSV");
1408 alg->setProperty(
"ColumnHeader",
true);
1409 alg->setProperty(
"AppendToFile",
false);
1410 alg->executeAsChildAlg();
1421 g_log.
notice() <<
"START of profiling objective func along L1\n";
1431 std::ostringstream msgrst;
1432 msgrst.precision(12);
1433 msgrst <<
"dL1\tresidual\n";
1436 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1438 std::vector<double> tofs =
captureTOF(pws_original);
1439 objf->setPeakWorkspace(pws,
"moderator", tofs,
m_waveFromUB);
1442 const int n_peaks = pws->getNumberPeaks();
1443 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1446 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1447 for (
int i = 0; i < n_peaks; ++i) {
1448 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1450 for (
int j = 0; j < 3; ++j) {
1451 target[i * 3 + j] = qv[j];
1455 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1459 double deltaL1 = -4e-2;
1460 while (deltaL1 < 4e-2) {
1461 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1462 objf->setParameter(
"DeltaZ", deltaL1);
1463 objf->setParameter(
"DeltaT0", 0.0);
1464 objf->function1D(out.get(), xValues, 1);
1467 double residual = 0.0;
1468 for (
int i = 0; i < n_peaks * 3; ++i) {
1469 residual += (out[i] - target[i]) * (out[i] - target[i]);
1471 residual = std::sqrt(residual) / (n_peaks - 1);
1473 msgrst << deltaL1 <<
"\t" << residual <<
"\n";
1476 g_log.
notice() << deltaL1 <<
" -- " << residual <<
"\n";
1484 auto filenamebase = std::filesystem::temp_directory_path() /
"profileSCDCalibratePanels2_L1.csv";
1485 std::ofstream profL1File;
1486 profL1File.open(filenamebase.string());
1487 profL1File << msgrst.str();
1490 << filenamebase <<
"\n"
1491 <<
"END of profiling objective func along L1\n";
1502 g_log.
notice() <<
"START of profiling all banks along six degree of freedom\n";
1512 for (
int bankIndex = 0; bankIndex < static_cast<int>(
m_BankNames.size()); ++bankIndex) {
1515 const std::string bankname = *std::next(
m_BankNames.begin(), bankIndex);
1516 const std::string pwsBankiName =
"_pws_" + bankname;
1522 std::vector<double> tofs =
captureTOF(pwsBanki_original);
1526 int nBankPeaks = pwsBanki->getNumberPeaks();
1529 std::ostringstream msg_npeakCheckFail;
1530 msg_npeakCheckFail <<
"-- Cannot profile Bank " << bankname <<
" have only " << nBankPeaks <<
" (<"
1538 std::ostringstream msgrst;
1539 msgrst.precision(12);
1540 msgrst <<
"dx\tdy\tdz\ttheta\tphi\trogang\tresidual\n";
1542 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1543 objf->setPeakWorkspace(pwsBanki, bankname, tofs,
m_waveFromUB);
1545 const int n_peaks = pwsBanki->getNumberPeaks();
1546 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1548 auto ubmatrix = pwsBanki->sample().getOrientedLattice().getUB();
1549 for (
int i = 0; i < n_peaks; ++i) {
1550 V3D qv = ubmatrix * pwsBanki->getPeak(i).getIntHKL();
1552 for (
int j = 0; j < 3; ++j) {
1553 target[i * 3 + j] = qv[j];
1557 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1560 for (
double dx = -1e-2; dx < 1e-2; dx += 2e-2 / 20.0) {
1562 for (
double dy = -1e-2; dy < 1e-2; dy += 2e-2 / 20.0) {
1564 for (
double dz = -1e-2; dz < 1e-2; dz += 2e-2 / 20.0) {
1566 for (
double theta = 0.0; theta <
PI; theta +=
PI / 20.0) {
1568 for (
double phi = 0.0; phi < 2 *
PI; phi += 2 *
PI / 20.0) {
1570 for (
double ang = -5.0; ang < 5.0; ang += 5.0 / 20.0) {
1573 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1574 objf->setParameter(
"DeltaX", dx);
1575 objf->setParameter(
"DeltaY", dy);
1576 objf->setParameter(
"DeltaZ", dz);
1577 objf->setParameter(
"Theta", theta);
1578 objf->setParameter(
"Phi", phi);
1579 objf->setParameter(
"DeltaRotationAngle", ang);
1580 objf->setParameter(
"DeltaT0", 0.0);
1581 objf->function1D(out.get(), xValues, 1);
1583 double residual = 0.0;
1584 for (
int i = 0; i < n_peaks * 3; ++i) {
1585 residual += (out[i] - target[i]) * (out[i] - target[i]);
1587 residual = std::sqrt(residual) / (n_peaks - 6);
1589 msgrst << dx <<
"\t" << dy <<
"\t" << dz <<
"\t" << theta <<
"\t" << phi <<
"\t" << ang <<
"\t"
1590 << residual <<
"\n";
1593 g_log.
notice() <<
"--" << bankname <<
": " << residual <<
"\n";
1603 const std::string csvname =
"profileSCDCalibratePanels2_" + bankname +
".csv";
1604 auto filenamebase = std::filesystem::temp_directory_path() / csvname;
1605 std::ofstream profBankFile;
1606 profBankFile.open(filenamebase.string());
1607 profBankFile << msgrst.str();
1608 profBankFile.close();
1611 std::ostringstream msg;
1612 msg <<
"Profile of " << bankname <<
" is saved at:\n"
1613 << filenamebase <<
"\n"
1614 <<
"END of profiling objective func for " << bankname <<
"\n";
1629 g_log.
notice() <<
"START of profiling objective func along T0\n";
1639 std::ostringstream msgrst;
1640 msgrst.precision(12);
1641 msgrst <<
"dT0\tresidual\n";
1644 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1646 std::vector<double> tofs =
captureTOF(pws_original);
1647 objf->setPeakWorkspace(pws,
"none", tofs,
m_waveFromUB);
1650 const int n_peaks = pws->getNumberPeaks();
1651 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1652 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1653 for (
int i = 0; i < n_peaks; ++i) {
1654 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1656 for (
int j = 0; j < 3; ++j) {
1657 target[i * 3 + j] = qv[j];
1661 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1664 double deltaT0 = -10;
1665 while (deltaT0 < 10) {
1666 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1667 objf->setParameter(
"DeltaT0", deltaT0);
1668 objf->function1D(out.get(), xValues, 1);
1671 double residual = 0.0;
1672 for (
int i = 0; i < n_peaks * 3; ++i) {
1673 residual += (out[i] - target[i]) * (out[i] - target[i]);
1675 residual = std::sqrt(residual) / (n_peaks - 1);
1677 msgrst << deltaT0 <<
"\t" << residual <<
"\n";
1680 g_log.
notice() << deltaT0 <<
" -- " << residual <<
"\n";
1688 auto filenamebase = std::filesystem::temp_directory_path() /
"profileSCDCalibratePanels2_T0.csv";
1689 std::ofstream profL1File;
1690 profL1File.open(filenamebase.string());
1691 profL1File << msgrst.str();
1694 << filenamebase <<
"\n"
1695 <<
"END of profiling objective func along T0\n";
1706 g_log.
notice() <<
"START of profiling objective func along L1 and T0\n";
1712 g_log.
notice() <<
"deltaL1 -- deltaT0 -- residual\n";
1716 std::ostringstream msgrst;
1717 msgrst.precision(12);
1718 msgrst <<
"dL1\tdT0\tresidual\n";
1721 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1723 std::vector<double> tofs =
captureTOF(pws_original);
1724 objf->setPeakWorkspace(pws,
"moderator", tofs,
m_waveFromUB);
1727 const int n_peaks = pws->getNumberPeaks();
1728 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1729 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1730 for (
int i = 0; i < n_peaks; ++i) {
1731 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1733 for (
int j = 0; j < 3; ++j) {
1734 target[i * 3 + j] = qv[j];
1738 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1741 for (
double deltaL1 = -4e-2; deltaL1 < 4e-2; deltaL1 += 1e-4) {
1742 for (
double deltaT0 = -4.0; deltaT0 < 4.0; deltaT0 += 1e-2) {
1743 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1744 objf->setParameter(
"DeltaZ", deltaL1);
1745 objf->setParameter(
"DeltaT0", deltaT0);
1746 objf->function1D(out.get(), xValues, 1);
1749 double residual = 0.0;
1750 for (
int i = 0; i < n_peaks * 3; ++i) {
1751 residual += (out[i] - target[i]) * (out[i] - target[i]);
1753 residual = std::sqrt(residual) / (n_peaks - 2);
1756 g_log.
notice() << deltaL1 <<
" -- " << deltaT0 <<
" -- " << residual <<
"\n";
1759 msgrst << deltaL1 <<
"\t" << deltaT0 <<
"\t" << residual <<
"\n";
1764 auto filenamebase = std::filesystem::temp_directory_path() /
"profileSCDCalibratePanels2_L1T0.csv";
1765 std::ofstream profL1File;
1766 profL1File.open(filenamebase.string());
1767 profL1File << msgrst.str();
1772 << filenamebase <<
"\n"
1773 <<
"END of profiling objective func along L1 and T0\n";
1788std::pair<double, double>
1790 const std::string &bankname,
1793 std::pair<double, double> scales{1.0, 1.0};
1797 std::shared_ptr<const Geometry::RectangularDetector> rectDet =
1798 std::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp);
1802 auto scalexparams =
pmap.getDouble(rectDet->getName(),
"scalex");
1803 auto scaleyparams =
pmap.getDouble(rectDet->getName(),
"scaley");
1804 if (!scalexparams.empty())
1805 scales.first = scalexparams[0];
1806 if (!scaleyparams.empty())
1807 scales.second = scaleyparams[0];
#define DECLARE_ALGORITHM(classname)
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
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.
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.
@ OptionalSave
to specify a file to write to but an empty string is
TableRow represents a row in a TableWorkspace.
A property class for workspaces.
SCDCalibratePanels2 : Using input peakworkspace with indexation results to calibrate each individual ...
Mantid::API::IPeaksWorkspace_sptr removeUnindexedPeaks(const Mantid::API::IPeaksWorkspace_sptr &pws)
Remove unindexed peaks from workspace.
void adjustComponent(double dx, double dy, double dz, double drx, double dry, double drz, double scalex, double scaley, const std::string &cmptName, Mantid::API::IPeaksWorkspace_sptr &pws)
Helper functions for adjusting components.
void saveIsawDetCal(const std::string &filename, boost::container::flat_set< std::string > &AllBankName, std::shared_ptr< Geometry::Instrument > &instrument, double T0)
Save to ISAW type det calibration output for backward compatiblity.
Mantid::API::ITableWorkspace_sptr generateCalibrationTable(std::shared_ptr< Geometry::Instrument > &instrument, const Geometry::ParameterMap &pmap)
Generate a Table workspace to store the calibration results.
void profileBanks(Mantid::API::IPeaksWorkspace_sptr const &pws, const Mantid::API::IPeaksWorkspace_sptr &pws_original)
Profiling obj func along six degree of freedom, which can be very slow.
void optimizeT0(Mantid::API::IPeaksWorkspace_sptr pws, Mantid::API::IPeaksWorkspace_sptr pws_original)
Private function for calibrating T0.
void optimizeL1(Mantid::API::IPeaksWorkspace_sptr pws, Mantid::API::IPeaksWorkspace_sptr pws_original)
Private function for calibrating L1.
double m_a
unique vars for a given instance of calibration
void optimizeSamplePos(Mantid::API::IPeaksWorkspace_sptr pws, Mantid::API::IPeaksWorkspace_sptr pws_original)
Private function for fine tunning sample position.
const std::vector< std::string > calibrationTableColumnTypes
void getBankNames(const Mantid::API::IPeaksWorkspace_sptr &pws)
Private function for getting names of banks to be calibrated.
boost::container::flat_set< std::string > m_BankNames
const int MINIMUM_PEAKS_PER_BANK
static constexpr double Tolerance
void updateUBMatrix(const Mantid::API::IPeaksWorkspace_sptr &pws)
Update the UB matrix.
void optimizeBanks(Mantid::API::IPeaksWorkspace_sptr pws, const Mantid::API::IPeaksWorkspace_sptr &pws_original, const bool &docalibsize, const double &sizesearchradius, const bool &fixdetxyratio)
Private function for calibrating banks.
void parseLatticeConstant(const Mantid::API::IPeaksWorkspace_sptr &pws)
Private function dedicated for parsing lattice constant.
const std::vector< std::string > calibrationTableColumnNames
void saveXmlFile(const std::string &FileName, const boost::container::flat_set< std::string > &AllBankNames, std::shared_ptr< Geometry::Instrument > &instrument, const Geometry::ParameterMap &pmap)
Save to xml file for Mantid to load by manual crafting.
void exec() override
Overwrites Algorithm method.
void profileT0(Mantid::API::IPeaksWorkspace_sptr &pws, Mantid::API::IPeaksWorkspace_sptr pws_original)
Profile obj func along T0 axis.
Mantid::API::IPeaksWorkspace_sptr selectPeaksByBankName(const Mantid::API::IPeaksWorkspace_sptr &pws, const std::string &bankname, const std::string &outputwsn)
Helper function for selecting peaks based on given bank name.
std::map< std::string, std::string > validateInputs() override
Private validator for inputs.
std::pair< double, double > getRectangularDetectorScaleFactors(std::shared_ptr< Geometry::Instrument > &instrument, const std::string &bankname, const Geometry::ParameterMap &pmap)
Retrieve "scalex" and "scaley" from a workspace's parameter map if the component is rectangular detec...
std::string mCalibBankName
bool m_waveFromUB
if true, wavelength is derived from Bragg's law using the UB matrix instead of from the measured TOF;...
void saveCalibrationTable(const std::string &FileName, Mantid::API::ITableWorkspace_sptr const &tws)
Save the calibration table to a CSV file.
Mantid::API::MatrixWorkspace_sptr getIdealQSampleAsHistogram1D(const Mantid::API::IPeaksWorkspace_sptr &pws)
Helper function that calculates the ideal qSample based on integer HKL.
void profileL1(Mantid::API::IPeaksWorkspace_sptr &pws, Mantid::API::IPeaksWorkspace_sptr pws_original)
Profile related functions.
void profileL1T0(Mantid::API::IPeaksWorkspace_sptr &pws, Mantid::API::IPeaksWorkspace_sptr pws_original)
Profile obj func along L1 and T0 axis.
std::vector< double > captureTOF(const Mantid::API::IPeaksWorkspace_sptr &pws)
Cache TOF equivalent to those measured from experiment.
Class to implement UB matrix.
double alpha() const
Get lattice parameter.
double a(int nd) const
Get lattice parameter a1-a3 as function of index (0-2)
double c() const
Get lattice parameter.
double beta() const
Get lattice parameter.
double b() const
Get lattice parameter.
double gamma() const
Get lattice parameter.
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
The Logger class is in charge of the publishing messages from the framework through various channels.
void notice(const std::string &msg)
Logs at notice level.
void warning(const std::string &msg)
Logs at warning level.
void information(const std::string &msg)
Logs at information level.
void getAngleAxis(double &_deg, double &_ax0, double &_ax1, double &ax2) const
Extracts the angle of roatation and axis.
std::vector< double > getEulerAngles(const std::string &convention) const
Calculate the Euler angles that are equivalent to this Quaternion.
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
constexpr double X() const noexcept
Get x.
constexpr double Y() const noexcept
Get y.
constexpr double Z() const noexcept
Get z.
std::shared_ptr< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
std::unique_ptr< T > create(const P &parent, const IndexArg &indexArg, const HistArg &histArg)
This is the create() method that all the other create() methods call.
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.
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Generate a tableworkspace to store the calibration results.
adjust instrument component position and orientation
: detector size scale at y-direction
@ Input
An input workspace.
@ Output
An output workspace.