28#include <boost/container/flat_set.hpp>
29#include <boost/property_tree/ptree.hpp>
30#include <boost/property_tree/xml_parser.hpp>
32#include <boost/math/special_functions/round.hpp>
49Logger logger(
"SCDCalibratePanels2");
61 "Workspace of Indexed Peaks");
64 auto mustBeNonNegative = std::make_shared<BoundedValidator<double>>();
65 mustBeNonNegative->setLower(0.0);
66 declareProperty(
"RecalculateUB",
true,
"Recalculate UB matrix using given lattice constants");
67 declareProperty(
"a",
EMPTY_DBL(), mustBeNonNegative,
68 "Lattice Parameter a (Leave empty to use lattice constants "
69 "in peaks workspace)");
70 declareProperty(
"b",
EMPTY_DBL(), mustBeNonNegative,
71 "Lattice Parameter b (Leave empty to use lattice constants "
72 "in peaks workspace)");
73 declareProperty(
"c",
EMPTY_DBL(), mustBeNonNegative,
74 "Lattice Parameter c (Leave empty to use lattice constants "
75 "in peaks workspace)");
76 declareProperty(
"alpha",
EMPTY_DBL(), mustBeNonNegative,
77 "Lattice Parameter alpha in degrees (Leave empty to use "
78 "lattice constants in peaks workspace)");
79 declareProperty(
"beta",
EMPTY_DBL(), mustBeNonNegative,
80 "Lattice Parameter beta in degrees (Leave empty to use "
81 "lattice constants in peaks workspace)");
82 declareProperty(
"gamma",
EMPTY_DBL(), mustBeNonNegative,
83 "Lattice Parameter gamma in degrees (Leave empty to use "
84 "lattice constants in peaks workspace)");
85 const std::string LATTICE(
"Lattice Constants");
86 setPropertyGroup(
"RecalculateUB", LATTICE);
87 setPropertyGroup(
"a", LATTICE);
88 setPropertyGroup(
"b", LATTICE);
89 setPropertyGroup(
"c", LATTICE);
90 setPropertyGroup(
"alpha", LATTICE);
91 setPropertyGroup(
"beta", LATTICE);
92 setPropertyGroup(
"gamma", LATTICE);
93 setPropertySettings(
"a", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
94 setPropertySettings(
"b", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
95 setPropertySettings(
"c", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
96 setPropertySettings(
"alpha", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
97 setPropertySettings(
"beta", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
98 setPropertySettings(
"gamma", std::make_unique<EnabledWhenProperty>(
"RecalculateUB",
IS_DEFAULT));
100 declareProperty(
"Tolerance", 0.15, mustBeNonNegative,
"Peak indexing tolerance");
102 declareProperty(
"WavelengthFromUB",
false,
103 "If True, compute each peak's wavelength from Bragg's law using the UB matrix and its "
104 "assigned integer HKL, instead of from the measured TOF. Intended for quasi-Laue workflows, "
105 "where a peak's TOF-derived wavelength can be unreliable, but works for standard "
106 "time-of-flight Laue data as well. NOTE: when enabled, CalibrateT0 has no effect, since "
107 "wavelength no longer depends on TOF.");
117 const std::string CALIBRATION(
"Calibration Options");
121 declareProperty(
"CalibrateL1",
true,
"Change the L1(source to sample) distance");
122 declareProperty(
"SearchRadiusL1", 0.1, mustBeNonNegative,
123 "Search radius of delta L1 in meters, which is used to constrain optimization search space"
124 "when calibrating L1");
126 setPropertySettings(
"SearchRadiusL1", std::make_unique<EnabledWhenProperty>(
"CalibrateL1",
IS_EQUAL_TO,
"1"));
128 setPropertyGroup(
"CalibrateL1", CALIBRATION);
129 setPropertyGroup(
"SearchRadiusL1", CALIBRATION);
133 declareProperty(
"CalibrateBanks",
false,
"Calibrate position and orientation of each bank.");
135 "SearchRadiusTransBank", 5e-2, mustBeNonNegative,
136 "This is the search radius (in meter) when calibrating component translations, used to constrain optimization"
137 "search space when calibration translation of banks");
138 declareProperty(
"SearchradiusRotXBank", 1.0, mustBeNonNegative,
139 "This is the search radius (in deg) when calibrating component reorientation, used to constrain "
140 "optimization search space");
141 declareProperty(
"SearchradiusRotYBank", 1.0, mustBeNonNegative,
142 "This is the search radius (in deg) when calibrating component reorientation, used to constrain "
143 "optimization search space");
144 declareProperty(
"SearchradiusRotZBank", 1.0, mustBeNonNegative,
145 "This is the search radius (in deg) when calibrating component reorientation, used to constrain "
146 "optimization search space");
147 declareProperty(
"CalibrateSize",
false,
"Calibrate detector size for each bank.");
148 declareProperty(
"SearchRadiusSize", 0.0, mustBeNonNegative,
149 "This is the search radius (unit less) of scale factor around at value 1.0 "
150 "when calibrating component size if it is a rectangualr detector.");
151 declareProperty(
"FixAspectRatio",
true,
152 "If true, the scaling factor for detector along X- and Y-axis "
153 "must be the same. Otherwise, the 2 scaling factors are free.");
154 declareProperty(
"BankName",
"",
155 "If given, only the specified bank/component will be calibrated."
156 "Otherwise, all banks will be calibrated.");
159 setPropertySettings(
"BankName", std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
160 setPropertySettings(
"SearchRadiusTransBank",
161 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
162 setPropertySettings(
"SearchradiusRotXBank",
163 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
164 setPropertySettings(
"SearchradiusRotYBank",
165 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
166 setPropertySettings(
"SearchradiusRotZBank",
167 std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
168 setPropertySettings(
"CalibrateSize", std::make_unique<EnabledWhenProperty>(
"CalibrateBanks",
IS_EQUAL_TO,
"1"));
169 setPropertySettings(
"SearchRadiusSize", std::make_unique<EnabledWhenProperty>(
"CalibrateSize",
IS_EQUAL_TO,
"1"));
170 setPropertySettings(
"FixAspectRatio", std::make_unique<EnabledWhenProperty>(
"CalibrateSize",
IS_EQUAL_TO,
"1"));
172 setPropertyGroup(
"CalibrateBanks", CALIBRATION);
173 setPropertyGroup(
"BankName", CALIBRATION);
174 setPropertyGroup(
"SearchRadiusTransBank", CALIBRATION);
175 setPropertyGroup(
"SearchradiusRotXBank", CALIBRATION);
176 setPropertyGroup(
"SearchradiusRotYBank", CALIBRATION);
177 setPropertyGroup(
"SearchradiusRotZBank", CALIBRATION);
178 setPropertyGroup(
"CalibrateSize", CALIBRATION);
179 setPropertyGroup(
"SearchRadiusSize", CALIBRATION);
180 setPropertyGroup(
"FixAspectRatio", CALIBRATION);
185 declareProperty(
"CalibrateT0",
false,
"Calibrate the T0 (initial TOF)");
186 declareProperty(
"SearchRadiusT0", 10.0, mustBeNonNegative,
187 "Search radius of T0 (in ms), used to constrain optimization search space");
189 setPropertySettings(
"SearchRadiusT0", std::make_unique<EnabledWhenProperty>(
"CalibrateT0",
IS_EQUAL_TO,
"1"));
191 setPropertyGroup(
"CalibrateT0", CALIBRATION);
192 setPropertyGroup(
"SearchRadiusT0", CALIBRATION);
196 declareProperty(
"TuneSamplePosition",
false,
"Fine tunning sample position");
197 declareProperty(
"SearchRadiusSamplePos", 0.1, mustBeNonNegative,
198 "Search radius of sample position change (in meters), used to constrain optimization search space");
200 setPropertySettings(
"SearchRadiusSamplePos",
201 std::make_unique<EnabledWhenProperty>(
"TuneSamplePosition",
IS_EQUAL_TO,
"1"));
203 setPropertyGroup(
"TuneSamplePosition", CALIBRATION);
204 setPropertyGroup(
"SearchRadiusSamplePos", CALIBRATION);
208 "The workspace containing the calibration table.");
210 const std::vector<std::string> detcalExts{
".DetCal",
".Det_Cal"};
213 "Path to an ISAW-style .detcal file to save.");
216 "Path to an Mantid .xml description(for LoadParameterFile) file to "
220 "Path to an .csv file which contains the Calibration Table");
222 const std::string OUTPUT(
"Output");
223 setPropertyGroup(
"OutputWorkspace", OUTPUT);
224 setPropertyGroup(
"DetCalFilename", OUTPUT);
225 setPropertyGroup(
"XmlFilename", OUTPUT);
226 setPropertyGroup(
"CSVFilename", OUTPUT);
230 declareProperty(
"VerboseOutput",
false,
"Toggle of child algorithm console output.");
231 declareProperty(
"ProfileL1",
false,
"Perform profiling of objective function with given input for L1");
232 declareProperty(
"ProfileBanks",
false,
"Perform profiling of objective function with given input for Banks");
233 declareProperty(
"ProfileT0",
false,
"Perform profiling of objective function with given input for T0");
234 declareProperty(
"ProfileL1T0",
false,
"Perform profiling of objective function along L1 and T0");
236 const std::string ADVCNTRL(
"Advanced Option");
237 setPropertyGroup(
"VerboseOutput", ADVCNTRL);
238 setPropertyGroup(
"ProfileL1", ADVCNTRL);
239 setPropertyGroup(
"ProfileBanks", ADVCNTRL);
240 setPropertyGroup(
"ProfileT0", ADVCNTRL);
241 setPropertyGroup(
"ProfileL1T0", ADVCNTRL);
244 auto mustBePositive = std::make_shared<Kernel::BoundedValidator<int>>();
245 mustBePositive->setLower(0);
246 declareProperty(
"MaxFitIterations", 500, mustBePositive,
247 "Stop after this number of iterations if a good fit is not found");
256 std::map<std::string, std::string> issues;
269 (!pws->sample().hasOrientedLattice())) {
270 issues[
"RecalculateUB"] =
"Lattice constants are needed for peak "
271 "workspace without a UB mattrix";
279 issues[
"CalibrateT0"] =
"CalibrateT0 has no effect when WavelengthFromUB is enabled, since wavelength no "
280 "longer depends on TOF.";
285 throw std::runtime_error(
"calibrationTableColumnTypes and calibrationTableColumnTypes have different size.");
313 bool calibrateBanks =
getProperty(
"CalibrateBanks");
314 bool tuneSamplePos =
getProperty(
"TuneSamplePosition");
321 const std::string DetCalFilename =
getProperty(
"DetCalFilename");
322 const std::string XmlFilename =
getProperty(
"XmlFilename");
323 const std::string CSVFilename =
getProperty(
"CSVFilename");
327 double sizesearchradius =
getProperty(
"SearchRadiusSize");
328 bool fixdetxyratio =
getProperty(
"FixAspectRatio");
334 std::vector<std::pair<std::string, bool>> criteria{{
"BankName",
true}};
335 m_pws->sort(criteria);
367 g_log.
notice() <<
"** Calibrating L1 (moderator) as requested\n";
371 if (calibrateBanks) {
372 g_log.
notice() <<
"** Calibrating L2 and orientation (bank) as requested\n";
373 optimizeBanks(m_pws, pws_original, docalibsize, sizesearchradius, fixdetxyratio);
376 if (calibrateL1 && calibrateBanks) {
377 g_log.
notice() <<
"** Calibrating L1 (moderator) after bank adjusted\n";
395 if (calibrateT0 && !calibrateL1) {
400 g_log.
notice() <<
"** Calibrating T0 only as requested\n";
404 if (tuneSamplePos && !calibrateL1) {
405 g_log.
notice() <<
"** Tunning sample position only as requested\n";
409 if (calibrateT0 && tuneSamplePos && !calibrateL1) {
410 g_log.
warning() <<
"** You have chosen to calibrate T0 and sample position while ignoring"
411 <<
" L1, which means an iterative search outside this calibration is needed"
412 <<
" in order to find the minimum.\n";
416 g_log.
notice() <<
"-- Generate calibration table\n";
417 Instrument_sptr instCalibrated = std::const_pointer_cast<Geometry::Instrument>(m_pws->getInstrument());
422 if (!XmlFilename.empty()) {
426 if (!DetCalFilename.empty()) {
430 if (!CSVFilename.empty()) {
450 double original_L1 = std::abs(pws->getInstrument()->getSource()->getPos().Z());
453 bool tuneSamplepos =
getProperty(
"TuneSamplePosition");
459 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
461 std::vector<double> tofs =
captureTOF(pws_original);
462 objf->setPeakWorkspace(pws,
"moderator", tofs,
m_waveFromUB);
463 fitL1_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
466 std::ostringstream tie_str;
467 tie_str <<
"DeltaX=0.0,DeltaY=0.0,"
468 <<
"RotX=0.0,RotY=0.0,RotZ=0.0";
469 if (!tuneSamplepos) {
470 tie_str <<
",DeltaSampleX=0.0,DeltaSampleY=0.0,DeltaSampleZ=0.0";
473 tie_str <<
",DeltaT0=" <<
m_T0;
475 std::ostringstream constraint_str;
477 r_L1 = std::abs(r_L1);
478 constraint_str << -r_L1 <<
"<DeltaZ<" << r_L1;
482 r_dT0 = std::abs(r_dT0);
483 constraint_str <<
"," << -r_dT0 <<
"<DeltaT0<" << r_dT0;
486 double r_dsp =
getProperty(
"SearchRadiusSamplePos");
487 r_dsp = std::abs(r_dsp);
488 constraint_str <<
"," << -r_dsp <<
"<DeltaSampleX<" << r_dsp
489 <<
"," << -r_dsp <<
"<DeltaSampleY<" << r_dsp
490 <<
"," << -r_dsp <<
"<DeltaSampleZ<" << r_dsp;
493 fitL1_alg->setProperty(
"Ties", tie_str.str());
494 fitL1_alg->setProperty(
"Constraints", constraint_str.str());
495 fitL1_alg->setProperty(
"InputWorkspace", l1ws);
496 fitL1_alg->setProperty(
"CreateOutput",
true);
497 fitL1_alg->setProperty(
"Output",
"fit");
498 fitL1_alg->executeAsChildAlg();
501 std::ostringstream calilog;
502 double chi2OverDOF = fitL1_alg->getProperty(
"OutputChi2overDoF");
505 double dL1_optimized = rst->getRef<
double>(
"Value", 2);
508 double dT0_optimized = rst->getRef<
double>(
"Value", 6);
514 double dsx_optimized = rst->getRef<
double>(
"Value", 7);
515 double dsy_optimized = rst->getRef<
double>(
"Value", 8);
516 double dsz_optimized = rst->getRef<
double>(
"Value", 9);
520 pws->getInstrument()->getSource()->getName(), pws);
521 m_T0 = dT0_optimized;
523 "sample-position", pws);
525 int npks = pws->getNumberPeaks();
526 calilog <<
"-- Fit L1 results using " << npks <<
" peaks:\n"
527 <<
" dL1: " << dL1_optimized <<
" \n"
528 <<
" L1 " << original_L1 <<
" -> " << -pws->getInstrument()->getSource()->getPos().Z() <<
" \n"
529 <<
" dT0 = " <<
m_T0 <<
" (ms)\n"
530 <<
" dSamplePos = (" << dsx_optimized <<
"," << dsy_optimized <<
"," << dsz_optimized <<
")\n"
531 <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
545 const bool &docalibsize,
const double &sizesearchradius,
546 const bool &fixdetxyratio) {
548 for (
int i = 0; i < static_cast<int>(
m_BankNames.size()); ++i) {
551 const std::string bankname = *std::next(
m_BankNames.begin(), i);
552 const std::string pwsBankiName =
"_pws_" + bankname;
558 std::stringstream ss;
559 ss <<
"i = " << i <<
" m bank name = " << bankname;
561 ss <<
" ... True ...";
563 ss <<
" ... Stop ...";
574 std::vector<double> tofs =
captureTOF(pwsBanki_original);
578 int nBankPeaks = pwsBanki->getNumberPeaks();
581 std::ostringstream msg_npeakCheckFail;
582 msg_npeakCheckFail <<
"-- Bank " << bankname <<
" have only " << nBankPeaks <<
" (<" <<
MINIMUM_PEAKS_PER_BANK
583 <<
") Peaks, skipping\n";
594 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
595 objf->setPeakWorkspace(pwsBanki, bankname, tofs,
m_waveFromUB);
596 fitBank_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
600 double searchRadiusRotX =
getProperty(
"SearchradiusRotXBank");
601 searchRadiusRotX = std::abs(searchRadiusRotX);
602 double searchRadiusRotY =
getProperty(
"SearchradiusRotYBank");
603 searchRadiusRotY = std::abs(searchRadiusRotY);
604 double searchRadiusRotZ =
getProperty(
"SearchradiusRotZBank");
605 searchRadiusRotZ = std::abs(searchRadiusRotZ);
607 double searchRadiusTran =
getProperty(
"SearchRadiusTransBank");
608 searchRadiusTran = std::abs(searchRadiusTran);
610 std::ostringstream tie_str;
611 tie_str <<
"DeltaSampleX=0.0,DeltaSampleY=0.0,DeltaSampleZ=0.0,"
612 <<
"DeltaT0=" <<
m_T0;
613 std::ostringstream constraint_str;
616 tie_str <<
",RotX=0.0";
618 constraint_str << -searchRadiusRotX <<
"<RotX<" << searchRadiusRotX <<
",";
622 tie_str <<
",RotY=0.0";
624 constraint_str << -searchRadiusRotY <<
"<RotY<" << searchRadiusRotY <<
",";
628 tie_str <<
",RotZ=0.0";
630 constraint_str << -searchRadiusRotZ <<
"<RotZ<" << searchRadiusRotZ <<
",";
634 tie_str <<
",DeltaX=0.0,DeltaY=0.0,DeltaZ=0.0";
636 constraint_str << -searchRadiusTran <<
"<DeltaX<" << searchRadiusTran <<
","
637 << -searchRadiusTran <<
"<DeltaY<" << searchRadiusTran <<
","
638 << -searchRadiusTran <<
"<DeltaZ<" << searchRadiusTran;
644 std::shared_ptr<const Geometry::RectangularDetector> rectDet =
645 std::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp);
649 std::ostringstream scaleconstraints;
650 std::ostringstream scaleties;
651 if (rectDet && docalibsize) {
653 scaleconstraints << scales.first - sizesearchradius <<
" <=ScaleX<" << scales.first + sizesearchradius;
655 scaleties <<
"ScaleX=ScaleY";
657 scaleconstraints <<
"," << scales.second - sizesearchradius <<
" <=ScaleY<" << scales.second + sizesearchradius;
661 scaleties <<
"ScaleX=" << scales.first <<
", ScaleY=" << scales.second;
665 std::string fitconstraint{constraint_str.str()};
666 if (scaleconstraints.str() !=
"") {
667 if (fitconstraint ==
"")
668 fitconstraint += scaleconstraints.str();
670 fitconstraint +=
"," + scaleconstraints.str();
672 std::string fittie{tie_str.str()};
673 if (scaleties.str() !=
"") {
675 fittie += scaleties.str();
677 fittie +=
"," + scaleties.str();
680 g_log.
information(
"Fitting " + bankname +
": constraint = " + fitconstraint +
"\n\t tie = " + fittie);
684 fitBank_alg->setProperty(
"Ties", fittie);
685 if (fitconstraint !=
"")
686 fitBank_alg->setProperty(
"Constraints", fitconstraint);
687 fitBank_alg->setProperty(
"InputWorkspace", wsBankCali);
688 fitBank_alg->setProperty(
"CreateOutput",
true);
689 fitBank_alg->setProperty(
"Output",
"fit");
692 fitBank_alg->executeAsChildAlg();
695 double chi2OverDOF = fitBank_alg->getProperty(
"OutputChi2overDoF");
697 double dx = rstFitBank->getRef<
double>(
"Value", 0);
698 double dy = rstFitBank->getRef<
double>(
"Value", 1);
699 double dz = rstFitBank->getRef<
double>(
"Value", 2);
700 double drx = rstFitBank->getRef<
double>(
"Value", 3);
701 double dry = rstFitBank->getRef<
double>(
"Value", 4);
702 double drz = rstFitBank->getRef<
double>(
"Value", 5);
703 double scalex = rstFitBank->getRef<
double>(
"Value", 10);
704 double scaley = rstFitBank->getRef<
double>(
"Value", 11);
707 std::string bn = bankname;
708 std::ostringstream calilog;
716 if (pws->getInstrument()->getName().compare(
"CORELLI") == 0) {
717 bn.append(
"/sixteenpack");
720 if (rectDet && docalibsize) {
729 V3D dtrans(dx, dy, dz);
730 V3D drots(drx, dry, drz);
731 calilog <<
"-- Fit " << bn <<
" results using " << nBankPeaks <<
" peaks:\n"
732 <<
" d(x,y,z) = " << dtrans <<
"\n"
733 <<
" r(x,y,z) = " << drots <<
"\n"
734 <<
" scale(x, y) = " <<
scalex <<
", " <<
scaley <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
769 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
771 std::vector<double> tofs =
captureTOF(pws_original);
772 objf->setPeakWorkspace(pws,
"none", tofs,
m_waveFromUB);
773 fitT0_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
776 std::ostringstream tie_str;
777 tie_str <<
"DeltaX=0.0,DeltaY=0.0,DeltaZ=0.0,"
778 <<
"RotX=0.0,RotY=0.0,RotZ=0.0,"
779 <<
"DeltaSampleX=0.0,DeltaSampleY=0.0,DeltaSampleZ=0.0";
780 std::ostringstream constraint_str;
782 r_dT0 = std::abs(r_dT0);
783 constraint_str << -r_dT0 <<
"<DeltaT0<" << r_dT0;
786 fitT0_alg->setProperty(
"Ties", tie_str.str());
787 fitT0_alg->setProperty(
"Constraints", constraint_str.str());
788 fitT0_alg->setProperty(
"InputWorkspace", t0ws);
789 fitT0_alg->setProperty(
"CreateOutput",
true);
790 fitT0_alg->setProperty(
"Output",
"fit");
791 fitT0_alg->executeAsChildAlg();
794 std::ostringstream calilog;
795 double chi2OverDOF = fitT0_alg->getProperty(
"OutputChi2overDoF");
797 double dT0_optimized = rst->getRef<
double>(
"Value", 6);
800 m_T0 = dT0_optimized;
801 int npks = pws->getNumberPeaks();
803 calilog <<
"-- Fit T0 results using " << npks <<
" peaks:\n"
804 <<
" dT0 = " <<
m_T0 <<
" (ms)\n"
805 <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
822 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
824 std::vector<double> tofs =
captureTOF(pws_original);
825 objf->setPeakWorkspace(pws,
"none", tofs,
m_waveFromUB);
826 fitSamplePos_alg->setProperty(
"Function", std::dynamic_pointer_cast<IFunction>(objf));
829 std::ostringstream tie_str;
830 tie_str <<
"DeltaX=0.0,DeltaY=0.0,DeltaZ=0.0,"
831 <<
"RotX=0.0,RotY=0.0,RotZ=0.0,"
832 <<
"DeltaT0=" <<
m_T0;
833 std::ostringstream constraint_str;
834 double r_dsp =
getProperty(
"SearchRadiusSamplePos");
835 r_dsp = std::abs(r_dsp);
836 constraint_str << -r_dsp <<
"<DeltaSampleX<" << r_dsp <<
"," << -r_dsp <<
"<DeltaSampleY<" << r_dsp <<
"," << -r_dsp
837 <<
"<DeltaSampleZ<" << r_dsp;
840 fitSamplePos_alg->setProperty(
"Ties", tie_str.str());
841 fitSamplePos_alg->setProperty(
"Constraints", constraint_str.str());
842 fitSamplePos_alg->setProperty(
"InputWorkspace", samplePosws);
843 fitSamplePos_alg->setProperty(
"CreateOutput",
true);
844 fitSamplePos_alg->setProperty(
"Output",
"fit");
845 fitSamplePos_alg->executeAsChildAlg();
848 std::ostringstream calilog;
849 double chi2OverDOF = fitSamplePos_alg->getProperty(
"OutputChi2overDoF");
851 double dsx_optimized = rst->getRef<
double>(
"Value", 7);
852 double dsy_optimized = rst->getRef<
double>(
"Value", 8);
853 double dsz_optimized = rst->getRef<
double>(
"Value", 9);
857 "sample-position", pws);
858 int npks = pws->getNumberPeaks();
860 calilog <<
"-- Tune SamplePos results using " << npks <<
" peaks:\n"
861 <<
" deltaSamplePos = (" << dsx_optimized <<
"," << dsy_optimized <<
"," << dsz_optimized <<
")\n"
862 <<
" chi2/DOF = " << chi2OverDOF <<
"\n";
886 (pws->sample().hasOrientedLattice())) {
906 calcUB_alg->setProperty(
"PeaksWorkspace", pws);
907 calcUB_alg->setProperty(
"a",
m_a);
908 calcUB_alg->setProperty(
"b",
m_b);
909 calcUB_alg->setProperty(
"c",
m_c);
910 calcUB_alg->setProperty(
"alpha",
m_alpha);
911 calcUB_alg->setProperty(
"beta",
m_beta);
912 calcUB_alg->setProperty(
"gamma",
m_gamma);
913 calcUB_alg->executeAsChildAlg();
920 idxpks_alg->setProperty(
"PeaksWorkspace", pws);
921 idxpks_alg->setProperty(
"RoundHKLs",
true);
922 idxpks_alg->setProperty(
"Tolerance", tol);
923 idxpks_alg->executeAsChildAlg();
935 fltpk_alg->setProperty(
"InputWorkspace", pws);
936 fltpk_alg->setProperty(
"FilterVariable",
"h^2+k^2+l^2");
937 fltpk_alg->setProperty(
"Operator",
">");
938 fltpk_alg->setProperty(
"FilterValue", 0.0);
939 fltpk_alg->setProperty(
"OutputWorkspace",
"pws_filtered");
940 fltpk_alg->executeAsChildAlg();
953 std::vector<double> tofs;
955 for (
int i = 0; i < pws->getNumberPeaks(); ++i) {
956 tofs.emplace_back(pws->getPeak(i).getTOF());
968 auto peaksWorkspace = std::dynamic_pointer_cast<DataObjects::PeaksWorkspace>(pws);
970 throw std::invalid_argument(
"a PeaksWorkspace is required to retrieve bank names");
971 int npeaks =
static_cast<int>(pws->getNumberPeaks());
972 for (
int i = 0; i < npeaks; ++i) {
973 std::string bname = peaksWorkspace->getPeak(i).getBankName();
988 const std::string &bankname,
989 const std::string &outputwsn) {
992 fltpk_alg->setProperty(
"InputWorkspace", pws);
993 fltpk_alg->setProperty(
"BankName", bankname);
994 fltpk_alg->setProperty(
"Criterion",
"=");
995 fltpk_alg->setProperty(
"OutputWorkspace", outputwsn);
996 fltpk_alg->executeAsChildAlg();
1010 int npeaks = pws->getNumberPeaks();
1018 auto &spectrum = mws->getSpectrum(0);
1019 auto &xvector = spectrum.mutableX();
1020 auto &yvector = spectrum.mutableY();
1021 auto &evector = spectrum.mutableE();
1024 double totalSigmaInt = 0.0;
1025 for (
int i = 0; i < npeaks; ++i) {
1026 totalSigmaInt += pws->getPeak(i).getSigmaIntensity();
1028 double totalInt = 0.0;
1029 for (
int i = 0; i < npeaks; ++i) {
1030 totalInt += pws->getPeak(i).getIntensity();
1032 double totalCnt = 0.0;
1033 for (
int i = 0; i < npeaks; ++i) {
1034 totalCnt += pws->getPeak(i).getBinCount();
1038 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1039 for (
int i = 0; i < npeaks; ++i) {
1041 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1045 if (totalSigmaInt > 0.0) {
1046 wgt = 1.0 / pws->getPeak(i).getSigmaIntensity();
1047 }
else if (totalInt > 0.0) {
1048 wgt = 1.0 / pws->getPeak(i).getIntensity();
1049 }
else if (totalCnt > 0.0) {
1050 wgt = 1.0 / pws->getPeak(i).getBinCount();
1053 for (
int j = 0; j < 3; ++j) {
1054 xvector[i * 3 + j] = i * 3 + j;
1055 yvector[i * 3 + j] = qv[j];
1056 evector[i * 3 + j] = wgt;
1078 double scalex,
double scaley,
const std::string &cmptName,
1084 mv_alg->setProperty(
"ComponentName", cmptName);
1085 mv_alg->setProperty(
"X", dx);
1086 mv_alg->setProperty(
"Y", dy);
1087 mv_alg->setProperty(
"Z", dz);
1088 mv_alg->setProperty(
"RelativePosition",
true);
1089 mv_alg->executeAsChildAlg();
1096 rot_alg->setProperty(
"ComponentName", cmptName);
1097 rot_alg->setProperty(
"X", 1.0);
1098 rot_alg->setProperty(
"Y", 0.0);
1099 rot_alg->setProperty(
"Z", 0.0);
1100 rot_alg->setProperty(
"Angle", drx);
1101 rot_alg->setProperty(
"RelativeRotation",
true);
1102 rot_alg->executeAsChildAlg();
1105 rot_alg->setProperty(
"ComponentName", cmptName);
1106 rot_alg->setProperty(
"X", 0.0);
1107 rot_alg->setProperty(
"Y", 1.0);
1108 rot_alg->setProperty(
"Z", 0.0);
1109 rot_alg->setProperty(
"Angle", dry);
1110 rot_alg->setProperty(
"RelativeRotation",
true);
1111 rot_alg->executeAsChildAlg();
1114 rot_alg->setProperty(
"ComponentName", cmptName);
1115 rot_alg->setProperty(
"X", 0.0);
1116 rot_alg->setProperty(
"Y", 0.0);
1117 rot_alg->setProperty(
"Z", 1.0);
1118 rot_alg->setProperty(
"Angle", drz);
1119 rot_alg->setProperty(
"RelativeRotation",
true);
1120 rot_alg->executeAsChildAlg();
1125 resizeAlg->initialize();
1126 resizeAlg->setProperty(
"Workspace", pws);
1127 resizeAlg->setProperty(
"ComponentName", cmptName);
1128 resizeAlg->setProperty(
"ScaleX",
scalex);
1129 resizeAlg->setProperty(
"ScaleY",
scaley);
1130 resizeAlg->execute();
1145 g_log.
notice() <<
"Generate a TableWorkspace to store calibration results.\n";
1154 V3D sourceRelPos = source->getRelativePos();
1158 sourceRow << instrument->getSource()->getName() << sourceRelPos.
X() << sourceRelPos.
Y() << sourceRelPos.
Z() << 1.0
1159 << 0.0 << 0.0 << 0.0 << 0.0 << 0.0;
1165 if (instrument->getName().compare(
"CORELLI") == 0)
1166 bankName.append(
"/sixteenpack");
1168 std::shared_ptr<const IComponent> bank = instrument->getComponentByName(bankName);
1170 Quat relRot = bank->getRelativeRot();
1171 V3D pos1 = bank->getRelativePos();
1174 double deg, xAxis, yAxis, zAxis;
1183 bankRow << bankName << pos1.
X() << pos1.
Y() << pos1.
Z() << xAxis << yAxis << zAxis << deg << scales.first
1210 const boost::container::flat_set<std::string> &AllBankNames,
1214 using boost::property_tree::ptree;
1219 parafile.put(
"<xmlattr>.instrument", instrument->getName());
1220 parafile.put(
"<xmlattr>.valid-from",
pmap.instrumentMetadata().validFromDate().toISO8601String());
1224 ptree src_dx, src_dy, src_dz;
1225 ptree src_dx_val, src_dy_val, src_dz_val;
1228 V3D sourceRelPos = source->getRelativePos();
1230 src_dx_val.put(
"<xmlattr>.val", sourceRelPos.
X());
1231 src_dy_val.put(
"<xmlattr>.val", sourceRelPos.
Y());
1232 src_dz_val.put(
"<xmlattr>.val", sourceRelPos.
Z());
1233 src_dx.put(
"<xmlattr>.name",
"x");
1234 src_dy.put(
"<xmlattr>.name",
"y");
1235 src_dz.put(
"<xmlattr>.name",
"z");
1236 src.put(
"<xmlattr>.name", source->getName());
1238 src_dx.add_child(
"value", src_dx_val);
1239 src_dy.add_child(
"value", src_dy_val);
1240 src_dz.add_child(
"value", src_dz_val);
1241 src.add_child(
"parameter", src_dx);
1242 src.add_child(
"parameter", src_dy);
1243 src.add_child(
"parameter", src_dz);
1245 parafile.add_child(
"component-link", src);
1250 ptree property_root;
1251 property_root.put(
"<xmlattr>.name", instrument->getName());
1254 tof0.put(
"<xmlattr>.name",
"T0");
1255 tof0_val.put(
"<xmlattr>.val",
m_T0);
1256 tof0.add_child(
"value", tof0_val);
1257 property_root.add_child(
"parameter", tof0);
1258 parafile.add_child(
"component-link", property_root);
1262 ptree samplePos_dx, samplePos_dy, samplePos_dz;
1263 ptree samplePos_dx_val, samplePos_dy_val, samplePos_dz_val;
1265 std::shared_ptr<const IComponent> sp = instrument->getComponentByName(
"sample-position");
1266 V3D sppos = sp->getRelativePos();
1267 samplePos_dx_val.put(
"<xmlattr>.val", sppos.
X());
1268 samplePos_dy_val.put(
"<xmlattr>.val", sppos.
Y());
1269 samplePos_dz_val.put(
"<xmlattr>.val", sppos.
Z());
1270 samplePos_dx.put(
"<xmlattr>.name",
"x");
1271 samplePos_dy.put(
"<xmlattr>.name",
"y");
1272 samplePos_dz.put(
"<xmlattr>.name",
"z");
1273 samplePos.put(
"<xmlattr>.name",
"sample-position");
1275 samplePos_dx.add_child(
"value", samplePos_dx_val);
1276 samplePos_dy.add_child(
"value", samplePos_dy_val);
1277 samplePos_dz.add_child(
"value", samplePos_dz_val);
1278 samplePos.add_child(
"parameter", samplePos_dx);
1279 samplePos.add_child(
"parameter", samplePos_dy);
1280 samplePos.add_child(
"parameter", samplePos_dz);
1282 parafile.add_child(
"component-link", samplePos);
1285 for (
auto bankName : AllBankNames) {
1287 if (instrument->getName().compare(
"CORELLI") == 0)
1288 bankName.append(
"/sixteenpack");
1290 std::shared_ptr<const IComponent> bank = instrument->getComponentByName(bankName);
1291 auto bankFullName = bank->getFullName();
1293 Quat relRot = bank->getRelativeRot();
1295 V3D pos1 = bank->getRelativePos();
1300 ptree bank_dx, bank_dy, bank_dz;
1301 ptree bank_dx_val, bank_dy_val, bank_dz_val;
1302 ptree bank_drotx, bank_droty, bank_drotz;
1303 ptree bank_drotx_val, bank_droty_val, bank_drotz_val;
1304 ptree bank_sx, bank_sy;
1305 ptree bank_sx_val, bank_sy_val;
1308 bank_dx_val.put(
"<xmlattr>.val", pos1.
X());
1309 bank_dy_val.put(
"<xmlattr>.val", pos1.
Y());
1310 bank_dz_val.put(
"<xmlattr>.val", pos1.
Z());
1311 bank_dx.put(
"<xmlattr>.name",
"x");
1312 bank_dy.put(
"<xmlattr>.name",
"y");
1313 bank_dz.put(
"<xmlattr>.name",
"z");
1315 bank_drotx_val.put(
"<xmlattr>.val", relRotAngles[0]);
1316 bank_droty_val.put(
"<xmlattr>.val", relRotAngles[1]);
1317 bank_drotz_val.put(
"<xmlattr>.val", relRotAngles[2]);
1318 bank_drotx.put(
"<xmlattr>.name",
"rotx");
1319 bank_droty.put(
"<xmlattr>.name",
"roty");
1320 bank_drotz.put(
"<xmlattr>.name",
"rotz");
1322 bank_sx_val.put(
"<xmlattr>.val", scales.first);
1323 bank_sy_val.put(
"<xmlattr>.val", scales.second);
1324 bank_sx.put(
"<xmlattr>.name",
"scalex");
1325 bank_sy.put(
"<xmlattr>.name",
"scaley");
1327 bank_root.put(
"<xmlattr>.name", bankFullName);
1330 bank_dx.add_child(
"value", bank_dx_val);
1331 bank_dy.add_child(
"value", bank_dy_val);
1332 bank_dz.add_child(
"value", bank_dz_val);
1334 bank_drotx.add_child(
"value", bank_drotx_val);
1335 bank_droty.add_child(
"value", bank_droty_val);
1336 bank_drotz.add_child(
"value", bank_drotz_val);
1338 bank_sx.add_child(
"value", bank_sx_val);
1339 bank_sy.add_child(
"value", bank_sy_val);
1341 bank_root.add_child(
"parameter", bank_drotx);
1343 bank_root.add_child(
"parameter", bank_droty);
1344 bank_root.add_child(
"parameter", bank_drotz);
1345 bank_root.add_child(
"parameter", bank_dx);
1346 bank_root.add_child(
"parameter", bank_dy);
1347 bank_root.add_child(
"parameter", bank_dz);
1348 bank_root.add_child(
"parameter", bank_sx);
1349 bank_root.add_child(
"parameter", bank_sy);
1351 parafile.add_child(
"component-link", bank_root);
1355 root.add_child(
"parameter-file", parafile);
1357 g_log.
notice() <<
"\tSaving parameter file as " << FileName <<
"\n";
1358 boost::property_tree::write_xml(FileName, root, std::locale(),
1359 boost::property_tree::xml_writer_settings<std::string>(
' ', 2));
1373 boost::container::flat_set<std::string> &AllBankName,
1374 std::shared_ptr<Instrument> &instrument,
double T0) {
1375 g_log.
notice() <<
"Saving DetCal file in " << filename <<
"\n";
1377 bool tuneSamplePos =
getProperty(
"TuneSamplePosition");
1378 if (tuneSamplePos) {
1380 <<
"DetCal format cannot retain sample position info, therefore the calibrated "
1381 <<
"sample position will be lost if DetCal format is the only output!\n";
1385 const size_t number_spectra = instrument->getNumberDetectors();
1388 wksp->setInstrument(instrument);
1389 wksp->rebuildSpectraMapping(
true );
1392 std::vector<std::string> banknames(AllBankName.begin(), AllBankName.end());
1396 alg->setProperty(
"InputWorkspace", wksp);
1397 alg->setProperty(
"Filename", filename);
1398 alg->setProperty(
"TimeOffset", T0);
1399 alg->setProperty(
"BankNames", banknames);
1400 alg->executeAsChildAlg();
1412 alg->setProperty(
"InputWorkspace", tws);
1413 alg->setProperty(
"Filename", FileName);
1414 alg->setPropertyValue(
"CommentIndicator",
"#");
1415 alg->setPropertyValue(
"Separator",
"CSV");
1416 alg->setProperty(
"ColumnHeader",
true);
1417 alg->setProperty(
"AppendToFile",
false);
1418 alg->executeAsChildAlg();
1429 g_log.
notice() <<
"START of profiling objective func along L1\n";
1439 std::ostringstream msgrst;
1440 msgrst.precision(12);
1441 msgrst <<
"dL1\tresidual\n";
1444 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1446 std::vector<double> tofs =
captureTOF(pws_original);
1447 objf->setPeakWorkspace(pws,
"moderator", tofs,
m_waveFromUB);
1450 const int n_peaks = pws->getNumberPeaks();
1451 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1454 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1455 for (
int i = 0; i < n_peaks; ++i) {
1456 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1458 for (
int j = 0; j < 3; ++j) {
1459 target[i * 3 + j] = qv[j];
1463 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1467 double deltaL1 = -4e-2;
1468 while (deltaL1 < 4e-2) {
1469 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1470 objf->setParameter(
"DeltaZ", deltaL1);
1471 objf->setParameter(
"DeltaT0", 0.0);
1472 objf->function1D(out.get(), xValues, 1);
1475 double residual = 0.0;
1476 for (
int i = 0; i < n_peaks * 3; ++i) {
1477 residual += (out[i] - target[i]) * (out[i] - target[i]);
1479 residual = std::sqrt(residual) / (n_peaks - 1);
1481 msgrst << deltaL1 <<
"\t" << residual <<
"\n";
1484 g_log.
notice() << deltaL1 <<
" -- " << residual <<
"\n";
1492 auto filenamebase = std::filesystem::temp_directory_path() /
"profileSCDCalibratePanels2_L1.csv";
1493 std::ofstream profL1File;
1494 profL1File.open(filenamebase.string());
1495 profL1File << msgrst.str();
1498 << filenamebase <<
"\n"
1499 <<
"END of profiling objective func along L1\n";
1510 g_log.
notice() <<
"START of profiling all banks along six degree of freedom\n";
1520 for (
int bankIndex = 0; bankIndex < static_cast<int>(
m_BankNames.size()); ++bankIndex) {
1523 const std::string bankname = *std::next(
m_BankNames.begin(), bankIndex);
1524 const std::string pwsBankiName =
"_pws_" + bankname;
1530 std::vector<double> tofs =
captureTOF(pwsBanki_original);
1534 int nBankPeaks = pwsBanki->getNumberPeaks();
1537 std::ostringstream msg_npeakCheckFail;
1538 msg_npeakCheckFail <<
"-- Cannot profile Bank " << bankname <<
" have only " << nBankPeaks <<
" (<"
1546 std::ostringstream msgrst;
1547 msgrst.precision(12);
1548 msgrst <<
"dx\tdy\tdz\ttheta\tphi\trogang\tresidual\n";
1550 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1551 objf->setPeakWorkspace(pwsBanki, bankname, tofs,
m_waveFromUB);
1553 const int n_peaks = pwsBanki->getNumberPeaks();
1554 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1556 auto ubmatrix = pwsBanki->sample().getOrientedLattice().getUB();
1557 for (
int i = 0; i < n_peaks; ++i) {
1558 V3D qv = ubmatrix * pwsBanki->getPeak(i).getIntHKL();
1560 for (
int j = 0; j < 3; ++j) {
1561 target[i * 3 + j] = qv[j];
1565 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1568 for (
double dx = -1e-2; dx < 1e-2; dx += 2e-2 / 20.0) {
1570 for (
double dy = -1e-2; dy < 1e-2; dy += 2e-2 / 20.0) {
1572 for (
double dz = -1e-2; dz < 1e-2; dz += 2e-2 / 20.0) {
1574 for (
double theta = 0.0; theta <
PI; theta +=
PI / 20.0) {
1576 for (
double phi = 0.0; phi < 2 *
PI; phi += 2 *
PI / 20.0) {
1578 for (
double ang = -5.0; ang < 5.0; ang += 5.0 / 20.0) {
1581 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1582 objf->setParameter(
"DeltaX", dx);
1583 objf->setParameter(
"DeltaY", dy);
1584 objf->setParameter(
"DeltaZ", dz);
1585 objf->setParameter(
"Theta", theta);
1586 objf->setParameter(
"Phi", phi);
1587 objf->setParameter(
"DeltaRotationAngle", ang);
1588 objf->setParameter(
"DeltaT0", 0.0);
1589 objf->function1D(out.get(), xValues, 1);
1591 double residual = 0.0;
1592 for (
int i = 0; i < n_peaks * 3; ++i) {
1593 residual += (out[i] - target[i]) * (out[i] - target[i]);
1595 residual = std::sqrt(residual) / (n_peaks - 6);
1597 msgrst << dx <<
"\t" << dy <<
"\t" << dz <<
"\t" << theta <<
"\t" << phi <<
"\t" << ang <<
"\t"
1598 << residual <<
"\n";
1601 g_log.
notice() <<
"--" << bankname <<
": " << residual <<
"\n";
1611 const std::string csvname =
"profileSCDCalibratePanels2_" + bankname +
".csv";
1612 auto filenamebase = std::filesystem::temp_directory_path() / csvname;
1613 std::ofstream profBankFile;
1614 profBankFile.open(filenamebase.string());
1615 profBankFile << msgrst.str();
1616 profBankFile.close();
1619 std::ostringstream msg;
1620 msg <<
"Profile of " << bankname <<
" is saved at:\n"
1621 << filenamebase <<
"\n"
1622 <<
"END of profiling objective func for " << bankname <<
"\n";
1637 g_log.
notice() <<
"START of profiling objective func along T0\n";
1647 std::ostringstream msgrst;
1648 msgrst.precision(12);
1649 msgrst <<
"dT0\tresidual\n";
1652 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1654 std::vector<double> tofs =
captureTOF(pws_original);
1655 objf->setPeakWorkspace(pws,
"none", tofs,
m_waveFromUB);
1658 const int n_peaks = pws->getNumberPeaks();
1659 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1660 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1661 for (
int i = 0; i < n_peaks; ++i) {
1662 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1664 for (
int j = 0; j < 3; ++j) {
1665 target[i * 3 + j] = qv[j];
1669 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1672 double deltaT0 = -10;
1673 while (deltaT0 < 10) {
1674 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1675 objf->setParameter(
"DeltaT0", deltaT0);
1676 objf->function1D(out.get(), xValues, 1);
1679 double residual = 0.0;
1680 for (
int i = 0; i < n_peaks * 3; ++i) {
1681 residual += (out[i] - target[i]) * (out[i] - target[i]);
1683 residual = std::sqrt(residual) / (n_peaks - 1);
1685 msgrst << deltaT0 <<
"\t" << residual <<
"\n";
1688 g_log.
notice() << deltaT0 <<
" -- " << residual <<
"\n";
1696 auto filenamebase = std::filesystem::temp_directory_path() /
"profileSCDCalibratePanels2_T0.csv";
1697 std::ofstream profL1File;
1698 profL1File.open(filenamebase.string());
1699 profL1File << msgrst.str();
1702 << filenamebase <<
"\n"
1703 <<
"END of profiling objective func along T0\n";
1714 g_log.
notice() <<
"START of profiling objective func along L1 and T0\n";
1720 g_log.
notice() <<
"deltaL1 -- deltaT0 -- residual\n";
1724 std::ostringstream msgrst;
1725 msgrst.precision(12);
1726 msgrst <<
"dL1\tdT0\tresidual\n";
1729 auto objf = std::make_shared<SCDCalibratePanels2ObjFunc>();
1731 std::vector<double> tofs =
captureTOF(pws_original);
1732 objf->setPeakWorkspace(pws,
"moderator", tofs,
m_waveFromUB);
1735 const int n_peaks = pws->getNumberPeaks();
1736 std::unique_ptr<double[]> target(
new double[n_peaks * 3]);
1737 auto ubmatrix = pws->sample().getOrientedLattice().getUB();
1738 for (
int i = 0; i < n_peaks; ++i) {
1739 V3D qv = ubmatrix * pws->getPeak(i).getIntHKL();
1741 for (
int j = 0; j < 3; ++j) {
1742 target[i * 3 + j] = qv[j];
1746 const double xValues[7] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1749 for (
double deltaL1 = -4e-2; deltaL1 < 4e-2; deltaL1 += 1e-4) {
1750 for (
double deltaT0 = -4.0; deltaT0 < 4.0; deltaT0 += 1e-2) {
1751 std::unique_ptr<double[]> out(
new double[n_peaks * 3]);
1752 objf->setParameter(
"DeltaZ", deltaL1);
1753 objf->setParameter(
"DeltaT0", deltaT0);
1754 objf->function1D(out.get(), xValues, 1);
1757 double residual = 0.0;
1758 for (
int i = 0; i < n_peaks * 3; ++i) {
1759 residual += (out[i] - target[i]) * (out[i] - target[i]);
1761 residual = std::sqrt(residual) / (n_peaks - 2);
1764 g_log.
notice() << deltaL1 <<
" -- " << deltaT0 <<
" -- " << residual <<
"\n";
1767 msgrst << deltaL1 <<
"\t" << deltaT0 <<
"\t" << residual <<
"\n";
1772 auto filenamebase = std::filesystem::temp_directory_path() /
"profileSCDCalibratePanels2_L1T0.csv";
1773 std::ofstream profL1File;
1774 profL1File.open(filenamebase.string());
1775 profL1File << msgrst.str();
1780 << filenamebase <<
"\n"
1781 <<
"END of profiling objective func along L1 and T0\n";
1796std::pair<double, double>
1798 const std::string &bankname,
1801 std::pair<double, double> scales{1.0, 1.0};
1805 std::shared_ptr<const Geometry::RectangularDetector> rectDet =
1806 std::dynamic_pointer_cast<const Geometry::RectangularDetector>(comp);
1810 auto scalexparams =
pmap.getDouble(rectDet->getName(),
"scalex");
1811 auto scaleyparams =
pmap.getDouble(rectDet->getName(),
"scaley");
1812 if (!scalexparams.empty())
1813 scales.first = scalexparams[0];
1814 if (!scaleyparams.empty())
1815 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.
Parameter map iterator typedef.
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.