144 if (peaks != outPeaks) {
145 outPeaks = peaks->clone();
148 std::vector<int> NOoptimizeRuns =
getProperty(
"KeepGoniometerFixedfor");
150 const DblMatrix X = peaks->sample().getOrientedLattice().getUB();
158 std::vector<int> RunNumList;
159 std::vector<V3D> ChiPhiOmega;
163 double HKLintOffsetMax =
getProperty(
"MaxIndexingError");
165 for (
int i = 0; i < peaks->getNumberPeaks(); i++) {
166 IPeak const &peak = peaks->getPeak(i);
168 auto it = RunNumList.begin();
169 for (; it != RunNumList.end() && *it != runNum; ++it) {
175 if (use && HKLMax > 0)
176 for (
int k = 0; k < 3; k++) {
177 if (
fabs(hkl[k]) > HKLMax)
181 if (it == RunNumList.end() && use)
183 RunNumList.emplace_back(runNum);
187 ChiPhiOmega.emplace_back(phichiOmega[1], phichiOmega[2], phichiOmega[0]);
193 xRef.emplace_back(
static_cast<double>(i));
194 xRef.emplace_back(
static_cast<double>(i));
195 xRef.emplace_back(
static_cast<double>(i));
199 g_log.
notice() <<
"Number initially indexed = " << nPeaksUsed <<
" at tolerance = " << HKLintOffsetMax <<
'\n';
201 if (nPeaksUsed < 1) {
202 g_log.
error() <<
"Error in UB too large. 0 peaks indexed at " << HKLintOffsetMax <<
'\n';
203 throw std::invalid_argument(
"Error in UB too large. 0 peaks indexed ");
206 int N = 3 * nPeaksUsed;
207 auto mwkspc = createWorkspace<Workspace2D>(1, N, N);
208 mwkspc->setPoints(0, xRef);
209 mwkspc->setCounts(0, N, 0.0);
210 mwkspc->setCountStandardDeviations(0, N, 1.0);
212 std::string FuncArg =
"name=PeakHKLErrors,PeakWorkspaceName=" +
getPropertyValue(
"PeaksWorkspace") +
"";
214 std::string OptRunNums;
218 std::vector<std::string> ChRunNumList;
219 std::string predChar;
220 for (
auto runNum : RunNumList) {
221 auto it1 = NOoptimizeRuns.begin();
222 for (; it1 != NOoptimizeRuns.end() && *it1 != runNum; ++it1) {
225 if (it1 == NOoptimizeRuns.end()) {
227 OptRunNums += predChar + runNumStr;
229 ChRunNumList.emplace_back(runNumStr);
235 NOoptimizeRuns = RunNumList;
237 std::string message =
"No Goniometer Angles ";
239 message +=
"relative to the tilted Goniometer ";
240 message +=
"will be 'changed'";
243 if (!OptRunNums.empty() && !omitRuns)
244 FuncArg +=
",OptRuns=" + OptRunNums;
248 std::ostringstream oss(std::ostringstream::out);
250 std::ostringstream oss1(std::ostringstream::out);
254 double DegreeTol =
getProperty(
"MaxAngularChange");
255 std::string startConstraint;
257 for (
size_t i = 0; i < RunNumList.size(); i++) {
258 int runNum = RunNumList[i];
261 for (; k < NOoptimizeRuns.size(); k++) {
262 if (NOoptimizeRuns[k] == runNum)
265 if (k >= NOoptimizeRuns.size()) {
266 V3D chiphiomega = ChiPhiOmega[i];
267 oss <<
",chi" << runNum <<
"=" << chiphiomega[0] <<
",phi" << runNum <<
"=" << chiphiomega[1] <<
",omega"
268 << runNum <<
"=" << chiphiomega[2];
270 oss1 << startConstraint << chiphiomega[0] - DegreeTol <<
"<chi" << runNum <<
"<" << chiphiomega[0] + DegreeTol;
271 oss1 <<
"," << chiphiomega[1] - DegreeTol <<
"<phi" << runNum <<
"<" << chiphiomega[1] + DegreeTol;
273 oss1 <<
"," << chiphiomega[2] - DegreeTol <<
"<omega" << runNum <<
"<" << chiphiomega[2] + DegreeTol;
274 startConstraint =
",";
280 V3D sampPos =
V3D(0., 0., 0.);
282 oss <<
",SampleXOffset=" << sampPos.
X() <<
",SampleYOffset=" << sampPos.
Y() <<
",SampleZOffset=" << sampPos.
Z();
283 oss <<
",GonRotx=0.0,GonRoty=0.0,GonRotz=0.0";
285 double maxSampshift =
getProperty(
"MaxSamplePositionChangeMeters");
286 oss1 << startConstraint << sampPos.
X() - maxSampshift <<
"<SampleXOffset<" << sampPos.
X() + maxSampshift <<
","
287 << sampPos.
Y() - maxSampshift <<
"<SampleYOffset<" << sampPos.
Y() + maxSampshift <<
","
288 << sampPos.
Z() - maxSampshift <<
"<SampleZOffset<" << sampPos.
Z() + maxSampshift;
290 oss1 <<
"," << -DegreeTol <<
"<GonRotx<" << DegreeTol <<
"," << -DegreeTol <<
"<GonRoty<" << DegreeTol <<
","
291 << -DegreeTol <<
"<GonRotz<" << DegreeTol;
293 FuncArg += oss.str();
294 std::string Constr = oss1.str();
296 g_log.
debug() <<
"Function argument=" << FuncArg <<
'\n';
297 g_log.
debug() <<
"Constraint argument=" << Constr <<
'\n';
303 fit_alg->setProperty(
"Function", FuncArg);
305 fit_alg->setProperty(
"MaxIterations", 60);
307 fit_alg->setProperty(
"Constraints", Constr);
309 fit_alg->setProperty(
"InputWorkspace", mwkspc);
311 fit_alg->setProperty(
"CreateOutput",
true);
316 std::ostringstream oss3(std::ostringstream::out);
319 oss3 <<
"SampleXOffset=" << sampPos.
X() <<
",SampleYOffset=" << sampPos.
Y() <<
",SampleZOffset=" << sampPos.
Z();
323 if (!(
bool)
getProperty(
"OptimizeGoniometerTilt")) {
327 Ties +=
"GonRotx=0.0,GonRoty=0.0,GonRotz=0.0";
331 fit_alg->setProperty(
"Ties", Ties);
333 fit_alg->setProperty(
"Output",
"out");
335 fit_alg->executeAsChildAlg();
339 double chisq = fit_alg->getProperty(
"OutputChi2overDoF");
340 g_log.
notice() <<
"Fit finished. Status=" << (std::string)fit_alg->getProperty(
"OutputStatus") <<
'\n';
347 g_log.
debug() <<
"Chi2overDof=" << chisq <<
" # Peaks used=" << nPeaksUsed <<
"# fitting parameters =" << nParams
348 <<
" dof=" << (nPeaksUsed - nParams) <<
'\n';
352 double sigma = sqrt(chisq);
354 std::string OutputStatus = fit_alg->getProperty(
"OutputStatus");
355 g_log.
notice() <<
"Output Status=" << OutputStatus <<
'\n';
359 setProperty(
"OutputNormalisedCovarianceMatrixOptX",
362 if (chisq < 0 || chisq != chisq)
366 std::map<std::string, double> Results;
367 for (
int prm = 0; prm < static_cast<int>(RRes->rowCount()); ++prm) {
368 std::string namee = RRes->getRef<std::string>(
"Name", prm);
370 std::string start = namee.substr(0, 3);
371 if (start !=
"chi" && start !=
"phi" && start !=
"ome" && start !=
"Sam" && start !=
"Gon")
374 double value = RRes->getRef<
double>(
"Value", prm);
375 Results[namee] =
value;
378 double v =
sigma * RRes->getRef<
double>(
"Error", prm);
379 RRes->getRef<
double>(
"Error", prm) = v;
387 V3D newSampPos(Results[
"SampleXOffset"], Results[
"SampleYOffset"], Results[
"SampleZOffset"]);
389 auto &componentInfo = outPeaks->mutableComponentInfo();
397 std::map<int, Matrix<double>> MapRunNum2GonMat;
398 std::string OptRun2 =
"/" + OptRunNums +
"/";
401 UBinv = outPeaks->sample().getOrientedLattice().getUB();
404 for (
int i = 0; i < outPeaks->getNumberPeaks(); ++i) {
405 auto &peak = outPeaks->getPeak(i);
406 peak.setSamplePos(peak.getSamplePos() + newSampPos);
407 int RunNum = peak.getRunNumber();
410 if (RunNum == prevRunNum || MapRunNum2GonMat.find(RunNum) != MapRunNum2GonMat.end())
411 GonMatrix = MapRunNum2GonMat[RunNum];
412 else if (OptRun2.find(
"/" + RunNumStr +
"/") < OptRun2.size() - 2) {
414 double chi = Results[
"chi" + RunNumStr];
415 double phi = Results[
"phi" + RunNumStr];
416 double omega = Results[
"omega" + RunNumStr];
425 GonMatrix = GonTilt * uniGonio.
getR();
426 MapRunNum2GonMat[RunNum] = GonMatrix;
428 GonMatrix = GonTilt * peak.getGoniometerMatrix();
429 MapRunNum2GonMat[RunNum] = GonMatrix;
432 peak.setGoniometerMatrix(GonMatrix);
433 V3D hkl = UBinv * peak.getQSampleFrame();
440 if (MapRunNum2GonMat.size() == 1)
442 Matrix<double> GonMatrix = MapRunNum2GonMat[outPeaks->getPeak(0).getRunNumber()];
444 outPeaks->mutableRun().setGoniometer(Gon,
false);
449 g_log.
notice() <<
"Number indexed after optimization= " << nIndexed <<
" at tolerance = " << HKLintOffsetMax <<
'\n';