Mantid
Loading...
Searching...
No Matches
IntegratePeakTimeSlices.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7/*
8 * IntegratePeakTimeSlices.cpp
9 *
10 * Created on: May 5, 2011
11 * Author: ruth
12 *
13 *
14 *
15 */
22#include "MantidAPI/IFunction.h"
25
26#include "MantidHistogramData/BinEdges.h"
27#include "MantidHistogramData/CountStandardDeviations.h"
28#include "MantidHistogramData/Counts.h"
29#include "MantidHistogramData/Points.h"
30
31#include <boost/math/special_functions/round.hpp>
32#include <utility>
33
34using namespace Mantid::Kernel;
35using namespace Mantid::API;
36using namespace Mantid::DataObjects;
37using namespace Mantid::Geometry;
38using namespace Mantid::HistogramData;
39using namespace std;
40namespace Mantid::Crystal {
41
42DECLARE_ALGORITHM(IntegratePeakTimeSlices)
43
44// Attr, m_AttributeValues, and StatBase indicies
45#define IStartRow 0
46#define IStartCol 1
47#define INRows 2
48#define INCol 3
49#define ISSIxx 4
50#define ISSIyy 5
51#define ISSIxy 6
52#define ISSxx 7
53#define ISSyy 8
54#define ISSxy 9
55#define ISSIx 10
56#define ISSIy 11
57#define ISSx 12
58#define ISSy 13
59#define IIntensities 14
60#define ISS1 15
61#define IVariance 16
62#define ITotBoundary 17
63#define INBoundary 18
64#define IVarBoundary 19
65#define NAttributes 20
66
67// Parameter indicies
68#define IBACK 0
69#define ITINTENS 1
70#define IXMEAN 2
71#define IYMEAN 3
72#define IVXX 4
73#define IVYY 5
74#define IVXY 6
75// TODO: Edge Peaks-Return NoPeak(Intensity=0,variance=0) if any center on any
76// slice is out of bounds
77// TODO: Calc ratio for edge peaks, should use the slant of bivariate normal
78// instead of assuming
79// distribution axes are lined up with the row and col vectors
80#define NParameters 7
81
82namespace {
83// # std sigs 0 .25 .5 .75 1 1.25 1.5 2 2.5
84const double probs[9] = {.5f, .5987f, .6915f, .7734f, .8413f, .8944f, .9322f, .9599f, .9772f};
85
86const int MinRowColSpan = 6;
87const int MaxRowColSpan = 36;
88const int MinTimeSpan = 3;
89const double NeighborhoodRadiusDivPeakRadius = 1.5;
90const double MaxNeighborhoodRadius = 10;
91const double NStdDevPeakSpan = 2;
92const double MaxGoodRatioFitvsExpIntenisites = 2.5;
93const double MinGoodRatioFitvsExpIntenisites = .25;
94const double MinGoodIoverSigI = 3.0;
95const double MinVariationInXYvalues = .6; // Peak spans one pixel only
96const double MaxCorrCoeffinXY = .9; // otherwise all data on one line
97} // namespace
98
100 : Algorithm(), m_R0(-1), m_ROW(0.), m_COL(0.), m_cellWidth(0.), m_cellHeight(0.), m_NROWS(0), m_NCOLS(0) {
101 this->deprecatedDate("2024-10-02");
102 m_EdgePeak = false;
103 m_NeighborIDs = new int[3];
104 m_NeighborIDs[0] = 3;
105 m_NeighborIDs[1] = 2;
106 m_AttributeNames[0] = "StartRow";
107 m_AttributeNames[1] = "StartCol";
108 m_AttributeNames[2] = "NRows";
109 m_AttributeNames[3] = "NCols";
110 m_AttributeNames[4] = "SSIxx";
111 m_AttributeNames[5] = "SSIyy";
112 m_AttributeNames[6] = "SSIxy";
113 m_AttributeNames[7] = "SSxx";
114 m_AttributeNames[8] = "SSyy";
115 m_AttributeNames[9] = "SSxy";
116 m_AttributeNames[10] = "SSIx";
117 m_AttributeNames[11] = "SSIy";
118 m_AttributeNames[12] = "SSx";
119 m_AttributeNames[13] = "SSy";
120 m_AttributeNames[14] = "Intensities";
121 m_AttributeNames[15] = " SS1";
122 m_AttributeNames[16] = "Variance";
123 m_AttributeNames[17] = "TotBoundary";
124 m_AttributeNames[18] = "NBoundary";
125 m_AttributeNames[19] = "VarianceBoundary";
126
127 m_ParameterNames[0] = "Background";
128 m_ParameterNames[1] = "Intensity";
129 m_ParameterNames[2] = "Mcol";
130 m_ParameterNames[3] = "Mrow";
131 m_ParameterNames[4] = "SScol";
132 m_ParameterNames[5] = "SSrow";
133 m_ParameterNames[6] = "SSrc";
134
135 std::fill(m_ParameterValues.begin(), m_ParameterValues.end(), 0.0);
136}
137
138double SQRT(double v) {
139 if (v < 0)
140 return -1;
141 return sqrt(v);
142}
145
147 declareProperty(std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input),
148 "A 2D workspace with X values of time of flight");
149
150 declareProperty(std::make_unique<WorkspaceProperty<TableWorkspace>>("OutputWorkspace", "", Direction::Output),
151 "Name of the output table workspace with Log info");
152
154 "Workspace of Peaks");
155
156 declareProperty("PeakIndex", 0, "Index of peak in PeaksWorkspace to integrate");
157
158 declareProperty("PeakQspan", .06, "Max magnitude of Q of Peak to Q of Peak Center, where mod(Q)=1/d");
159
160 declareProperty("CalculateVariances", true, "Calc (co)variances given parameter values versus fit (co)Variances ");
161
162 declareProperty("Ties", "", "Tie parameters(Background,Intensity, Mrow,...) to values/formulas.");
163
164 declareProperty("NBadEdgePixels", 0, "Number of bad Edge Pixels");
165
166 declareProperty("Intensity", 0.0, "Peak Integrated Intensity", Direction::Output);
167
168 declareProperty("SigmaIntensity", 0.0, "Peak Integrated Intensity Error", Direction::Output);
169}
170
181 time_t seconds1;
182
183 seconds1 = time(nullptr);
184
185 double dQ = getProperty("PeakQspan");
186
187 g_log.debug("------------------Start Peak Integrate-------------------");
188
189 if (dQ <= 0) {
190 g_log.error("Negative PeakQspans are not allowed. Use .17/G where G is the "
191 "max unit cell length");
192 throw std::runtime_error("Negative PeakQspans are not allowed in IntegratePeakTimeSlices");
193 }
194
195 MatrixWorkspace_const_sptr inpWkSpace = getProperty("InputWorkspace");
196 if (!inpWkSpace) {
197 g_log.error("Improper Input Workspace");
198 throw std::runtime_error("Improper Input Workspace in IntegratePeakTimeSlices");
199 }
200
201 PeaksWorkspace_sptr peaksW;
202 peaksW = getProperty("Peaks");
203 if (!peaksW) {
204 g_log.error("Improper Peaks Input");
205 throw std::runtime_error("Improper Peaks Input");
206 }
207
208 int indx = getProperty("PeakIndex");
209
210 Peak const &peak = peaksW->getPeak(indx);
211
212 //------------------------------- Get Panel
213 //--------------------------------------
214 std::shared_ptr<const Geometry::IComponent> panel_const =
215 peak.getInstrument()->getComponentByName(peak.getBankName());
216
217 std::shared_ptr<Geometry::IComponent> panel = std::const_pointer_cast<Geometry::IComponent>(panel_const);
218
219 if (!panel || !panel_const) {
220 g_log.error("Cannot get panel for a peak");
221 throw std::runtime_error("Cannot get panel for a peak");
222 }
223
224 BoundingBox box;
225 panel->getBoundingBox(box);
226
227 if (!box.isPointInside(peak.getDetPos())) {
228 g_log.error("Detector pixel is NOT inside the Peaks Bank");
229 throw std::runtime_error("Detector pixel is NOT inside the Peaks Bank");
230 }
231
233
234 g_log.debug() << " Peak Index " << indx << '\n';
235
236 double TotVariance = 0;
237 double TotIntensity = 0;
238 double lastRow = m_ROW;
239 double Row0 = lastRow;
240 double lastCol = m_COL;
241 double Col0 = lastCol;
242
243 // For quickly looking up workspace index from det id
244 m_wi_to_detid_map = inpWkSpace->getDetectorIDToWorkspaceIndexMap();
245
246 TableWorkspace_sptr TabWS = std::make_shared<TableWorkspace>(0);
247
248 //----------------------------- get Peak extents
249 //------------------------------
250 try {
251 string spec_idList;
252 int detID = peak.getDetectorID();
253
254 // Find the workspace index for this detector ID
255 detid2index_map::const_iterator it = m_wi_to_detid_map.find(detID);
256 size_t wsIndx = (it->second);
257
258 double R = CalculatePositionSpan(peak, dQ) / 2;
259
260 R = min<double>(MaxRowColSpan * max<double>(m_cellWidth, m_cellHeight), R);
261 R = max<double>(MinRowColSpan * max<double>(m_cellWidth, m_cellHeight), R);
262
263 R = 2 * R; // Gets a few more background cells.
264 int Chan;
265
266 const auto &X = inpWkSpace->x(wsIndx);
267 int dChan = CalculateTimeChannelSpan(peak, dQ, X, int(wsIndx), Chan);
268
269 dChan = max<int>(dChan, MinTimeSpan);
270
271 double Centy = Row0;
272 double Centx = Col0;
273 IDetector_const_sptr CenterDet = peak.getDetector();
274
275 double neighborRadius; // last radius for finding neighbors
276
277 neighborRadius = min<double>(MaxNeighborhoodRadius, NeighborhoodRadiusDivPeakRadius * R);
278 auto Nneighbors = static_cast<int>(neighborRadius * neighborRadius / m_cellWidth / m_cellHeight * 4);
279
280 Nneighbors = min<int>(Nneighbors, static_cast<int>(inpWkSpace->getNumberHistograms()) - 2);
281 delete[] m_NeighborIDs;
282
283 m_NeighborIDs = new int[Nneighbors + 2];
284 m_NeighborIDs[0] = Nneighbors + 2;
285 m_NeighborIDs[1] = 2;
286 Kernel::V3D Cent = (m_center + m_xvec * (Centx - m_COL) + m_yvec * (Centy - m_ROW));
287
288 getNeighborPixIDs(panel, Cent, neighborRadius, m_NeighborIDs);
289
290 if (m_NeighborIDs[1] < 10) {
291 g_log.error("Not enough neighboring pixels to fit ");
292 throw std::runtime_error("Not enough neighboring pixels to fit ");
293 }
294 int NBadEdgeCells = getProperty("NBadEdgePixels");
295 int MaxChan = -1;
296 double MaxCounts = -1;
297
298 // --------------- Find Time Chan with max counts----------------
299 for (int dir = 1; dir > -2; dir -= 2) {
300 bool done = false;
301 for (int t = 0; t < dChan && !done; t++)
302 if (dir < 0 && t == 0) {
303 Centy = Row0;
304 Centx = Col0;
305 } else if (Chan + dir * t < 0 || Chan + dir * t >= static_cast<int>(X.size()))
306 done = true;
307 else {
308
309 int NN = m_NeighborIDs[1];
310 MatrixWorkspace_sptr Data = WorkspaceFactory::Instance().create(std::string("Workspace2D"), 3, NN, NN);
311
312 auto XXX = std::make_shared<DataModeHandler>(R, R, Centy, Centx, m_cellWidth, m_cellHeight,
313 getProperty("CalculateVariances"), NBadEdgeCells,
314 m_NCOLS - NBadEdgeCells, NBadEdgeCells, m_NROWS - NBadEdgeCells);
315 m_AttributeValues = XXX;
316 XXX->setCurrentRadius(R);
317
318 SetUpData1(Data, inpWkSpace, Chan + dir * t, Chan + dir * t, R, CenterDet->getPos(), spec_idList);
319
320 if (m_AttributeValues->StatBaseVals(ISSIxx) > 0) {
321 if (m_AttributeValues->StatBaseVals(IIntensities) > MaxCounts) {
322 MaxCounts = m_AttributeValues->StatBaseVals(IIntensities);
323 MaxChan = Chan + dir * t;
324 }
325 if (m_AttributeValues->StatBaseVals(IIntensities) > 0) {
326 Centx = m_AttributeValues->StatBaseVals(ISSIx) / m_AttributeValues->StatBaseVals(IIntensities);
327 Centy = m_AttributeValues->StatBaseVals(ISSIy) / m_AttributeValues->StatBaseVals(IIntensities);
328 } else
329 done = true;
330 } else
331 done = true;
332
333 if (t >= 3 && (m_AttributeValues->StatBaseVals(IIntensities) < MaxCounts / 2.0) && MaxCounts >= 0)
334 done = true;
335 }
336 }
337 if (MaxChan > 0)
338 Chan = MaxChan;
339
340 g_log.debug() << " largest Channel,Radius,m_cellWidth,m_cellHeight = " << Chan << " " << R << " " << m_cellWidth
341 << " " << m_cellHeight << '\n';
342
343 if (R < MinRowColSpan / 2 * max<double>(m_cellWidth, m_cellHeight) || dChan < MinTimeSpan) {
344 g_log.error("Not enough rows and cols or time channels ");
345 throw std::runtime_error("Not enough rows and cols or time channels ");
346 }
347
349
350 //------------------------------------- Start the Integrating
351 //-------------------------------
352 double time;
353 int ncells;
354
355 Mantid::API::Progress prog(this, 0.0, 1.0, dChan);
356
357 // Set from attributes replace by m_R0
358 m_R0 = -1;
359 int LastTableRow = -1;
360 auto origAttributeList = std::make_shared<DataModeHandler>();
361 auto lastAttributeList = std::make_shared<DataModeHandler>();
362
363 for (int dir = 1; dir >= -1; dir -= 2) {
364 bool done = false;
365
366 for (int chan = 0; chan < dChan && !done; chan++)
367 if (dir < 0 && chan == 0) {
368 lastRow = Row0;
369 lastCol = Col0;
370 lastAttributeList = origAttributeList;
371 if (TabWS->rowCount() > 0)
372 LastTableRow = 0;
373
374 } else if (Chan + dir * chan < 0 || Chan + dir * chan >= static_cast<int>(X.size()))
375 done = true;
376 else {
377
378 int xchan = Chan + dir * chan;
379
380 size_t topIndex = xchan + 1;
381 if (topIndex >= X.size())
382 topIndex = X.size() - 1;
383
384 time = (X[xchan] + X[topIndex]) / 2.0;
385
386 double Radius = R;
387
388 if (m_R0 > 0)
389 Radius = m_R0;
390
392 WorkspaceFactory::Instance().create(std::string("Workspace2D"), 3, m_NeighborIDs[1], m_NeighborIDs[1]);
393
394 g_log.debug() << " A:chan=" << xchan << " time=" << time << " Radius=" << Radius << "row= " << lastRow
395 << " col=" << lastCol << '\n';
396
397 SetUpData(Data, inpWkSpace, panel, xchan, xchan, lastCol, lastRow, Cent, neighborRadius, Radius, spec_idList);
398
399 m_AttributeValues->setTime(time);
400
401 // if( dir==1 && chan ==0)
402 // origAttributeList= m_AttributeValues;
403
404 ncells = static_cast<int>(m_AttributeValues->StatBaseVals(ISS1));
405
406 std::vector<double> params;
407 std::vector<double> errs;
408 std::vector<std::string> names;
409
410 if (m_AttributeValues->StatBaseVals(ISSIxx) > 0 &&
411 m_AttributeValues->IsEnoughData(m_ParameterValues.data(), g_log) && m_ParameterValues[ITINTENS] > 0) {
412 double chisqOverDOF;
413
414 Fit(Data, chisqOverDOF, done, names, params, errs, lastRow, lastCol, neighborRadius);
415
416 if (!done) // Bivariate error happened
417 {
418
419 if (isGoodFit(params, errs, names, chisqOverDOF)) {
420 LastTableRow = UpdateOutputWS(TabWS, dir, xchan, params, errs, names, chisqOverDOF,
421 m_AttributeValues->time, spec_idList);
422
423 double TotSliceIntensity = m_AttributeValues->StatBaseVals(IIntensities);
424 double TotSliceVariance = m_AttributeValues->StatBaseVals(IVariance);
425
426 updatePeakInformation(params, errs, names, TotVariance, TotIntensity, TotSliceIntensity,
427 TotSliceVariance, chisqOverDOF, ncells);
428
429 lastAttributeList = m_AttributeValues;
430
431 if (dir == 1 && chan == 0)
432 origAttributeList = lastAttributeList;
433 } else
434
435 done = true;
436 }
437
438 } else //(!IsEnoughData() || ParameterValues[ITINTENS] <= 0
439 {
440 done = true;
441 }
442
443 if (done) // try to merge
444 {
445 done = false;
446
447 int chanMin, chanMax;
448 if ((dir == 1 && chan == 0) || lastAttributeList->CellHeight <= 0) {
449 chanMin = xchan;
450 chanMax = xchan + 1;
451 if (dir < 0)
452 chanMax++;
453 auto XXX = std::make_shared<DataModeHandler>(*m_AttributeValues);
454 m_AttributeValues = XXX;
455 if (!X.empty())
456 m_AttributeValues->setTime((X[chanMax] + X[chanMin]) / 2.0);
457
458 } else // lastAttributeList exists
459
460 {
461 chanMin = std::min<int>(xchan, xchan - dir);
462 chanMax = chanMin + 1;
463 if (lastAttributeList->case4)
464 chanMax++;
465
466 auto XXX = std::make_shared<DataModeHandler>(*lastAttributeList);
467 m_AttributeValues = XXX;
468
469 m_AttributeValues->setTime((time + m_AttributeValues->time) / 2.0);
470 }
471
472 if (updateNeighbors(panel, m_AttributeValues->getCurrentCenter(), Cent,
473 m_AttributeValues->getCurrentRadius(), neighborRadius))
474 Cent = m_AttributeValues->getCurrentCenter();
475
476 Data =
477 WorkspaceFactory::Instance().create(std::string("Workspace2D"), 3, m_NeighborIDs[1], m_NeighborIDs[1]);
478
479 SetUpData1(Data, inpWkSpace, chanMin, chanMax, m_AttributeValues->getCurrentRadius(),
480 m_AttributeValues->getCurrentCenter(), spec_idList);
481
482 double chisqOverDOF;
483
484 g_log.debug("Try Merge 2 time slices");
485 if (m_AttributeValues->StatBaseVals(ISSIxx) >= 0 &&
486 m_AttributeValues->IsEnoughData(m_ParameterValues.data(), g_log))
487
488 Fit(Data, chisqOverDOF, done, names, params, errs, lastRow, lastCol, neighborRadius);
489 else
490 chisqOverDOF = -1;
491
492 if (!done && isGoodFit(params, errs, names, chisqOverDOF)) {
493
494 if (LastTableRow >= 0 && LastTableRow < static_cast<int>(TabWS->rowCount()))
495 TabWS->removeRow(LastTableRow);
496 else
497 LastTableRow = -1;
498
499 LastTableRow = UpdateOutputWS(TabWS, dir, (chanMin + chanMax) / 2.0, params, errs, names, chisqOverDOF,
500 m_AttributeValues->time, spec_idList);
501
502 if (lastAttributeList->lastISAWVariance > 0 && lastAttributeList->CellHeight > 0) {
503 TotIntensity -= lastAttributeList->lastISAWIntensity;
504 TotVariance -= lastAttributeList->lastISAWVariance;
505 }
506
507 double TotSliceIntensity = m_AttributeValues->StatBaseVals(IIntensities);
508
509 double TotSliceVariance = m_AttributeValues->StatBaseVals(IVariance);
510
511 updatePeakInformation(params, errs, names, TotVariance, TotIntensity, TotSliceIntensity, TotSliceVariance,
512 chisqOverDOF, static_cast<int>(m_AttributeValues->StatBaseVals(ISS1)));
513
514 // lastAttributeList= m_AttributeValues;
515
516 if (dir == 1 && (chan == 0 || chan == 1)) {
517 m_AttributeValues->case4 = true;
518 origAttributeList = m_AttributeValues;
519 } else
520 LastTableRow = -1;
521
522 } else {
523 auto XXX = std::make_shared<DataModeHandler>();
524 lastAttributeList = XXX;
525 }
526 done = true;
527 }
528
529 // Get ready for the next round
530 Data.reset();
531
532 if (!done) {
533
534 // Now set up the center for this peak
535 int i = findNameInVector("Mrow", names);
536 if (i < 0) {
537 throw std::runtime_error("Inconsistency found in algorithm "
538 "execution. The index for the parameter "
539 "Mrow is negative.");
540 }
541
542 lastRow = boost::math::iround(params[i]);
543 i = findNameInVector("Mcol", names);
544 if (i >= 0)
545 lastCol = boost::math::iround(params[i]);
546 prog.report();
547
548 } else if (dir > 0)
549 prog.report(dChan / 2);
550 else
551 prog.report(dChan);
552
553 params.clear();
554 errs.clear();
555 names.clear();
556 }
557 }
558
559 } catch (std::exception &EE1) {
560 std::cout << "Error in main reason=" << EE1.what() << '\n';
561
562 throw std::runtime_error(" Error IntegratePeakTimeSlices:" + std::string(EE1.what()));
563 } catch (std::string &mess) {
564 throw std::runtime_error("Error IntegratePeakTimeSlices:" + mess);
565
566 } catch (...) {
567 throw std::runtime_error("Error IntegratePeakTimeSlices:");
568 }
569
570 try {
571
572 setProperty("OutputWorkspace", TabWS);
573
574 setProperty("Intensity", TotIntensity);
575 setProperty("SigmaIntensity", SQRT(TotVariance));
576 time_t seconds2;
577
578 seconds2 = time(nullptr);
579 double dif = difftime(seconds2, seconds1);
580 g_log.debug() << "Finished Integr peak number " << indx << " in " << dif << " seconds\n";
581
582 } catch (std::exception &ss) {
583
584 std::cout << "Error occurred XX " << ss.what() << '\n';
585 throw std::runtime_error(ss.what());
586 }
587}
588
598bool IntegratePeakTimeSlices::getNeighborPixIDs(const std::shared_ptr<Geometry::IComponent> &comp,
599 const Kernel::V3D &Center, double &Radius, int *&ArryofID) {
600
601 int N = ArryofID[1];
602 int MaxN = ArryofID[0];
603
604 if (N >= MaxN)
605 return false;
606
608 comp->getBoundingBox(box);
609
610 double minx = Center.X() - Radius;
611 double miny = Center.Y() - Radius;
612 double minz = Center.Z() - Radius;
613 double maxx = Center.X() + Radius;
614 double maxy = Center.Y() + Radius;
615 double maxz = Center.Z() + Radius;
616
617 if (box.xMin() >= maxx)
618 return true;
619
620 if (box.xMax() <= minx)
621 return true;
622 ;
623
624 if (box.yMin() >= maxy)
625 return true;
626
627 if (box.yMax() <= miny)
628 return true;
629
630 if (box.zMin() >= maxz)
631 return true;
632
633 if (box.zMax() <= minz)
634 return true;
635 ;
636
637 auto det = std::dynamic_pointer_cast<Geometry::Detector>(comp);
638
639 if (det) {
640 V3D pos = det->getPos() - Center;
641 if (pos.X() * pos.X() + pos.Y() * pos.Y() + pos.Z() * pos.Z() < Radius * Radius) {
642 ArryofID[N] = det->getID();
643 N++;
644 ArryofID[1] = N;
645 }
646 return true;
647 }
648
649 auto Assembly = std::dynamic_pointer_cast<const Geometry::ICompAssembly>(comp);
650
651 if (!Assembly)
652 return true;
653
654 bool b = true;
655
656 for (int i = 0; i < Assembly->nelements() && b; i++)
657 b = getNeighborPixIDs(Assembly->getChild(i), Center, Radius, ArryofID);
658
659 return b;
660}
661
670bool IntegratePeakTimeSlices::updateNeighbors(const std::shared_ptr<Geometry::IComponent> &comp, const V3D &CentPos,
671 const V3D &oldCenter, double NewRadius, double &neighborRadius) {
672 double DD = (CentPos - oldCenter).norm();
673 bool changed = false;
674 if (DD + NewRadius > neighborRadius) {
675 auto NN = int(NStdDevPeakSpan * NeighborhoodRadiusDivPeakRadius * NewRadius / m_cellWidth * NStdDevPeakSpan *
676 NeighborhoodRadiusDivPeakRadius * NewRadius / m_cellHeight);
677 if (m_NeighborIDs[0] < NN) {
678 delete[] m_NeighborIDs;
679 m_NeighborIDs = new int[NN + 2];
680 m_NeighborIDs[0] = NN + 2;
681 }
682 m_NeighborIDs[1] = 2;
683 neighborRadius = NeighborhoodRadiusDivPeakRadius * NewRadius;
684
685 getNeighborPixIDs(comp, CentPos, neighborRadius, m_NeighborIDs);
686 changed = true;
687
688 } else // big enough neighborhood so
689 neighborRadius -= DD;
690
691 return changed;
692}
693
704double IntegratePeakTimeSlices::CalculatePositionSpan(Peak const &peak, const double dQ) {
705
706 try {
707 double Q = 0, ScatAngle = 0, dScatAngle = 0, DetSpan = 0;
708
709 Q = peak.getQLabFrame().norm();
711 const Geometry::IComponent_const_sptr sample = instr->getSample();
712 V3D pos = peak.getDetPos() - sample->getPos();
713
714 ScatAngle = acos(pos.Z() / pos.norm());
715
716 dScatAngle = 2 * dQ / Q * tan(ScatAngle / 2);
717
718 DetSpan = pos.norm() * dScatAngle; // s=r*theta
719
720 DetSpan = fabs(DetSpan);
721
722 // IDetector_sptr det = peak.getDetector();
723
724 return DetSpan;
725
726 } catch (std::exception &s) {
727 std::cout << "err in getNRowsCols, reason=" << s.what() << '\n';
728 return 0;
729 }
730}
731
746int IntegratePeakTimeSlices::CalculateTimeChannelSpan(Geometry::IPeak const &peak, const double dQ, const HistogramX &X,
747 const int specNum, int &Centerchan) {
748 UNUSED_ARG(specNum);
749 double Q = peak.getQLabFrame().norm(); // getQ( peak)/2/M_PI;
750
751 double time = peak.getTOF();
752 double dtime = dQ / Q * time;
753 int chanCenter = findTimeChannel(X, time);
754
755 Centerchan = chanCenter;
756 int chanLeft = findTimeChannel(X, time - dtime);
757 int chanRight = findTimeChannel(X, time + dtime);
758 int dchan = abs(chanCenter - chanLeft);
759
760 if (abs(chanRight - chanCenter) > dchan)
761 dchan = abs(chanRight - chanCenter);
762
763 dchan = max<int>(3, dchan);
764
765 return dchan + 5; // heuristic should be a lot more
766}
767
784void IntegratePeakTimeSlices::FindPlane(V3D &center, V3D &xvec, V3D &yvec, double &ROW, double &COL, int &NROWS,
785 int &NCOLS, double &pixWidthx, double &pixHeighty,
786 DataObjects::Peak const &peak) const {
787
788 NROWS = NCOLS = -1;
790 V3D detPos = det->getPos();
791
792 center.setX(detPos.X());
793 center.setY(detPos.Y());
794 center.setZ(detPos.Z());
795
796 std::shared_ptr<const Detector> dett = std::dynamic_pointer_cast<const Detector>(det);
797
798 pixWidthx = dett->getWidth();
799 pixHeighty = dett->getHeight();
800
801 Kernel::Quat Qt = dett->getRotation();
802 V3D yaxis0(0.0, 1.0, 0.0);
803
804 Qt.rotate(yaxis0);
805 yaxis0.normalize();
806
807 V3D xaxis0(1, 0, 0);
808 Qt.rotate(xaxis0);
809 xaxis0.normalize();
810
811 xvec.setX(xaxis0.X());
812 xvec.setY(xaxis0.Y());
813 xvec.setZ(xaxis0.Z());
814 yvec.setX(yaxis0.X());
815 yvec.setY(yaxis0.Y());
816 yvec.setZ(yaxis0.Z());
817 ROW = peak.getRow();
818 COL = peak.getCol();
820 if (!inst)
821 throw std::invalid_argument("No instrument for peak");
822 std::shared_ptr<const IComponent> panel = inst->getComponentByName(peak.getBankName());
823
824 std::shared_ptr<const RectangularDetector> ddet = std::dynamic_pointer_cast<const RectangularDetector>(panel);
825
826 if (ddet) {
827 std::pair<int, int> CR = ddet->getXYForDetectorID(det->getID());
828 ROW = CR.second;
829 COL = CR.first;
830 pixWidthx = ddet->xstep();
831 pixHeighty = ddet->ystep();
832
833 NROWS = ddet->ypixels();
834 NCOLS = ddet->xpixels();
835
836 return;
837 }
838 // Get NROWS and NCOLS for other panels
839 NROWS = NCOLS = -1;
840
841 if (!panel)
842 return;
843 std::shared_ptr<const Component> compPanel = std::dynamic_pointer_cast<const Component>(panel);
844 std::shared_ptr<IComponent> panel1(compPanel->base()->clone());
845 BoundingBox B;
846
847 Quat rot = panel1->getRotation();
848
849 rot.inverse();
850
851 panel1->rotate(rot);
852
853 panel1->getBoundingBox(B);
854
855 NROWS = boost::math::iround((B.yMax() - B.yMin()) / pixHeighty);
856 NCOLS = boost::math::iround((B.xMax() - B.xMin()) / pixWidthx);
857}
858
868void IntegratePeakTimeSlices::updateStats(const double intensity, const double variance, const double row,
869 const double col, std::vector<double> &StatBase) {
870
871 StatBase[ISSIxx] += col * col * intensity;
872 StatBase[ISSIyy] += intensity * row * row;
873 StatBase[ISSIxy] += intensity * row * col;
874 StatBase[ISSxx] += col * col;
875 StatBase[ISSyy] += row * row;
876 StatBase[ISSxy] += row * col;
877 StatBase[ISSIx] += intensity * col;
878 StatBase[ISSIy] += intensity * row;
879 StatBase[ISSx] += col;
880 StatBase[ISSy] += row;
881 StatBase[IIntensities] += intensity;
882 StatBase[IVariance] += variance;
883 StatBase[ISS1] += 1;
884}
885
896std::vector<double> DataModeHandler::InitValues(double Varx, double Vary, double b) {
897 std::vector<double> Res(7);
898
899 Res[IVXX] = Varx;
900 Res[IVYY] = Vary;
901 Res[IVXY] = 0;
902 auto nCells = static_cast<int>(StatBase[ISS1]);
903 double Den = StatBase[IIntensities] - b * nCells;
904 Res[IXMEAN] = (StatBase[ISSIx] - b * StatBase[ISSx]) / Den;
905 Res[IYMEAN] = (StatBase[ISSIy] - b * StatBase[ISSy]) / Den;
906 Res[IBACK] = b;
907 Res[ITINTENS] = StatBase[IIntensities] - b * nCells;
908
909 //---- Is Edge Cell ???-------
910 double NstdX = 4 * (currentRadius / CellWidth - EdgeX) / sqrt(Varx);
911 double NstdY = 4 * (currentRadius / CellHeight - EdgeY) / sqrt(Vary);
912 double sigx = 1;
913 double sigy = 1;
914 if (NstdX < 0)
915 sigx = -1;
916 if (NstdY < 0)
917 sigy = -1;
918
919 double x = 1;
920 if (sigy * NstdY < 7 && sigy * NstdY >= 0) // is close to row edge
921 {
922 x = probs[std::lround(sigy * NstdY)];
923 if (sigy < 0)
924 x = 1 - x;
925 double My2 = StatBase[IStartRow];
926 if (Res[IYMEAN] - My2 > My2 + StatBase[INRows] - Res[IYMEAN])
927 My2 += StatBase[INRows];
928 Res[IYMEAN] = Res[IYMEAN] * x + (1 - x) * My2;
929 }
930 double x1 = 1;
931 if (sigx * NstdX < 7 && sigx * NstdX > 0) // is close to x edge
932 {
933 x1 = probs[std::lround(sigx * NstdX)];
934 if (sigx < 0)
935 x1 = 1 - x1;
936 double Mx2 = StatBase[IStartCol];
937 if (Res[IXMEAN] - Mx2 > Mx2 + StatBase[INCol] - Res[IXMEAN])
938 Mx2 += StatBase[INCol];
939 Res[IXMEAN] = Res[IXMEAN] * x1 + (1 - x1) * Mx2;
940 }
941 Res[ITINTENS] /= x * x1;
942
943 return Res;
944}
945
953std::vector<double> DataModeHandler::GetParams(double b) {
954
955 auto nCells = static_cast<int>(StatBase[ISS1]);
956 double Den = StatBase[IIntensities] - b * nCells;
957 double Varx, Vary;
958
959 Varx = VarxHW;
960 Vary = VaryHW;
961
962 double Rx = lastRCRadius / CellWidth - EdgeX;
963 double Ry = lastRCRadius / CellHeight - EdgeY;
964 if (Varx <= 0)
966
967 if (Vary <= 0)
969 // Use
970 if (Rx * Rx < 4 * Varx || Ry * Ry < 4 * Vary) {
971 return InitValues(Varx, Vary, b);
972 }
973 if (Den < 0)
974 return std::vector<double>();
975
976 double Mx = StatBase[ISSIx] - b * StatBase[ISSx];
977 double My = StatBase[ISSIy] - b * StatBase[ISSy];
978
979 double Sxx = (StatBase[ISSIxx] - b * StatBase[ISSxx] - Mx * Mx / Den) / Den;
980 double Syy = (StatBase[ISSIyy] - b * StatBase[ISSyy] - My * My / Den) / Den;
981 double Sxy = (StatBase[ISSIxy] - b * StatBase[ISSxy] - Mx * My / Den) / Den;
982
983 double Intensity = StatBase[IIntensities] - b * nCells;
984 double col = Mx / Den;
985 double row = My / Den;
986 std::vector<double> Result(7);
987 Result[IBACK] = b;
988 Result[ITINTENS] = Intensity;
989 Result[IXMEAN] = col;
990 Result[IYMEAN] = row;
991 Result[IVXX] = Sxx;
992 Result[IVYY] = Syy;
993 Result[IVXY] = Sxy;
994
995 return Result;
996}
997
1004bool DataModeHandler::setStatBase(std::vector<double> const &statBase)
1005
1006{
1007 auto nBoundaryCells = static_cast<int>(statBase[INBoundary]);
1008 this->StatBase = statBase;
1009 double b = 0;
1010 if (nBoundaryCells > 0) {
1011 double TotBoundaryIntensities = statBase[ITotBoundary];
1012 b = TotBoundaryIntensities / nBoundaryCells;
1013 }
1014
1015 auto nCells = static_cast<int>(statBase[ISS1]);
1016 double Den = statBase[IIntensities] - b * nCells;
1017 int k = 0;
1018 while (Den <= 0 && b != 0) {
1019 b = b * .7;
1020 Den = statBase[IIntensities] - b * nCells;
1021
1022 if (k < 8)
1023 k++;
1024 else
1025 b = 0;
1026 }
1027
1028 double Varx, Vary;
1029 Varx = statBase[INCol] / 7; // Range = 3.5 standard deviations
1030 Vary = statBase[INRows] / 7;
1031 Varx *= Varx;
1032 Vary *= Vary;
1033
1034 double Rx = lastRCRadius / CellWidth - EdgeX;
1035 double Ry = lastRCRadius / CellHeight - EdgeY;
1036 if (CellWidth > 0 && currentRadius > 0 && lastCol > 0 && lastRow > 0)
1037 if (Rx * Rx < 4 * std::max(Varx, VarxHW) || HalfWidthAtHalfHeightRadius < 0 ||
1038 Ry * Ry < 4 * std::max(Vary, VaryHW)) // Edge peak so cannot use samples
1039 {
1040 Vx_calc = VarxHW;
1041 Vy_calc = VaryHW;
1042 Vxy_calc = 0;
1043 col_calc = lastCol;
1044 row_calc = lastRow;
1045 back_calc = b;
1046 Intensity_calc = statBase[IIntensities] - b * nCells;
1047 if (Vx_calc <= 0 || Vy_calc <= 0) // EdgePeak but not big enuf
1048 return true;
1049
1050 const double params[] = {back_calc, Intensity_calc, col_calc, row_calc, Vx_calc, Vy_calc, Vxy_calc};
1051 double r = CalcSampleIntensityMultiplier(params);
1052 Intensity_calc *= r;
1053 return true;
1054 }
1055 if (Den <= 0)
1056 Den = 1;
1057
1058 bool done = false;
1059 int ntimes = 0;
1060 double Mx = 0, My = 0, Sxx = 0, Syy = 0, Sxy = 0;
1061
1062 double RangeX = statBase[INCol] / 2;
1063 double RangeY = statBase[INRows] / 2;
1064
1065 while (!done && ntimes < 29) {
1066 Mx = statBase[ISSIx] - b * statBase[ISSx];
1067 My = statBase[ISSIy] - b * statBase[ISSy];
1068 Sxx = (statBase[ISSIxx] - b * statBase[ISSxx] - Mx * Mx / Den) / Den;
1069 Syy = (statBase[ISSIyy] - b * statBase[ISSyy] - My * My / Den) / Den;
1070 Sxy = (statBase[ISSIxy] - b * statBase[ISSxy] - Mx * My / Den) / Den;
1071 ntimes++;
1072 done = false;
1073
1074 if (Sxx <= RangeX / 12 || Syy <= RangeY / 12 || Sxy * Sxy / Sxx / Syy > .9) {
1075 b = b * .95;
1076
1077 if (ntimes + 1 == 29)
1078 b = 0;
1079
1080 Den = statBase[IIntensities] - b * nCells;
1081 if (Den <= 1)
1082 Den = 1;
1083
1084 } else
1085 done = true;
1086 }
1087
1088 back_calc = b;
1089 Intensity_calc = statBase[IIntensities] - b * nCells;
1090 col_calc = Mx / Den;
1091 row_calc = My / Den;
1092 Vx_calc = Sxx;
1093 Vy_calc = Syy;
1094 Vxy_calc = Sxy;
1095 return false;
1096}
1097
1105 double Vx, Vy;
1106 Vx = VarxHW;
1107 Vy = VaryHW;
1108 if (Vx < 0)
1110 if (Vy < 0)
1112
1113 double Rx = lastRCRadius / CellWidth - EdgeX;
1114 double Ry = lastRCRadius / CellHeight - EdgeY;
1115 double mult = 1;
1116 if (Rx * Rx > 4 * Vx)
1117 Vx = std::max(VarxHW, Vx_calc);
1118 else
1119 mult = 1.35;
1120
1121 if (Ry * Ry > 4 * Vy)
1122 Vy = std::max(VaryHW, Vy_calc);
1123 else
1124 mult *= 1.35;
1125
1126 double DD = max<double>(sqrt(Vy) * CellHeight, sqrt(Vx) * CellWidth);
1127 double NewRadius = 1.4 * max<double>(MinRowColSpan * max<double>(CellWidth, CellHeight), 4.5 * DD);
1128 NewRadius = mult * min<double>(baseRCRadius, NewRadius);
1129 // 1.4 is needed to get more background cells. In rectangle the corners were
1130 // background
1131
1132 NewRadius = min<double>(MaxRowColSpan * max<double>(CellWidth, CellHeight), NewRadius);
1133
1134 return NewRadius;
1135}
1136
1146void DataModeHandler::setHeightHalfWidthInfo(const std::vector<double> &xvals, const std::vector<double> &yvals,
1147 const std::vector<double> &counts) {
1148 double minCount, maxCount;
1149 const auto &X = xvals;
1150 const auto &Y = yvals;
1151 const auto &C = counts;
1152 VarxHW = -1;
1153 VaryHW = -1;
1154 auto N = static_cast<int>(X.size());
1155
1157
1158 if (N <= 2)
1159 return;
1160
1161 minCount = maxCount = C[0];
1162 double MaxX = -1;
1163 double MaxY = -1;
1164 int nmax = 0;
1165 double lowX, lowY, highX, highY;
1166 lowX = highX = X[0];
1167 lowY = highY = Y[0];
1168
1169 for (int i = 1; i < N; i++) {
1170 if (X[i] < lowX)
1171 lowX = X[i];
1172 else if (X[i] > highX)
1173 highX = X[i];
1174
1175 if (Y[i] < lowY)
1176 lowY = Y[i];
1177 else if (Y[i] > highY)
1178 highY = Y[i];
1179
1180 if (C[i] > maxCount) {
1181 maxCount = C[i];
1182 MaxX = X[i];
1183 MaxY = Y[i];
1184 nmax = 1;
1185 } else if (C[i] < minCount) {
1186 minCount = C[i];
1187
1188 } else if (C[i] == maxCount) // Get a tolerance on this
1189 {
1190 MaxX += X[i];
1191 MaxY += Y[i];
1192 nmax++;
1193 }
1194 }
1195 if (minCount == maxCount)
1196 return;
1197
1198 MaxX /= nmax;
1199 MaxY /= nmax;
1200
1201 double dCount = std::max(.51, (maxCount - minCount) / 6.2);
1202 double CountUp = (maxCount + minCount) / 2 + dCount;
1203 double CountLow = (maxCount + minCount) / 2 - dCount;
1204 double dSpanx = (highX - lowX) / 6.;
1205 double dSpany = (highY - lowY) / 6.0;
1206
1207 int nMax = 0;
1208 int nMin = 0;
1209 double TotMax = 0;
1210 double TotMin = 0;
1211 double offset = std::max(.2, (maxCount - minCount) / 20);
1212 double TotR_max = 0;
1213 double TotR_min = 0;
1214 double TotRx0 = 0;
1215 double TotRy0 = 0;
1216 double TotCx = 0;
1217 double TotCy = 0;
1218 for (int i = 0; i < N; i++) {
1219 if (C[i] > maxCount - offset) {
1220 TotMax += C[i];
1221 nMax++;
1222 TotR_max += C[i] * sqrt((X[i] - MaxX) * (X[i] - MaxX) + (Y[i] - MaxY) * (Y[i] - MaxY));
1223 }
1224 if (C[i] < minCount + offset)
1225
1226 {
1227 TotMin += C[i];
1228 nMin++;
1229
1230 TotR_min += C[i] * sqrt((X[i] - MaxX) * (X[i] - MaxX) + (Y[i] - MaxY) * (Y[i] - MaxY));
1231 }
1232
1233 if (fabs(MaxY - Y[i]) < 1.2 && fabs(MaxX - X[i]) > 1.2 && C[i] >= CountLow && C[i] <= CountUp &&
1234 fabs(MaxX - X[i]) < dSpanx) {
1235 TotRx0 += (C[i] - minCount) * (X[i] - MaxX) * (X[i] - MaxX);
1236 TotCx += C[i] - minCount;
1237 }
1238
1239 if (fabs(MaxX - X[i]) < 1.2 && fabs(MaxY - Y[i]) > 1.2 && C[i] >= CountLow && C[i] <= CountUp &&
1240 fabs(MaxY - Y[i]) < dSpany) {
1241 TotRy0 += (C[i] - minCount) * (Y[i] - MaxY) * (Y[i] - MaxY);
1242 TotCy += C[i] - minCount;
1243 }
1244 }
1245
1246 if (nMax + nMin == N) // all data are on two levels essentially
1247 {
1248 if (TotMax <= 0)
1249 TotMax = 1;
1250 if (TotMin <= 0)
1251 TotMin = 1;
1252 double AvR = .5 * (TotR_max / TotMax + TotR_min / TotMin);
1253 HalfWidthAtHalfHeightRadius = AvR / .8326;
1254
1257 return;
1258 }
1259
1260 double TotR = 0, nR = -1, nRx = -1, nRy = -1;
1261 double MidVal = (TotMax / nMax + TotMin / nMin) / 2.0;
1262 double TotRx = 0, TotRy = 0;
1263 while ((nR <= 0 || nRy <= 0 || nRx <= 0) && offset < MidVal) {
1264 TotR = 0;
1265 nR = 0;
1266 TotRx = 0;
1267 TotRy = 0;
1268 nRx = 0;
1269 nRy = 0;
1270
1271 for (int i = 0; i < N; i++)
1272 if (C[i] < MidVal + offset && C[i] > MidVal - offset) {
1273 double X1 = X[i] - MaxX;
1274 double Y1 = Y[i] - MaxY;
1275 TotR += sqrt(X1 * X1 + Y1 * Y1);
1276 nR++;
1277 if ((X1 >= -1.2 && X1 <= 1.2) && fabs(Y1) > 1.2 && fabs(Y1) < dSpany) {
1278 nRy++;
1279 TotRy += abs(Y1);
1280 }
1281 if ((Y1 >= -1.2 && Y1 <= 1.2) && fabs(X1) > 1.2 && fabs(X1) < dSpanx) {
1282 nRx++;
1283 TotRx += fabs(X1);
1284 }
1285 }
1286 offset *= 1.1;
1287 }
1288
1289 double AvR = TotR / nR;
1290 HalfWidthAtHalfHeightRadius = AvR / .8326;
1291
1292 if (nRx > 0)
1293 VarxHW = (TotRx / nRx) * (TotRx / nRx) / .8326 / .8326;
1294 else if (TotCx > 0)
1295 VarxHW = TotRx0 * TotRx0 / TotCx / TotCx / .8326 / .8326;
1296 else if (HalfWidthAtHalfHeightRadius > 0)
1298 else
1299 VarxHW = -1;
1300
1301 if (nRy > 0)
1302 VaryHW = (TotRy / nRy) * (TotRy / nRy) / .8326 / .8326;
1303 else if (TotCy > 0)
1304 VaryHW = TotRy0 * TotRy0 / TotCy / TotCy / .8326 / .8326;
1305 else if (HalfWidthAtHalfHeightRadius > 0)
1307 else
1308 VaryHW = -1;
1309}
1330 const std::shared_ptr<Geometry::IComponent> &comp, const int chanMin,
1331 const int chanMax, double CentX, double CentY, Kernel::V3D &CentNghbr,
1332 double &neighborRadius, // from CentDetspec
1333 double Radius, string &spec_idList) {
1334
1335 Kernel::V3D CentPos1 = m_center + m_xvec * (CentX - m_COL) * m_cellWidth + m_yvec * (CentY - m_ROW) * m_cellHeight;
1336
1337 int NBadEdgeCells = getProperty("NBadEdgePixels");
1338
1339 auto X = std::make_shared<DataModeHandler>(Radius, Radius, CentY, CentX, m_cellWidth, m_cellHeight,
1340 getProperty("CalculateVariances"), NBadEdgeCells, m_NCOLS - NBadEdgeCells,
1341 NBadEdgeCells, m_NROWS - NBadEdgeCells);
1342
1344 m_AttributeValues->setCurrentRadius(Radius);
1345 m_AttributeValues->setCurrentCenter(CentPos1);
1346
1347 SetUpData1(Data, inpWkSpace, chanMin, chanMax, Radius, CentPos1, spec_idList);
1348
1349 if (m_AttributeValues->StatBaseVals(ISSIxx) < 0) // Not enough data
1350 return;
1351
1352 double NewRadius = m_AttributeValues->getNewRCRadius();
1353 if (m_R0 > 0) {
1354 NewRadius = m_R0;
1355 } else {
1356 m_R0 = NewRadius;
1357 }
1358
1359 CentX = m_ParameterValues[IXMEAN];
1360 CentY = m_ParameterValues[IYMEAN];
1361 Kernel::V3D CentPos = m_center + m_xvec * (CentX - m_COL) * m_cellWidth + m_yvec * (CentY - m_ROW) * m_cellHeight;
1362
1363 double DD = (CentPos - CentNghbr).norm();
1364
1365 if (DD + NewRadius > neighborRadius) {
1366 auto NN = int(NStdDevPeakSpan * NeighborhoodRadiusDivPeakRadius * NewRadius / m_cellWidth * NStdDevPeakSpan *
1367 NeighborhoodRadiusDivPeakRadius * NewRadius / m_cellHeight);
1368 if (m_NeighborIDs[0] < NN) {
1369 delete[] m_NeighborIDs;
1370 m_NeighborIDs = new int[NN + 2];
1371 m_NeighborIDs[0] = NN + 2;
1372 } // else
1373 // NN= m_NeighborIDs[0]-2;
1374 m_NeighborIDs[1] = 2;
1375 neighborRadius = NeighborhoodRadiusDivPeakRadius * NewRadius;
1376 CentNghbr = CentPos;
1377 getNeighborPixIDs(comp, CentPos, neighborRadius, m_NeighborIDs);
1378
1379 } else // big enough neighborhood so
1380 neighborRadius -= DD;
1381
1382 // if( changed) CentNghbr = CentPos.
1383 auto X1 = std::make_shared<DataModeHandler>(Radius, NewRadius, CentY, CentX, m_cellWidth, m_cellHeight,
1384 getProperty("CalculateVariances"), NBadEdgeCells, m_NCOLS - NBadEdgeCells,
1385 NBadEdgeCells, m_NROWS - NBadEdgeCells);
1386
1387 m_AttributeValues = X1;
1388 m_AttributeValues->setCurrentRadius(NewRadius);
1389 m_AttributeValues->setCurrentCenter(CentPos);
1390 SetUpData1(Data, inpWkSpace, chanMin, chanMax, NewRadius, CentPos, spec_idList);
1391}
1392
1405 API::MatrixWorkspace_const_sptr const &inpWkSpace, const int chanMin,
1406 const int chanMax, double Radius, const Kernel::V3D &CentPos,
1407 string &spec_idList) {
1409 if (m_NeighborIDs[1] < 10) {
1410 return;
1411 }
1412 std::vector<double> StatBase(NAttributes);
1413 std::shared_ptr<Workspace2D> ws = std::dynamic_pointer_cast<Workspace2D>(Data);
1414
1415 int NBadEdges = getProperty("NBadEdgePixels");
1416 spec_idList.clear();
1417
1418 for (int i = 0; i < NAttributes + 2; i++)
1419 StatBase.emplace_back(0);
1420
1421 std::vector<double> yvalB;
1422 std::vector<double> errB;
1423 std::vector<double> xvalB;
1424 std::vector<double> YvalB;
1425
1426 double TotBoundaryIntensities = 0;
1427 int nBoundaryCells = 0;
1428 double TotBoundaryVariances = 0;
1429
1430 double BoundaryRadius = min<double>(.90 * Radius, Radius - 1.5 * max<double>(m_cellWidth, m_cellHeight));
1431 double minRow = 20000, maxRow = -1, minCol = 20000, maxCol = -1;
1432
1433 int jj = 0;
1434
1435 std::vector<double> xRef;
1436 for (int i = 2; i < m_NeighborIDs[1]; i++) {
1437 int DetID = m_NeighborIDs[i];
1438
1439 size_t workspaceIndex;
1440 if (m_wi_to_detid_map.count(DetID) > 0)
1441 workspaceIndex = m_wi_to_detid_map.find(DetID)->second;
1442 else {
1443 throw std::runtime_error("No workspaceIndex for detID=" + std::to_string(DetID));
1444 }
1445
1446 IDetector_const_sptr Det = inpWkSpace->getDetector(workspaceIndex);
1447 V3D pixPos = Det->getPos();
1448
1449 if (i > 2)
1450 spec_idList += ",";
1451
1452 V3D dist = pixPos - CentPos;
1453 if (dist.scalar_prod(dist) < Radius * Radius)
1454
1455 {
1456 spec_idList += std::to_string(inpWkSpace->getSpectrum(workspaceIndex).getSpectrumNo());
1457
1458 double R1 = dist.scalar_prod(m_yvec);
1459 double R1a = R1 / m_cellHeight;
1460
1461 double row = m_ROW + R1a;
1462
1463 double C1 = dist.scalar_prod(m_xvec);
1464 double C1a = C1 / m_cellWidth;
1465
1466 double col = m_COL + C1a;
1467
1468 if (row > NBadEdges && col > NBadEdges && (m_NROWS < 0 || row < m_NROWS - NBadEdges) &&
1469 (m_NCOLS < 0 || col < m_NCOLS - NBadEdges)) {
1470 const auto &histogram = inpWkSpace->y(workspaceIndex);
1471
1472 const auto &histoerrs = inpWkSpace->e(workspaceIndex);
1473 double intensity = 0;
1474 double variance = 0;
1475 for (int chan = chanMin; chan <= chanMax; chan++) {
1476 intensity += histogram[chan];
1477 variance += histoerrs[chan] * histoerrs[chan];
1478 }
1479
1480 yvalB.emplace_back(intensity);
1481 double sigma = 1;
1482
1483 errB.emplace_back(sigma);
1484 xvalB.emplace_back(col);
1485 YvalB.emplace_back(row);
1486
1487 xRef.emplace_back(static_cast<double>(jj));
1488 jj++;
1489
1490 updateStats(intensity, variance, row, col, StatBase);
1491
1492 if ((pixPos - CentPos).norm() > BoundaryRadius) {
1493 TotBoundaryIntensities += intensity;
1494 nBoundaryCells++;
1495
1496 TotBoundaryVariances += variance;
1497 }
1498
1499 if (row < minRow)
1500 minRow = row;
1501 if (col < minCol)
1502 minCol = col;
1503 if (row > maxRow)
1504 maxRow = row;
1505 if (col > maxCol)
1506 maxCol = col;
1507
1508 } // if not bad edge
1509
1510 } // peak within radius
1511 } // for each neighbor
1512
1513 m_AttributeValues->EdgeY =
1514 max<double>(0.0, max<double>(-m_ROW + minRow + Radius / m_cellHeight, -maxRow + m_ROW + Radius / m_cellHeight));
1515 m_AttributeValues->EdgeX =
1516 max<double>(0.0, max<double>(-m_COL + minCol + Radius / m_cellWidth, -maxCol + m_COL + Radius / m_cellWidth));
1517 if (m_AttributeValues->EdgeY <= 1)
1518 m_AttributeValues->EdgeY = 0;
1519 if (m_AttributeValues->EdgeX <= 1)
1520 m_AttributeValues->EdgeX = 0;
1521
1522 auto pX = Kernel::make_cow<HistogramData::HistogramX>(std::move(xRef));
1523 // Set the shared X and the counts together so the Histogram size invariant holds. The
1524 // workspace was allocated with an upper-bound number of points and is resized here to the
1525 // number of valid neighbour pixels actually collected. Calling setSharedX on its own would
1526 // be rejected, because the not-yet-resized Y still has the original (larger) length.
1527 ws->setHistogram(0, Points(pX), Counts(yvalB), CountStandardDeviations(errB));
1528 ws->setHistogram(1, Points(pX), Counts(xvalB));
1529 ws->setHistogram(2, Points(pX), Counts(YvalB));
1530 m_AttributeValues->setHeightHalfWidthInfo(xvalB, YvalB, yvalB);
1531
1532 StatBase[IStartRow] = minRow;
1533 StatBase[IStartCol] = minCol;
1534 StatBase[INRows] = maxRow - minRow + 1;
1535 StatBase[INCol] = maxCol - minCol + 1;
1536
1537 StatBase[ITotBoundary] = TotBoundaryIntensities;
1538 StatBase[INBoundary] = nBoundaryCells;
1539 StatBase[IVarBoundary] = TotBoundaryVariances;
1540 m_EdgePeak = m_AttributeValues->setStatBase(StatBase);
1541
1542 m_ParameterValues[IBACK] = m_AttributeValues->getInitBackground();
1543 m_ParameterValues[ITINTENS] = m_AttributeValues->getInitIntensity();
1546 m_ParameterValues[IVXX] = m_AttributeValues->getInitVarx();
1547 m_ParameterValues[IVYY] = m_AttributeValues->getInitVary();
1548 m_ParameterValues[IVXY] = m_AttributeValues->getInitVarxy();
1549}
1550
1557int IntegratePeakTimeSlices::findTimeChannel(const HistogramX &X, const double time) {
1558 int sgn = 1;
1559
1560 if (X[0] > X[1])
1561 sgn = -1;
1562
1563 if (sgn * (X[0] - time) >= 0)
1564 return 0;
1565
1566 if (sgn * (time - X[X.size() - 1u]) >= 0)
1567 return static_cast<int>(X.size()) - 1;
1568
1569 size_t end = X.size() - 1u;
1570 for (size_t i = 0; i < end; i++) {
1571 if (sgn * (time - X[i]) >= 0 && sgn * (X[i + 1u] - time) >= 0)
1572 return static_cast<int>(i);
1573 }
1574
1575 return -1;
1576}
1577
1585bool DataModeHandler::isEdgePeak(const double *params, int nparams) {
1587 double Vary = Varx;
1588 if (nparams > 4) {
1589 Varx = params[IVXX];
1590 Vary = params[IVYY];
1591 }
1592
1593 if (Varx <= 0 || Vary <= 0 || HalfWidthAtHalfHeightRadius <= 0)
1594 return true;
1595
1596 double Rx = lastRCRadius / CellWidth - EdgeX; // span from center in x direction
1597 double Ry = lastRCRadius / CellHeight - EdgeY; // span from center in y direction
1598
1599 return Rx * Rx < NStdDevPeakSpan * NStdDevPeakSpan * std::max(Varx, VarxHW) ||
1600 Ry * Ry < NStdDevPeakSpan * NStdDevPeakSpan * std::max(Vary, VaryHW);
1601}
1602
1609
1610 std::ostringstream fun_str;
1611
1612 fun_str << "name=BivariateNormal,";
1613
1614 if (m_AttributeValues->CalcVariances())
1615 fun_str << "CalcVariances=1";
1616 else
1617 fun_str << "CalcVariances=-1";
1618
1619 int NN = NParameters;
1620 if (m_AttributeValues->CalcVariances())
1621 NN -= 3;
1622
1623 for (int i = 0; i < NN; i++) {
1624 fun_str << "," << m_ParameterNames[i] << "=" << m_ParameterValues[i];
1625 }
1626
1627 return fun_str.str();
1628}
1629
1638int IntegratePeakTimeSlices::findNameInVector(std::string const &oneName, std::vector<std::string> const &nameList)
1639
1640{
1641 const auto it = std::find(nameList.cbegin(), nameList.cend(), oneName);
1642 if (it != nameList.cend()) {
1643 return static_cast<int>(std::distance(nameList.cbegin(), it));
1644 }
1645 return -1;
1646}
1647
1654
1655 this->baseRCRadius = handler.baseRCRadius;
1656 this->lastRCRadius = handler.lastRCRadius;
1658 this->calcNewRCRadius = handler.calcNewRCRadius;
1659 this->lastRow = handler.lastRow;
1660 this->lastCol = handler.lastCol;
1661 this->time = handler.time;
1662 this->CellWidth = handler.CellWidth;
1663 this->CellHeight = handler.CellHeight;
1664 this->currentRadius = handler.currentRadius;
1665 this->currentPosition = handler.currentPosition;
1666 this->StatBase = handler.StatBase;
1667 this->EdgeX = handler.EdgeX;
1668 this->EdgeY = handler.EdgeY;
1669 this->CalcVariance = handler.CalcVariance;
1670 this->VarxHW = handler.VarxHW;
1671 this->VaryHW = handler.VaryHW;
1672 this->MaxRow = handler.MaxRow;
1673 this->MaxCol = handler.MaxCol;
1674 this->MinRow = handler.MinRow;
1675 this->MinCol = handler.MinCol;
1676 this->lastISAWIntensity = handler.lastISAWIntensity;
1677 this->lastISAWVariance = handler.lastISAWIntensity;
1678 this->back_calc = handler.back_calc;
1679 this->Intensity_calc = handler.Intensity_calc;
1680 this->row_calc = handler.row_calc;
1681 this->col_calc = handler.col_calc;
1682 this->Vx_calc = handler.Vx_calc;
1683 this->Vy_calc = handler.Vy_calc;
1684 this->Vxy_calc = handler.Vxy_calc;
1685 this->case4 = handler.case4;
1686}
1701void DataModeHandler::CalcVariancesFromData(double background, double meanx, double meany, double &Varxx, double &Varxy,
1702 double &Varyy, const std::vector<double> &StatBase) {
1703
1704 double Den = StatBase[IIntensities] - background * StatBase[ISS1];
1705 Varxx = (StatBase[ISSIxx] - 2 * meanx * StatBase[ISSIx] + meanx * meanx * StatBase[IIntensities] -
1706 background * (StatBase[ISSxx] - 2 * meanx * StatBase[ISSx] + meanx * meanx * StatBase[ISS1])) /
1707 Den;
1708
1709 Varyy = (StatBase[ISSIyy] - 2 * meany * StatBase[ISSIy] + meany * meany * StatBase[IIntensities] -
1710 background * (StatBase[ISSyy] - 2 * meany * StatBase[ISSy] + meany * meany * StatBase[ISS1])) /
1711 Den;
1712
1713 Varxy =
1714 (StatBase[ISSIxy] - meanx * StatBase[ISSIy] - meany * StatBase[ISSIx] + meanx * meany * StatBase[IIntensities] -
1715 background *
1716 (StatBase[ISSxy] - meanx * StatBase[ISSy] - meany * StatBase[ISSx] + meanx * meany * StatBase[ISS1])) /
1717 Den;
1718
1719 if (CalcVariances()) {
1720
1721 Varxx = std::min(Varxx, 1.21 * getInitVarx()); // copied from BiVariateNormal
1722 Varxx = std::max(Varxx, .79 * getInitVarx());
1723 Varyy = std::min(Varyy, 1.21 * getInitVary());
1724 Varyy = std::max(Varyy, .79 * getInitVary());
1725 }
1726}
1733std::string DataModeHandler::CalcConstraints(std::vector<std::pair<double, double>> &Bounds, bool CalcVariances) {
1734 double TotIntensity = StatBase[IIntensities];
1735 double ncells = StatBase[ISS1];
1736 double Variance = StatBase[IVariance];
1737 double TotBoundaryIntensities = StatBase[ITotBoundary];
1738 double TotBoundaryVariances = StatBase[IVarBoundary];
1739
1740 double nBoundaryCells = StatBase[INBoundary];
1741 double back = TotBoundaryIntensities / nBoundaryCells;
1742 double backVar = std::max(nBoundaryCells / 50.0, TotBoundaryVariances) / nBoundaryCells / nBoundaryCells;
1743 double IntensVar = Variance + ncells * ncells * backVar;
1744
1745 double relError = .25;
1746
1747 if (back_calc != back)
1748 relError = .45;
1749
1750 int N = NParameters;
1751 if (CalcVariances)
1752 N = N - 3;
1753
1754 double NSigs = NStdDevPeakSpan;
1755 if (back_calc > 0)
1756 NSigs = std::max(NStdDevPeakSpan,
1757 7 - 5 * back_calc / back); // background too high
1758 ostringstream str;
1759
1760 NSigs *= max<double>(1.0, Intensity_calc / (TotIntensity - ncells * back_calc));
1761 str << max<double>(0.0, back_calc - NSigs * (1 + relError) * sqrt(backVar)) << "<Background<"
1762 << (back + NSigs * (1.8 + relError) * sqrt(backVar)) << ","
1763 << max<double>(0.0, Intensity_calc - NSigs * (1 + relError) * sqrt(IntensVar)) << "<Intensity<"
1764 << Intensity_calc + NSigs * (1 + relError) * sqrt(IntensVar);
1765
1766 double min = max<double>(0.0, back_calc - NSigs * (1 + relError) * sqrt(backVar));
1767 double maxx = back + NSigs * (1.8 + relError) * sqrt(backVar);
1768 Bounds.emplace_back(min, maxx);
1769 Bounds.emplace_back(max<double>(0.0, Intensity_calc - NSigs * (1 + relError) * sqrt(IntensVar)),
1770 Intensity_calc + NSigs * (1 + relError) * sqrt(IntensVar));
1771 double relErr1 = relError * .75;
1772 double val = col_calc;
1773 double minn = std::max(MinCol - .5, (1 - relErr1) * val);
1774 maxx = std::min((1 + relErr1) * val, MaxCol + .5);
1775
1776 str << "," << minn << "<"
1777 << "Mcol"
1778 << "<" << maxx;
1779 Bounds.emplace_back(minn, maxx);
1780
1781 val = row_calc;
1782
1783 minn = std::max(MinRow - .5, (1 - relErr1) * val);
1784 maxx = std::min((1 + relErr1) * val, MaxRow + .5);
1785 str << "," << minn << "<"
1786 << "Mrow"
1787 << "<" << maxx;
1788 Bounds.emplace_back(minn, maxx);
1789
1790 if (N >= 5) {
1791 val = Vx_calc;
1792 double valmin = val;
1793 double valmax = val;
1794 if (VarxHW > 0) {
1795 valmin = std::min(val, VarxHW);
1796 valmax = std::max(val, VarxHW);
1797 }
1798
1799 relErr1 *= .6; // Edge peaks: need to restrict sigmas.
1800 str << "," << (1 - relErr1) * valmin << "<"
1801 << "SScol"
1802 << "<" << (1 + relErr1) * valmax;
1803 Bounds.emplace_back((1 - relErr1) * valmin, (1 + relErr1) * valmax);
1804
1805 val = Vy_calc;
1806 valmin = val;
1807 valmax = val;
1808 if (VaryHW > 0) {
1809 valmin = std::min(val, VaryHW);
1810 valmax = std::max(val, VaryHW);
1811 }
1812 str << "," << (1 - relErr1) * valmin << "<"
1813 << "SSrow"
1814 << "<" << (1 + relErr1) * valmax;
1815 Bounds.emplace_back((1 - relErr1) * valmin, (1 + relErr1) * valmax);
1816 }
1817
1818 return str.str();
1819}
1820
1835void IntegratePeakTimeSlices::Fit(const MatrixWorkspace_sptr &Data, double &chisqOverDOF, bool &done,
1836 std::vector<string> &names, std::vector<double> &params, std::vector<double> &errs,
1837 double lastRow, double lastCol, double neighborRadius) {
1838
1839 bool CalcVars = m_AttributeValues->CalcVariances();
1840 std::vector<std::pair<double, double>> Bounds;
1841 std::string Constraints = m_AttributeValues->CalcConstraints(Bounds, CalcVars);
1842 auto fit_alg = createChildAlgorithm("Fit");
1843 std::string fun_str = CalculateFunctionProperty_Fit();
1844
1845 std::string SSS(" Fit string ");
1846 SSS += fun_str;
1847 g_log.debug(SSS);
1848 g_log.debug() << " TotCount=" << m_AttributeValues->StatBase[IIntensities] << '\n';
1849
1850 fit_alg->setPropertyValue("Function", fun_str);
1851
1852 fit_alg->setProperty("InputWorkspace", Data);
1853 fit_alg->setProperty("WorkspaceIndex", 0);
1854 fit_alg->setProperty("StartX", 0.0);
1855 fit_alg->setProperty("EndX", 0.0 + static_cast<double>(m_NeighborIDs[1]));
1856 fit_alg->setProperty("MaxIterations", 5000);
1857 fit_alg->setProperty("CreateOutput", true);
1858
1859 fit_alg->setProperty("Output", "out");
1860
1861 fit_alg->setProperty("MaxIterations", 50);
1862
1863 std::string tie = getProperty("Ties");
1864 if (tie.length() > static_cast<size_t>(0))
1865 fit_alg->setProperty("Ties", tie);
1866 if (Constraints.length() > static_cast<size_t>(0))
1867 fit_alg->setProperty("Constraints", Constraints);
1868 try {
1869 fit_alg->executeAsChildAlg();
1870
1871 chisqOverDOF = fit_alg->getProperty("OutputChi2overDoF");
1872 std::string outputStatus = fit_alg->getProperty("OutputStatus");
1873 g_log.debug() << "Chisq/OutputStatus=" << chisqOverDOF << "/" << outputStatus << '\n';
1874
1875 names.clear();
1876 params.clear();
1877 errs.clear();
1878 ITableWorkspace_sptr RRes = fit_alg->getProperty("OutputParameters");
1879 for (int prm = 0; prm < static_cast<int>(RRes->rowCount()) - 1; prm++) {
1880 names.emplace_back(RRes->getRef<string>("Name", prm));
1881 params.emplace_back(RRes->getRef<double>("Value", prm));
1882 double error = RRes->getRef<double>("Error", prm);
1883 errs.emplace_back(error);
1884 }
1885 if (names.size() < 5) {
1886 names.emplace_back(m_ParameterNames[IVXX]);
1887 names.emplace_back(m_ParameterNames[IVYY]);
1888 names.emplace_back(m_ParameterNames[IVXY]);
1889 double Varxx, Varxy, Varyy;
1890 m_AttributeValues->CalcVariancesFromData(params[IBACK], params[IXMEAN], params[IYMEAN], Varxx, Varxy, Varyy,
1891 m_AttributeValues->StatBase);
1892 params.emplace_back(Varxx);
1893 params.emplace_back(Varyy);
1894 params.emplace_back(Varxy);
1895 errs.emplace_back(0);
1896 errs.emplace_back(0);
1897 errs.emplace_back(0);
1898 }
1899
1900 } catch (std::exception &Ex1) // ties or something else went wrong in BivariateNormal
1901 {
1902 done = true;
1903 g_log.error() << "Bivariate Error for PeakNum=" << static_cast<int>(getProperty("PeakIndex")) << ":"
1904 << std::string(Ex1.what()) << '\n';
1905 } catch (...) {
1906 done = true;
1907 g_log.error() << "Bivariate Error A for peakNum=" << static_cast<int>(getProperty("PeakIndex")) << '\n';
1908 }
1909 if (!done) // Bivariate error happened
1910 {
1911
1912 g_log.debug() << " Thru Algorithm: chiSq=" << setw(7) << chisqOverDOF << '\n';
1913 g_log.debug() << " Row,Col Radius=" << lastRow << "," << lastCol << "," << neighborRadius << '\n';
1914
1915 double sqrtChisq = -1;
1916 if (chisqOverDOF >= 0)
1917 sqrtChisq = (chisqOverDOF);
1918
1919 sqrtChisq =
1920 max<double>(sqrtChisq, m_AttributeValues->StatBaseVals(IIntensities) / m_AttributeValues->StatBaseVals(ISS1));
1921 sqrtChisq = SQRT(sqrtChisq);
1922
1923 for (size_t kk = 0; kk < params.size(); kk++) {
1924 g_log.debug() << " Parameter " << setw(8) << names[kk] << " " << setw(8) << params[kk];
1925 // if (names[kk].substr(0, 2) != string("SS"))
1926 g_log.debug() << "(" << setw(8) << (errs[kk] * sqrtChisq) << ")";
1927 if (Bounds.size() > kk) {
1928 pair<double, double> upLow = Bounds[kk];
1929 g_log.debug() << " Bounds(" << upLow.first << "," << upLow.second << ")";
1930 }
1931 g_log.debug() << '\n';
1932 }
1933
1934 double intensity = m_AttributeValues->CalcISAWIntensity(params.data());
1935 g_log.debug() << "IsawIntensity= " << intensity << '\n';
1936 }
1937}
1938
1955void IntegratePeakTimeSlices::PreFit(const MatrixWorkspace_sptr &Data, double &chisqOverDOF, bool &done,
1956 std::vector<string> &names, std::vector<double> &params, std::vector<double> &errs,
1957 double lastRow, double lastCol, double neighborRadius) {
1958
1960 int N = 3;
1961 if (background <= 0) {
1962 background = 0;
1963 N = 1;
1964 }
1965 bool CalcVars = m_AttributeValues->CalcVariances();
1966 int NParams = 4;
1967 if (!CalcVars)
1968 NParams += 3;
1969
1970 double minChiSqOverDOF = -1;
1971 double Bestparams[7];
1972 std::string Bestnames[7];
1973 for (int i = 0; i < N; i++) {
1974 Fit(Data, chisqOverDOF, done, names, params, errs, lastRow, lastCol, neighborRadius);
1975 g_log.debug() << "-----------------------" << i << "--------------------------\n";
1976 if ((minChiSqOverDOF < 0 || chisqOverDOF < minChiSqOverDOF) && (chisqOverDOF > 0) && !done) {
1977 for (int j = 0; j < NParams; j++) {
1978 Bestparams[j] = m_ParameterValues[j];
1979 Bestnames[j] = m_ParameterNames[j];
1980 }
1981 minChiSqOverDOF = chisqOverDOF;
1982 }
1983
1984 // Next round, reduce background
1985 background = background / 2;
1986 if (i + 1 == N - 1)
1987 background = 0;
1988
1989 std::vector<double> prms = m_AttributeValues->GetParams(background);
1990
1991 for (int j = 0; j < NParams; j++)
1992 m_ParameterValues[j] = prms[j];
1993 }
1994 vector<std::string> ParNames(m_ParameterNames, m_ParameterNames + NParams);
1995 for (int i = 0; i < NParams; i++) {
1996 int k = findNameInVector(Bestnames[i], ParNames);
1997 if (k >= 0 && k < NParams)
1998 m_ParameterValues[k] = Bestparams[k];
1999 }
2000
2001 Fit(Data, chisqOverDOF, done, names, params, errs, lastRow, lastCol, neighborRadius);
2002}
2003
2014bool IntegratePeakTimeSlices::isGoodFit(std::vector<double> const &params, std::vector<double> const &errs,
2015 std::vector<std::string> const &names, double chisqOverDOF) {
2016 int Ibk = findNameInVector("Background", names);
2017 if (Ibk < 0)
2018 throw std::runtime_error("Irrecoverable inconsistency found. The index for the "
2019 "parameter 'Background' is lower than zero.");
2020
2021 int IIntensity = findNameInVector("Intensity", names);
2022 if (IIntensity < 0)
2023 throw std::runtime_error("Irrecoverable inconsistency found. The index for the "
2024 "parameter 'Intensity' is lower than zero.");
2025
2026 if (chisqOverDOF < 0) {
2027
2028 g_log.debug() << " Bad Slice- negative chiSq= " << chisqOverDOF << '\n';
2029 ;
2030 return false;
2031 }
2032
2033 int NBadEdgeCells = getProperty("NBadEdgePixels");
2034 NBadEdgeCells = static_cast<int>(.6 * NBadEdgeCells);
2035 if (params[IXMEAN] < NBadEdgeCells || params[IYMEAN] < NBadEdgeCells || params[IXMEAN] > m_NCOLS - NBadEdgeCells ||
2036 params[IYMEAN] > m_NROWS - NBadEdgeCells)
2037 return false;
2038
2039 auto ncells = static_cast<int>(m_AttributeValues->StatBaseVals(ISS1));
2040
2041 if (m_AttributeValues->StatBaseVals(IIntensities) <= 0 ||
2042 (m_AttributeValues->StatBaseVals(IIntensities) - params[Ibk] * ncells) <= 0) {
2043
2044 g_log.debug() << " Bad Slice. Negative Counts= "
2045 << m_AttributeValues->StatBaseVals(IIntensities) - params[Ibk] * ncells << '\n';
2046 ;
2047 return false;
2048 }
2049
2050 double x = params[IIntensity] / (m_AttributeValues->StatBaseVals(IIntensities) - params[Ibk] * ncells);
2051
2052 if ((x < MinGoodRatioFitvsExpIntenisites || x > MaxGoodRatioFitvsExpIntenisites) &&
2053 !m_EdgePeak) // The fitted intensity should be close to tot intensity -
2054 // background
2055 {
2056 g_log.debug() << " Bad Slice. Fitted Intensity & Observed "
2057 "Intensity(-back) too different. ratio="
2058 << x << '\n';
2059
2060 return false;
2061 }
2062
2063 bool GoodNums = true;
2064 bool paramBad = false;
2065 auto BadParamNum = static_cast<size_t>(-1);
2066 for (size_t i = 0; i < errs.size(); i++)
2067 if (errs[i] != errs[i]) {
2068 GoodNums = false;
2069 paramBad = false;
2070 BadParamNum = i;
2071 } else if (errs[i] < 0) {
2072 GoodNums = false;
2073 paramBad = false;
2074 BadParamNum = i;
2075 } else if (params[i] != params[i]) {
2076 GoodNums = false;
2077 paramBad = true;
2078 BadParamNum = i;
2079 }
2080
2081 if (!GoodNums) {
2082 std::string obj = " parameter ";
2083 if (!paramBad)
2084 obj = " error ";
2085 g_log.debug() << " Bad Slice." << obj << BadParamNum << " is not a number\n";
2086 return false;
2087 }
2088
2089 GoodNums = true;
2090
2091 std::string Err("back ground is negative");
2092 if (params[Ibk] < -.002)
2093 GoodNums = false;
2094
2095 if (GoodNums)
2096 Err = "Intensity is negative";
2097 if (params[IIntensity] < 0)
2098 GoodNums = false;
2099
2100 double IsawIntensity = m_AttributeValues->CalcISAWIntensity(params.data());
2101 double IsawVariance = m_AttributeValues->CalcISAWIntensityVariance(params.data(), errs.data(), chisqOverDOF);
2102 if (GoodNums)
2103 Err = "Isaw Variance is negative";
2104 if (IsawVariance > 0) {
2105 if (GoodNums)
2106 Err = "I/sigI > 3";
2107 if (IsawIntensity * IsawIntensity / IsawVariance < MinGoodIoverSigI * MinGoodIoverSigI)
2108 GoodNums = false;
2109 } else
2110 GoodNums = false;
2111
2112 if (!GoodNums)
2113
2114 {
2115 g_log.debug() << Err << '\n';
2116
2117 return false;
2118 }
2119
2120 // Check weak peak. Max theoretical height should be more than 3
2121
2122 double maxPeakHeightTheoretical =
2123 params[ITINTENS] / 2 / M_PI / sqrt(params[IVXX] * params[IVYY] - params[IVXY] * params[IVXY]);
2124
2125 double AvHeight =
2126 m_AttributeValues->StatBaseVals(IIntensities) / m_AttributeValues->StatBaseVals(ISS1) - params[IBACK];
2127
2128 if (maxPeakHeightTheoretical < 2 * AvHeight || AvHeight < 0 || maxPeakHeightTheoretical < 0) {
2129
2130 g_log.debug() << " Bad Slice. Peak too small= " << maxPeakHeightTheoretical << "/" << AvHeight << '\n';
2131 return false;
2132 }
2133
2134 double Nrows = std::max(m_AttributeValues->StatBase[INRows], m_AttributeValues->StatBase[INCol]);
2135 if (maxPeakHeightTheoretical < 1 && (params[IVXX] > Nrows * Nrows / 4 || params[IVYY] > Nrows * Nrows / 4)) {
2136 g_log.debug() << "Peak is too flat \n";
2137 return false;
2138 }
2139
2140 // Exponential too steep, i.e. intensities at pixels 1 from center are <3*
2141 // intensity center
2142 if (params[IVXX] + params[IVYY] > 2.6 * (params[IVXX] * params[IVYY] - params[IVXY] * params[IVXY])) {
2143 g_log.debug() << " Bad Slice. Too steep of an exponential\n";
2144 return false;
2145 }
2146
2147 return true;
2148}
2149
2156bool DataModeHandler::IsEnoughData(const double *ParameterValues, Kernel::Logger & /*unused*/) {
2157 // Check if flat
2158 double Varx, Vary, Cov;
2159
2160 if (StatBase.empty())
2161 return false;
2162
2163 double ncells = static_cast<int>(StatBase[IIntensities]);
2164 if (ncells <= 0)
2165 return false;
2166
2167 double meanx = StatBase[ISSIx] / ncells;
2168 double meany = StatBase[ISSIy] / ncells;
2169
2170 if (!CalcVariances()) {
2171 Varx = ParameterValues[IVXX];
2172 Vary = ParameterValues[IVYY];
2173 Cov = ParameterValues[IVXY];
2174
2175 } else
2176 CalcVariancesFromData(ParameterValues[0], meanx, meany, Varx, Cov, Vary, StatBase);
2177
2178 if (Varx < MinVariationInXYvalues || Vary < MinVariationInXYvalues) // All data essentially the same.
2179 return false;
2180
2181 if (Cov * Cov > MaxCorrCoeffinXY * Varx * Vary) // All data on a obtuse line
2182 return false;
2183
2184 return true;
2185}
2186
2199double IntegratePeakTimeSlices::CalculateIsawIntegrateError(const double background, const double backError,
2200 const double ChiSqOverDOF, const double TotVariance,
2201 const int ncells) {
2202
2203 double B = TotVariance / ncells;
2204 if (B < ChiSqOverDOF)
2205 B = ChiSqOverDOF;
2206
2207 double Variance = TotVariance + (backError * backError * B) * ncells * ncells + background * ncells;
2208
2209 return SQRT(Variance);
2210}
2211
2218 // TabWS->setName("Log Table");
2219 TabWS->addColumn("double", "Time");
2220 TabWS->addColumn("double", "Channel");
2221 TabWS->addColumn("double", "Background");
2222 TabWS->addColumn("double", "Intensity");
2223 TabWS->addColumn("double", "Mcol");
2224 TabWS->addColumn("double", "Mrow");
2225 TabWS->addColumn("double", "SScol");
2226 TabWS->addColumn("double", "SSrow");
2227 TabWS->addColumn("double", "SSrc");
2228 TabWS->addColumn("double", "NCells");
2229 TabWS->addColumn("double", "ChiSqrOverDOF");
2230 TabWS->addColumn("double", "TotIntensity");
2231 TabWS->addColumn("double", "BackgroundError");
2232 TabWS->addColumn("double", "FitIntensityError");
2233 TabWS->addColumn("double", "ISAWIntensity");
2234 TabWS->addColumn("double", "ISAWIntensityError");
2235 TabWS->addColumn("double", "TotalBoundary");
2236 TabWS->addColumn("double", "NBoundaryCells");
2237 TabWS->addColumn("double", "Start Row");
2238 TabWS->addColumn("double", "End Row");
2239 TabWS->addColumn("double", "Start Col");
2240 TabWS->addColumn("double", "End Col");
2241 TabWS->addColumn("double", "TotIntensityError");
2242 TabWS->addColumn("str", "SpecIDs");
2243}
2244
2263 std::vector<double> const &params, std::vector<double> const &errs,
2264 std::vector<std::string> const &names, const double Chisq,
2265 const double time, string spec_idList) {
2266 int Ibk = findNameInVector("Background", names);
2267 int IIntensity = findNameInVector("Intensity", names);
2268 int IVx = findNameInVector("SScol", names);
2269 int IVy = findNameInVector("SSrow", names);
2270 int IVxy = findNameInVector("SSrc", names);
2271 int Irow = findNameInVector("Mrow", names);
2272 int Icol = findNameInVector("Mcol", names);
2273
2274 if (Ibk < 0 || IIntensity < 0 || IVx < 0 || IVy < 0 || IVxy < 0 || Irow < 0 || Icol < 0) {
2275 throw std::runtime_error("Inconsistency found when updating output "
2276 "workspace. None of the indices for the "
2277 "parameters 'Background', 'Intensity', 'SScol', "
2278 "'SSrow', 'SSrc', 'Mrow', 'Mcol' can be "
2279 "negative.");
2280 }
2281
2282 int newRowIndex = 0;
2283
2284 if (dir > 0)
2285 newRowIndex = static_cast<int>(TabWS->rowCount());
2286
2287 auto TableRow = static_cast<int>(TabWS->insertRow(newRowIndex));
2288
2289 auto ncells = static_cast<int>(m_AttributeValues->StatBaseVals(ISS1));
2290 double chisq = max<double>(Chisq, m_AttributeValues->StatBaseVals(IIntensities) / max<int>(ncells, 1));
2291
2292 TabWS->getRef<double>(std::string("Background"), TableRow) = params[Ibk];
2293 TabWS->getRef<double>(std::string("Channel"), TableRow) = chan;
2294
2295 TabWS->getRef<double>(std::string("Intensity"), TableRow) = params[IIntensity];
2296 TabWS->getRef<double>(std::string("FitIntensityError"), TableRow) = errs[IIntensity] * sqrt(chisq);
2297 TabWS->getRef<double>(std::string("Mcol"), TableRow) = params[Icol];
2298 TabWS->getRef<double>(std::string("Mrow"), TableRow) = params[Irow];
2299
2300 TabWS->getRef<double>(std::string("SScol"), TableRow) = params[IVx];
2301 TabWS->getRef<double>(std::string("SSrow"), TableRow) = params[IVy];
2302
2303 TabWS->getRef<double>(std::string("SSrc"), TableRow) = params[IVxy];
2304 TabWS->getRef<double>(std::string("NCells"), TableRow) = ncells;
2305 TabWS->getRef<double>(std::string("ChiSqrOverDOF"), TableRow) = chisq;
2306
2307 TabWS->getRef<double>(std::string("TotIntensity"), TableRow) = m_AttributeValues->StatBaseVals(IIntensities);
2308 TabWS->getRef<double>(std::string("BackgroundError"), TableRow) = errs[Ibk] * SQRT(chisq);
2309 TabWS->getRef<double>(std::string("ISAWIntensity"), TableRow) = m_AttributeValues->CalcISAWIntensity(params.data());
2310 // m_AttributeValues->StatBaseVals(IIntensities)
2311 // -
2312 // params[Ibk]
2313 // * ncells;
2314
2315 TabWS->getRef<double>(std::string("ISAWIntensityError"), TableRow) =
2316 sqrt(m_AttributeValues->CalcISAWIntensityVariance(params.data(), errs.data(), Chisq));
2317
2318 // CalculateIsawIntegrateError(
2319 // params[Ibk], errs[Ibk], chisq, m_AttributeValues->StatBaseVals(IVariance),
2320 // ncells);
2321
2322 TabWS->getRef<double>(std::string("Time"), TableRow) = time;
2323
2324 TabWS->getRef<double>(std::string("TotalBoundary"), TableRow) = m_AttributeValues->StatBaseVals(ITotBoundary);
2325 TabWS->getRef<double>(std::string("NBoundaryCells"), TableRow) = m_AttributeValues->StatBaseVals(INBoundary);
2326
2327 TabWS->getRef<double>(std::string("Start Row"), TableRow) = m_AttributeValues->StatBaseVals(IStartRow);
2328 TabWS->getRef<double>(std::string("End Row"), TableRow) =
2329 m_AttributeValues->StatBaseVals(IStartRow) + m_AttributeValues->StatBaseVals(INRows) - 1;
2330
2331 TabWS->getRef<double>(std::string("Start Col"), TableRow) = m_AttributeValues->StatBaseVals(IStartCol);
2332 TabWS->getRef<double>(std::string("End Col"), TableRow) =
2333 m_AttributeValues->StatBaseVals(IStartCol) + m_AttributeValues->StatBaseVals(INCol) - 1;
2334 TabWS->getRef<double>(std::string("TotIntensityError"), TableRow) = SQRT(m_AttributeValues->StatBaseVals(IVariance));
2335 TabWS->getRef<string>(std::string("SpecIDs"), TableRow) = std::move(spec_idList);
2336
2337 return newRowIndex;
2338}
2339
2354void IntegratePeakTimeSlices::updatePeakInformation(std::vector<double> const &params, std::vector<double> const &errs,
2355 std::vector<std::string> const &names, double &TotVariance,
2356 double &TotIntensity, double const TotSliceIntensity,
2357 double const TotSliceVariance, double const chisqdivDOF,
2358 const int ncells) {
2359 UNUSED_ARG(TotSliceIntensity);
2360 UNUSED_ARG(TotSliceVariance);
2361 UNUSED_ARG(names);
2362 UNUSED_ARG(ncells);
2363
2364 double err = 0;
2365 double intensity = 0;
2366
2367 err = m_AttributeValues->CalcISAWIntensityVariance(params.data(), errs.data(), chisqdivDOF);
2368
2369 intensity = m_AttributeValues->CalcISAWIntensity(params.data());
2370 TotIntensity += intensity;
2371
2372 TotVariance += err;
2373 g_log.debug() << "TotIntensity/TotVariance=" << TotIntensity << "/" << TotVariance << '\n';
2374}
2375
2385 if (!CalcVariance)
2386 return false;
2387
2388 const double param[7] = {back_calc, Intensity_calc, col_calc, row_calc, Vx_calc, Vy_calc, Vxy_calc};
2389 return !isEdgePeak(param, 7);
2390}
2391
2401double DataModeHandler::CalcISAWIntensity(const double *params) {
2402
2403 double ExperimentalIntensity = StatBase[IIntensities] - params[IBACK] * StatBase[ISS1];
2404
2405 double r = CalcSampleIntensityMultiplier(params);
2406
2407 double alpha = .5 * (r - 1.0);
2408 alpha = std::min(1.0, alpha);
2409
2410 lastISAWIntensity = ExperimentalIntensity * r; //*( 1-alpha )+ alpha * FitIntensity;
2411 return lastISAWIntensity;
2412}
2423double DataModeHandler::CalcISAWIntensityVariance(const double *params, const double *errs, double chiSqOvDOF) {
2424
2425 auto ncells = static_cast<int>(StatBase[ISS1]);
2426 double B = StatBase[IVariance] / ncells;
2427 if (B < chiSqOvDOF)
2428 B = chiSqOvDOF;
2429
2430 double ExperimVar = StatBase[IVariance];
2431 double IntensityBackError = errs[IBACK] * sqrt(B);
2432
2433 ExperimVar += IntensityBackError * IntensityBackError * ncells * ncells + params[IBACK] * ncells;
2434
2435 double r = CalcSampleIntensityMultiplier(params);
2436 double alpha = .5 * (r - 1.0);
2437 alpha = std::min(1.0, alpha);
2438
2439 lastISAWVariance = ExperimVar * r * r; //*( 1 - alpha ) + alpha * FitVar;
2440 return lastISAWVariance;
2441}
2442
2451double DataModeHandler::CalcSampleIntensityMultiplier(const double *params) const {
2452 auto minRow = static_cast<int>(StatBase[IStartRow]);
2453 int maxRow = minRow + static_cast<int>(StatBase[INRows]) - 1;
2454 auto minCol = static_cast<int>(StatBase[IStartCol]);
2455 int maxCol = minCol + static_cast<int>(StatBase[INCol]) - 1;
2456 double r = 1;
2457
2458 if (params[IVXX] <= 0 || params[IVYY] <= 0)
2459 return 1.0;
2460
2461 // NstdX iand NstdY are the number of 1/4 standard deviations. Elements of
2462 // probs are in
2463 // 1/4 standard deviations
2464 double NstdX = 4 * min<double>(params[IXMEAN] - minCol, maxCol - params[IXMEAN]) / sqrt(params[IVXX]);
2465
2466 double NstdY = 4 * min<double>(params[IYMEAN] - minRow, maxRow - params[IYMEAN]) / sqrt(params[IVYY]);
2467
2468 double sgn = 1;
2469 if (NstdX < 0) {
2470 sgn = -1;
2471 }
2472 double P = 1;
2473 if (sgn * NstdX < 9) {
2474 auto xx = static_cast<int>(sgn * NstdX);
2475 double a = probs[xx];
2476 double b = 1;
2477 if (xx + 1 <= 8)
2478 b = probs[xx + 1];
2479 P = a + (b - a) * (sgn * NstdX - xx);
2480 }
2481 if (NstdX >= 7.5)
2482 r = 1.0;
2483 else if (sgn > 0)
2484 r = 1 / P;
2485 else
2486 r = 1 / (1 - P);
2487
2488 if (NstdY < 0) {
2489 sgn = -1;
2490 }
2491 P = 1;
2492 if (sgn * NstdY < 9) {
2493 auto xx = static_cast<int>(sgn * NstdY);
2494 double a = probs[xx];
2495 double b = 1;
2496 if (xx + 1 <= 8)
2497 b = probs[xx + 1];
2498 P = a + (b - a) * (sgn * NstdY - xx);
2499 }
2500 if (NstdY >= 7.5)
2501 r *= 1.0;
2502 else if (sgn > 0)
2503 r *= 1 / P;
2504 else
2505 r *= 1 / (1 - P);
2506
2507 r = std::max(r, 1.0);
2508 return r;
2509}
2510
2511} // namespace Mantid::Crystal
2512// Attr indicies
#define DECLARE_ALGORITHM(classname)
Definition Algorithm.h:542
double intensity
double background
double error
#define IVYY
#define IVarBoundary
#define IStartRow
#define ISS1
#define ISSIxx
#define ISSy
#define ISSyy
#define IBACK
#define INBoundary
#define ISSIx
#define INCol
#define IYMEAN
#define ISSIxy
#define ISSIy
#define ISSIyy
#define ITINTENS
#define NAttributes
#define IXMEAN
#define INRows
#define ITotBoundary
#define ISSx
#define IVariance
#define IVXX
#define ISSxy
#define IIntensities
#define IStartCol
#define ISSxx
#define NParameters
#define IVXY
#define fabs(x)
Definition Matrix.cpp:22
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:44
double obj
the value of the quadratic function
Base class from which all concrete algorithm classes should be derived.
Definition Algorithm.h:76
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
virtual std::shared_ptr< Algorithm > createChildAlgorithm(const std::string &name, const double startProgress=-1., const double endProgress=-1., const bool enableLogging=true, const int &version=-1)
Create a Child Algorithm.
Kernel::Logger & g_log
Definition Algorithm.h:423
void deprecatedDate(const std::string &)
The date the algorithm was deprecated on.
Helper class for reporting progress from algorithms.
Definition Progress.h:25
TableRow represents a row in a TableWorkspace.
Definition TableRow.h:39
A property class for workspaces.
Integrates each time slice using the BivariateNormal formula, adding the results to the peak object.
void setHeightHalfWidthInfo(const MantidVec &xvals, const MantidVec &yvals, const MantidVec &counts)
For edge peaks, the sample standard deviations do not work.
double CalcISAWIntensity(const double *params)
Calculates the Intensity designed for Edge Peaks.
double CalcISAWIntensityVariance(const double *params, const double *errs, double chiSqOvDOF)
Calculates the Error in the Intensity designed for Edge Peaks.
std::vector< double > InitValues(double Varx, double Vary, double b)
Returns init values with background and variances replaced by arguments.
bool isEdgePeak(const double *params, int nparams)
Determines if a Peak is an edge peak.
bool CalcVariances()
Determines whether the Variances can be calculated.
double getNewRCRadius()
Calculates the new radius for neighborhoods so as to include almost all of a peak.
void CalcVariancesFromData(double background, double meanx, double meany, double &Varxx, double &Varxy, double &Varyy, const std::vector< double > &StatBase)
Utility method to calculate variances from data given background and means.
double CalcSampleIntensityMultiplier(const double *params) const
For Edge Peaks.
std::vector< double > GetParams(double b)
Calculates the initial values of the parameters given background b.
bool IsEnoughData(const double *ParameterValues, Kernel::Logger &)
Calculates if there is enough data to for there to be a peak.
std::string CalcConstraints(std::vector< std::pair< double, double > > &Bounds, bool CalcVariances)
Calculates the string form of the constraints to be sent to the Fit Algorithm and also saves it in a ...
bool setStatBase(std::vector< double > const &StatBase)
Sets the Accumulated data values into this class, then updates other information like initial values.
void SetUpData1(API::MatrixWorkspace_sptr &Data, API::MatrixWorkspace_const_sptr const &inpWkSpace, const int chanMin, const int chanMax, double Radius, const Kernel::V3D &CentPos, std::string &spec_idList)
Prepares the data for futher analysis adding meta data and marking data on the edges of detectors.
void FindPlane(Kernel::V3D &center, Kernel::V3D &xvec, Kernel::V3D &yvec, double &ROW, double &COL, int &NROWS, int &NCOLS, double &pixWidthx, double &pixHeighty, DataObjects::Peak const &peak) const
For NonFlat banks, this determines the data of a small planar region approximating the instrument clo...
void Fit(const API::MatrixWorkspace_sptr &Data, double &chisqOverDOF, bool &done, std::vector< std::string > &names, std::vector< double > &params, std::vector< double > &errs, double lastRow, double lastCol, double neighborRadius)
Sets up data for the Fit Algorithm call and invokes it.
int CalculateTimeChannelSpan(Geometry::IPeak const &peak, const double dQ, const Mantid::HistogramData::HistogramX &X, const int specNum, int &Centerchan)
Calculates the span of channels needed to encompass all data around the peak with Q values within dQ ...
double m_COL
for Describing the Column(or 0) describing the center of the
double CalculatePositionSpan(DataObjects::Peak const &peak, const double dQ)
Calculates the span in rows and columns needed to include all data within dQ of the specified peak.
double CalculateIsawIntegrateError(const double background, const double backError, const double ChiSqOverDOF, const double TotVariance, const int ncells)
Calculates the error in integration closest to the latest ISAW calculations.
void exec() override
Executes this algorithm.
std::string CalculateFunctionProperty_Fit()
Calculates the string for the Function Property of the Fit Algorithm.
Kernel::V3D m_center
for Describing the Plane at the Peak
Kernel::V3D m_yvec
for Describing the Plane at the Peak
Kernel::V3D m_xvec
for Describing the Plane at the Peak
void SetUpData(API::MatrixWorkspace_sptr &Data, API::MatrixWorkspace_const_sptr const &inpWkSpace, const std::shared_ptr< Geometry::IComponent > &comp, const int chanMin, const int chanMax, double CentX, double CentY, Kernel::V3D &CentNghbr, double &neighborRadius, double Radius, std::string &spec_idList)
Initial phase at converting Detector data to workspace data that will be sent to the Fit Function,...
std::shared_ptr< DataModeHandler > m_AttributeValues
void init() override
Virtual method - must be overridden by concrete algorithm.
double m_ROW
for Describing the Row(or 0) describing the center of the Peak
double m_cellHeight
for Describing the Plane at the Peak
bool getNeighborPixIDs(const std::shared_ptr< Geometry::IComponent > &comp, const Kernel::V3D &Center, double &Radius, int *&ArryofID)
Finds all neighbors within a given Radius of the Center on the given component.
int findNameInVector(std::string const &oneName, std::vector< std::string > const &nameList)
Utility to find a name in a vector of strings.
double m_R0
for Weak Peaks, these can be set using info from close
void updateStats(const double intensity, const double variance, const double row, const double col, std::vector< double > &StatBase)
Updates the cumulative statistics for the data being considered.
void InitializeColumnNamesInTableWorkspace(DataObjects::TableWorkspace_sptr &TabWS)
Initializes the column names in the output table workspace.
bool updateNeighbors(const std::shared_ptr< Geometry::IComponent > &comp, const Kernel::V3D &CentPos, const Kernel::V3D &oldCenter, double NewRadius, double &neighborRadius)
Checks and updates if needed the list of m_NeighborIDs.
int UpdateOutputWS(DataObjects::TableWorkspace_sptr &TabWS, const int dir, const double chan, std::vector< double > const &params, std::vector< double > const &errs, std::vector< std::string > const &names, const double Chisq, const double time, std::string spec_idList)
Updates the information in the output OutputWorkspace.
void PreFit(const API::MatrixWorkspace_sptr &Data, double &chisqOverDOF, bool &done, std::vector< std::string > &names, std::vector< double > &params, std::vector< double > &errs, double lastRow, double lastCol, double neighborRadius)
Tests several starting points in the Marquardt algorithm then calls Fit.
bool isGoodFit(std::vector< double > const &params, std::vector< double > const &errs, std::vector< std::string > const &names, double chisqOverDOF)
Determines if the list of parameters and errors represent a "good" fit.
int findTimeChannel(const Mantid::HistogramData::HistogramX &X, const double time)
Finds the time channel with the given time in.
void updatePeakInformation(std::vector< double > const &params, std::vector< double > const &errs, std::vector< std::string > const &names, double &TotVariance, double &TotIntensity, double const TotSliceIntensity, double const TotSliceVariance, double const chisqdivDOF, const int ncells)
Updates m_AttributeValues with this peak information from this time slice.
A generic fitting algorithm.
Definition Fit.h:78
Structure describing a single-crystal peak.
Definition Peak.h:34
int getCol() const override
For RectangularDetectors only, returns the column (x) of the pixel of the detector or -1 if not found...
Definition Peak.cpp:335
Geometry::Instrument_const_sptr getInstrument() const
Return a shared ptr to the instrument for this peak.
Definition Peak.cpp:320
int getRow() const override
For RectangularDetectors only, returns the row (y) of the pixel of the detector or -1 if not found.
Definition Peak.cpp:326
Mantid::Kernel::V3D getQLabFrame() const override
Return the Q change (of the lattice, k_i - k_f) for this peak.
Definition Peak.cpp:451
int getDetectorID() const override
Get the ID of the detector at the center of the peak
Definition Peak.cpp:265
Geometry::IDetector_const_sptr getDetector() const
Return a shared ptr to the detector at center of peak.
Definition Peak.cpp:317
virtual Mantid::Kernel::V3D getDetPos() const
Return the detector position vector.
Definition Peak.cpp:720
const std::string & getBankName() const
Find the name of the bank that is the parent of the detector.
Definition Peak.cpp:347
A simple structure that defines an axis-aligned cuboid shaped bounding box for a geometrical object.
Definition BoundingBox.h:33
bool isPointInside(const Kernel::V3D &point) const
Is the given point within the bounding box?
double xMax() const
Return the maximum value of X.
Definition BoundingBox.h:79
double zMin() const
Return the minimum value of Z.
Definition BoundingBox.h:85
double zMax() const
Return the maximum value of Z.
Definition BoundingBox.h:87
double yMax() const
Return the maximum value of Y.
Definition BoundingBox.h:83
double xMin() const
Return the minimum value of X.
Definition BoundingBox.h:77
double yMin() const
Return the minimum value of Y.
Definition BoundingBox.h:81
Structure describing a single-crystal peak.
Definition IPeak.h:26
virtual double getTOF() const =0
virtual Mantid::Kernel::V3D getQLabFrame() const =0
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.
Definition Logger.h:51
void debug(const std::string &msg)
Logs at debug level.
Definition Logger.cpp:145
void error(const std::string &msg)
Logs at error level.
Definition Logger.cpp:108
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Class for quaternions.
Definition Quat.h:39
void inverse()
Inverse a quaternion (in the sense of rotation inversion)
Definition Quat.cpp:376
void rotate(V3D &) const
Rotate a vector.
Definition Quat.cpp:397
std::vector< double > getRotation(bool check_normalisation=false, bool throw_on_errors=false) const
returns the rotation matrix defined by this quaternion as an 9-point
Definition Quat.cpp:453
static T & Instance()
Return a reference to the Singleton instance, creating it if it does not already exist Creation is do...
Class for 3D vectors.
Definition V3D.h:34
constexpr double scalar_prod(const V3D &v) const noexcept
Calculates the cross product.
Definition V3D.h:280
constexpr double X() const noexcept
Get x.
Definition V3D.h:238
double normalize()
Make a normalized vector (return norm value)
Definition V3D.cpp:129
constexpr double Y() const noexcept
Get y.
Definition V3D.h:239
void setZ(const double zz) noexcept
Set is z position.
Definition V3D.h:236
double norm() const noexcept
Definition V3D.h:269
void setX(const double xx) noexcept
Set is x position.
Definition V3D.h:224
void setY(const double yy) noexcept
Set is y position.
Definition V3D.h:230
constexpr double Z() const noexcept
Get z.
Definition V3D.h:240
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::shared_ptr< const IComponent > IComponent_const_sptr
Typdef of a shared pointer to a const IComponent.
Definition IComponent.h:167
std::shared_ptr< const Mantid::Geometry::IDetector > IDetector_const_sptr
Shared pointer to IDetector (const version)
Definition IDetector.h:102
std::shared_ptr< const Instrument > Instrument_const_sptr
Shared pointer to an const instrument object.
STL namespace.
std::string to_string(const wide_integer< Bits, Signed > &n)
@ Input
An input workspace.
Definition Property.h:53
@ Output
An output workspace.
Definition Property.h:54