143 if (peaks != outPeaks) {
144 outPeaks = peaks->clone();
147 std::vector<int> NOoptimizeRuns =
getProperty(
"KeepGoniometerFixedfor");
149 const DblMatrix X = peaks->sample().getOrientedLattice().getUB();
157 std::vector<int> RunNumList;
158 std::vector<V3D> ChiPhiOmega;
162 double HKLintOffsetMax =
getProperty(
"MaxIndexingError");
164 for (
int i = 0; i < peaks->getNumberPeaks(); i++) {
165 IPeak const &peak = peaks->getPeak(i);
167 auto it = RunNumList.begin();
168 for (; it != RunNumList.end() && *it != runNum; ++it) {
174 if (use && HKLMax > 0)
175 for (
int k = 0; k < 3; k++) {
176 if (
fabs(hkl[k]) > HKLMax)
180 if (it == RunNumList.end() && use)
182 RunNumList.emplace_back(runNum);
186 ChiPhiOmega.emplace_back(phichiOmega[1], phichiOmega[2], phichiOmega[0]);
192 xRef.emplace_back(
static_cast<double>(i));
193 xRef.emplace_back(
static_cast<double>(i));
194 xRef.emplace_back(
static_cast<double>(i));
198 g_log.
notice() <<
"Number initially indexed = " << nPeaksUsed <<
" at tolerance = " << HKLintOffsetMax <<
'\n';
200 if (nPeaksUsed < 1) {
201 g_log.
error() <<
"Error in UB too large. 0 peaks indexed at " << HKLintOffsetMax <<
'\n';
202 throw std::invalid_argument(
"Error in UB too large. 0 peaks indexed ");
205 int N = 3 * nPeaksUsed;
206 auto mwkspc = createWorkspace<Workspace2D>(1, N, N);
207 mwkspc->setPoints(0, xRef);
208 mwkspc->setCounts(0, N, 0.0);
209 mwkspc->setCountStandardDeviations(0, N, 1.0);
211 std::string FuncArg =
"name=PeakHKLErrors,PeakWorkspaceName=" +
getPropertyValue(
"PeaksWorkspace") +
"";
213 std::string OptRunNums;
217 std::vector<std::string> ChRunNumList;
218 std::string predChar;
219 for (
auto runNum : RunNumList) {
220 auto it1 = NOoptimizeRuns.begin();
221 for (; it1 != NOoptimizeRuns.end() && *it1 != runNum; ++it1) {
224 if (it1 == NOoptimizeRuns.end()) {
226 OptRunNums += predChar + runNumStr;
228 ChRunNumList.emplace_back(runNumStr);
234 NOoptimizeRuns = RunNumList;
236 std::string message =
"No Goniometer Angles ";
238 message +=
"relative to the tilted Goniometer ";
239 message +=
"will be 'changed'";
242 if (!OptRunNums.empty() && !omitRuns)
243 FuncArg +=
",OptRuns=" + OptRunNums;
247 std::ostringstream oss(std::ostringstream::out);
249 std::ostringstream oss1(std::ostringstream::out);
253 double DegreeTol =
getProperty(
"MaxAngularChange");
254 std::string startConstraint;
256 for (
size_t i = 0; i < RunNumList.size(); i++) {
257 int runNum = RunNumList[i];
260 for (; k < NOoptimizeRuns.size(); k++) {
261 if (NOoptimizeRuns[k] == runNum)
264 if (k >= NOoptimizeRuns.size()) {
265 V3D chiphiomega = ChiPhiOmega[i];
266 oss <<
",chi" << runNum <<
"=" << chiphiomega[0] <<
",phi" << runNum <<
"=" << chiphiomega[1] <<
",omega"
267 << runNum <<
"=" << chiphiomega[2];
269 oss1 << startConstraint << chiphiomega[0] - DegreeTol <<
"<chi" << runNum <<
"<" << chiphiomega[0] + DegreeTol;
270 oss1 <<
"," << chiphiomega[1] - DegreeTol <<
"<phi" << runNum <<
"<" << chiphiomega[1] + DegreeTol;
272 oss1 <<
"," << chiphiomega[2] - DegreeTol <<
"<omega" << runNum <<
"<" << chiphiomega[2] + DegreeTol;
273 startConstraint =
",";
279 V3D sampPos =
V3D(0., 0., 0.);
281 oss <<
",SampleXOffset=" << sampPos.
X() <<
",SampleYOffset=" << sampPos.
Y() <<
",SampleZOffset=" << sampPos.
Z();
282 oss <<
",GonRotx=0.0,GonRoty=0.0,GonRotz=0.0";
284 double maxSampshift =
getProperty(
"MaxSamplePositionChangeMeters");
285 oss1 << startConstraint << sampPos.
X() - maxSampshift <<
"<SampleXOffset<" << sampPos.
X() + maxSampshift <<
","
286 << sampPos.
Y() - maxSampshift <<
"<SampleYOffset<" << sampPos.
Y() + maxSampshift <<
","
287 << sampPos.
Z() - maxSampshift <<
"<SampleZOffset<" << sampPos.
Z() + maxSampshift;
289 oss1 <<
"," << -DegreeTol <<
"<GonRotx<" << DegreeTol <<
"," << -DegreeTol <<
"<GonRoty<" << DegreeTol <<
","
290 << -DegreeTol <<
"<GonRotz<" << DegreeTol;
292 FuncArg += oss.str();
293 std::string Constr = oss1.str();
295 g_log.
debug() <<
"Function argument=" << FuncArg <<
'\n';
296 g_log.
debug() <<
"Constraint argument=" << Constr <<
'\n';
302 fit_alg->setProperty(
"Function", FuncArg);
304 fit_alg->setProperty(
"MaxIterations", 60);
306 fit_alg->setProperty(
"Constraints", Constr);
308 fit_alg->setProperty(
"InputWorkspace", mwkspc);
310 fit_alg->setProperty(
"CreateOutput",
true);
315 std::ostringstream oss3(std::ostringstream::out);
318 oss3 <<
"SampleXOffset=" << sampPos.
X() <<
",SampleYOffset=" << sampPos.
Y() <<
",SampleZOffset=" << sampPos.
Z();
322 if (!(
bool)
getProperty(
"OptimizeGoniometerTilt")) {
326 Ties +=
"GonRotx=0.0,GonRoty=0.0,GonRotz=0.0";
330 fit_alg->setProperty(
"Ties", Ties);
332 fit_alg->setProperty(
"Output",
"out");
334 fit_alg->executeAsChildAlg();
338 double chisq = fit_alg->getProperty(
"OutputChi2overDoF");
339 g_log.
notice() <<
"Fit finished. Status=" << (std::string)fit_alg->getProperty(
"OutputStatus") <<
'\n';
346 g_log.
debug() <<
"Chi2overDof=" << chisq <<
" # Peaks used=" << nPeaksUsed <<
"# fitting parameters =" << nParams
347 <<
" dof=" << (nPeaksUsed - nParams) <<
'\n';
351 double sigma = sqrt(chisq);
353 std::string OutputStatus = fit_alg->getProperty(
"OutputStatus");
354 g_log.
notice() <<
"Output Status=" << OutputStatus <<
'\n';
358 setProperty(
"OutputNormalisedCovarianceMatrixOptX",
361 if (chisq < 0 || chisq != chisq)
365 std::map<std::string, double> Results;
366 for (
int prm = 0; prm < static_cast<int>(RRes->rowCount()); ++prm) {
367 std::string namee = RRes->getRef<std::string>(
"Name", prm);
369 std::string start = namee.substr(0, 3);
370 if (start !=
"chi" && start !=
"phi" && start !=
"ome" && start !=
"Sam" && start !=
"Gon")
373 double value = RRes->getRef<
double>(
"Value", prm);
374 Results[namee] =
value;
377 double v =
sigma * RRes->getRef<
double>(
"Error", prm);
378 RRes->getRef<
double>(
"Error", prm) = v;
386 V3D newSampPos(Results[
"SampleXOffset"], Results[
"SampleYOffset"], Results[
"SampleZOffset"]);
388 auto &componentInfo = outPeaks->mutableComponentInfo();
396 std::map<int, Matrix<double>> MapRunNum2GonMat;
397 std::string OptRun2 =
"/" + OptRunNums +
"/";
400 UBinv = outPeaks->sample().getOrientedLattice().getUB();
403 for (
int i = 0; i < outPeaks->getNumberPeaks(); ++i) {
404 auto &peak = outPeaks->getPeak(i);
405 peak.setSamplePos(peak.getSamplePos() + newSampPos);
406 int RunNum = peak.getRunNumber();
409 if (RunNum == prevRunNum || MapRunNum2GonMat.find(RunNum) != MapRunNum2GonMat.end())
410 GonMatrix = MapRunNum2GonMat[RunNum];
411 else if (OptRun2.find(
"/" + RunNumStr +
"/") < OptRun2.size() - 2) {
413 double chi = Results[
"chi" + RunNumStr];
414 double phi = Results[
"phi" + RunNumStr];
415 double omega = Results[
"omega" + RunNumStr];
424 GonMatrix = GonTilt * uniGonio.
getR();
425 MapRunNum2GonMat[RunNum] = GonMatrix;
427 GonMatrix = GonTilt * peak.getGoniometerMatrix();
428 MapRunNum2GonMat[RunNum] = GonMatrix;
431 peak.setGoniometerMatrix(GonMatrix);
432 V3D hkl = UBinv * peak.getQSampleFrame();
439 if (MapRunNum2GonMat.size() == 1)
441 Matrix<double> GonMatrix = MapRunNum2GonMat[outPeaks->getPeak(0).getRunNumber()];
443 outPeaks->mutableRun().setGoniometer(Gon,
false);
448 g_log.
notice() <<
"Number indexed after optimization= " << nIndexed <<
" at tolerance = " << HKLintOffsetMax <<
'\n';