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 // NOTE: uses legacy accessors rather than ComponentInfo because peak.getInstrument()
827 // is not guaranteed to be parametrized (no ParameterMap available in that case), which
828 // GridDetector/RectangularDetector's own accessors handle natively but ComponentInfo cannot.
829 if (ddet) {
830 std::pair<int, int> CR = ddet->getXYForDetectorID(det->getID());
831 ROW = CR.second;
832 COL = CR.first;
833 pixWidthx = ddet->xstep();
834 pixHeighty = ddet->ystep();
835
836 NROWS = ddet->ypixels();
837 NCOLS = ddet->xpixels();
838
839 return;
840 }
841 // Get NROWS and NCOLS for other panels
842 NROWS = NCOLS = -1;
843
844 if (!panel)
845 return;
846 std::shared_ptr<const Component> compPanel = std::dynamic_pointer_cast<const Component>(panel);
847 std::shared_ptr<IComponent> panel1(compPanel->base()->clone());
848 BoundingBox B;
849
850 Quat rot = panel1->getRotation();
851
852 rot.inverse();
853
854 panel1->rotate(rot);
855
856 panel1->getBoundingBox(B);
857
858 NROWS = boost::math::iround((B.yMax() - B.yMin()) / pixHeighty);
859 NCOLS = boost::math::iround((B.xMax() - B.xMin()) / pixWidthx);
860}
861
871void IntegratePeakTimeSlices::updateStats(const double intensity, const double variance, const double row,
872 const double col, std::vector<double> &StatBase) {
873
874 StatBase[ISSIxx] += col * col * intensity;
875 StatBase[ISSIyy] += intensity * row * row;
876 StatBase[ISSIxy] += intensity * row * col;
877 StatBase[ISSxx] += col * col;
878 StatBase[ISSyy] += row * row;
879 StatBase[ISSxy] += row * col;
880 StatBase[ISSIx] += intensity * col;
881 StatBase[ISSIy] += intensity * row;
882 StatBase[ISSx] += col;
883 StatBase[ISSy] += row;
884 StatBase[IIntensities] += intensity;
885 StatBase[IVariance] += variance;
886 StatBase[ISS1] += 1;
887}
888
899std::vector<double> DataModeHandler::InitValues(double Varx, double Vary, double b) {
900 std::vector<double> Res(7);
901
902 Res[IVXX] = Varx;
903 Res[IVYY] = Vary;
904 Res[IVXY] = 0;
905 auto nCells = static_cast<int>(StatBase[ISS1]);
906 double Den = StatBase[IIntensities] - b * nCells;
907 Res[IXMEAN] = (StatBase[ISSIx] - b * StatBase[ISSx]) / Den;
908 Res[IYMEAN] = (StatBase[ISSIy] - b * StatBase[ISSy]) / Den;
909 Res[IBACK] = b;
910 Res[ITINTENS] = StatBase[IIntensities] - b * nCells;
911
912 //---- Is Edge Cell ???-------
913 double NstdX = 4 * (currentRadius / CellWidth - EdgeX) / sqrt(Varx);
914 double NstdY = 4 * (currentRadius / CellHeight - EdgeY) / sqrt(Vary);
915 double sigx = 1;
916 double sigy = 1;
917 if (NstdX < 0)
918 sigx = -1;
919 if (NstdY < 0)
920 sigy = -1;
921
922 double x = 1;
923 if (sigy * NstdY < 7 && sigy * NstdY >= 0) // is close to row edge
924 {
925 x = probs[std::lround(sigy * NstdY)];
926 if (sigy < 0)
927 x = 1 - x;
928 double My2 = StatBase[IStartRow];
929 if (Res[IYMEAN] - My2 > My2 + StatBase[INRows] - Res[IYMEAN])
930 My2 += StatBase[INRows];
931 Res[IYMEAN] = Res[IYMEAN] * x + (1 - x) * My2;
932 }
933 double x1 = 1;
934 if (sigx * NstdX < 7 && sigx * NstdX > 0) // is close to x edge
935 {
936 x1 = probs[std::lround(sigx * NstdX)];
937 if (sigx < 0)
938 x1 = 1 - x1;
939 double Mx2 = StatBase[IStartCol];
940 if (Res[IXMEAN] - Mx2 > Mx2 + StatBase[INCol] - Res[IXMEAN])
941 Mx2 += StatBase[INCol];
942 Res[IXMEAN] = Res[IXMEAN] * x1 + (1 - x1) * Mx2;
943 }
944 Res[ITINTENS] /= x * x1;
945
946 return Res;
947}
948
956std::vector<double> DataModeHandler::GetParams(double b) {
957
958 auto nCells = static_cast<int>(StatBase[ISS1]);
959 double Den = StatBase[IIntensities] - b * nCells;
960 double Varx, Vary;
961
962 Varx = VarxHW;
963 Vary = VaryHW;
964
965 double Rx = lastRCRadius / CellWidth - EdgeX;
966 double Ry = lastRCRadius / CellHeight - EdgeY;
967 if (Varx <= 0)
969
970 if (Vary <= 0)
972 // Use
973 if (Rx * Rx < 4 * Varx || Ry * Ry < 4 * Vary) {
974 return InitValues(Varx, Vary, b);
975 }
976 if (Den < 0)
977 return std::vector<double>();
978
979 double Mx = StatBase[ISSIx] - b * StatBase[ISSx];
980 double My = StatBase[ISSIy] - b * StatBase[ISSy];
981
982 double Sxx = (StatBase[ISSIxx] - b * StatBase[ISSxx] - Mx * Mx / Den) / Den;
983 double Syy = (StatBase[ISSIyy] - b * StatBase[ISSyy] - My * My / Den) / Den;
984 double Sxy = (StatBase[ISSIxy] - b * StatBase[ISSxy] - Mx * My / Den) / Den;
985
986 double Intensity = StatBase[IIntensities] - b * nCells;
987 double col = Mx / Den;
988 double row = My / Den;
989 std::vector<double> Result(7);
990 Result[IBACK] = b;
991 Result[ITINTENS] = Intensity;
992 Result[IXMEAN] = col;
993 Result[IYMEAN] = row;
994 Result[IVXX] = Sxx;
995 Result[IVYY] = Syy;
996 Result[IVXY] = Sxy;
997
998 return Result;
999}
1000
1007bool DataModeHandler::setStatBase(std::vector<double> const &statBase)
1008
1009{
1010 auto nBoundaryCells = static_cast<int>(statBase[INBoundary]);
1011 this->StatBase = statBase;
1012 double b = 0;
1013 if (nBoundaryCells > 0) {
1014 double TotBoundaryIntensities = statBase[ITotBoundary];
1015 b = TotBoundaryIntensities / nBoundaryCells;
1016 }
1017
1018 auto nCells = static_cast<int>(statBase[ISS1]);
1019 double Den = statBase[IIntensities] - b * nCells;
1020 int k = 0;
1021 while (Den <= 0 && b != 0) {
1022 b = b * .7;
1023 Den = statBase[IIntensities] - b * nCells;
1024
1025 if (k < 8)
1026 k++;
1027 else
1028 b = 0;
1029 }
1030
1031 double Varx, Vary;
1032 Varx = statBase[INCol] / 7; // Range = 3.5 standard deviations
1033 Vary = statBase[INRows] / 7;
1034 Varx *= Varx;
1035 Vary *= Vary;
1036
1037 double Rx = lastRCRadius / CellWidth - EdgeX;
1038 double Ry = lastRCRadius / CellHeight - EdgeY;
1039 if (CellWidth > 0 && currentRadius > 0 && lastCol > 0 && lastRow > 0)
1040 if (Rx * Rx < 4 * std::max(Varx, VarxHW) || HalfWidthAtHalfHeightRadius < 0 ||
1041 Ry * Ry < 4 * std::max(Vary, VaryHW)) // Edge peak so cannot use samples
1042 {
1043 Vx_calc = VarxHW;
1044 Vy_calc = VaryHW;
1045 Vxy_calc = 0;
1046 col_calc = lastCol;
1047 row_calc = lastRow;
1048 back_calc = b;
1049 Intensity_calc = statBase[IIntensities] - b * nCells;
1050 if (Vx_calc <= 0 || Vy_calc <= 0) // EdgePeak but not big enuf
1051 return true;
1052
1053 const double params[] = {back_calc, Intensity_calc, col_calc, row_calc, Vx_calc, Vy_calc, Vxy_calc};
1054 double r = CalcSampleIntensityMultiplier(params);
1055 Intensity_calc *= r;
1056 return true;
1057 }
1058 if (Den <= 0)
1059 Den = 1;
1060
1061 bool done = false;
1062 int ntimes = 0;
1063 double Mx = 0, My = 0, Sxx = 0, Syy = 0, Sxy = 0;
1064
1065 double RangeX = statBase[INCol] / 2;
1066 double RangeY = statBase[INRows] / 2;
1067
1068 while (!done && ntimes < 29) {
1069 Mx = statBase[ISSIx] - b * statBase[ISSx];
1070 My = statBase[ISSIy] - b * statBase[ISSy];
1071 Sxx = (statBase[ISSIxx] - b * statBase[ISSxx] - Mx * Mx / Den) / Den;
1072 Syy = (statBase[ISSIyy] - b * statBase[ISSyy] - My * My / Den) / Den;
1073 Sxy = (statBase[ISSIxy] - b * statBase[ISSxy] - Mx * My / Den) / Den;
1074 ntimes++;
1075 done = false;
1076
1077 if (Sxx <= RangeX / 12 || Syy <= RangeY / 12 || Sxy * Sxy / Sxx / Syy > .9) {
1078 b = b * .95;
1079
1080 if (ntimes + 1 == 29)
1081 b = 0;
1082
1083 Den = statBase[IIntensities] - b * nCells;
1084 if (Den <= 1)
1085 Den = 1;
1086
1087 } else
1088 done = true;
1089 }
1090
1091 back_calc = b;
1092 Intensity_calc = statBase[IIntensities] - b * nCells;
1093 col_calc = Mx / Den;
1094 row_calc = My / Den;
1095 Vx_calc = Sxx;
1096 Vy_calc = Syy;
1097 Vxy_calc = Sxy;
1098 return false;
1099}
1100
1108 double Vx, Vy;
1109 Vx = VarxHW;
1110 Vy = VaryHW;
1111 if (Vx < 0)
1113 if (Vy < 0)
1115
1116 double Rx = lastRCRadius / CellWidth - EdgeX;
1117 double Ry = lastRCRadius / CellHeight - EdgeY;
1118 double mult = 1;
1119 if (Rx * Rx > 4 * Vx)
1120 Vx = std::max(VarxHW, Vx_calc);
1121 else
1122 mult = 1.35;
1123
1124 if (Ry * Ry > 4 * Vy)
1125 Vy = std::max(VaryHW, Vy_calc);
1126 else
1127 mult *= 1.35;
1128
1129 double DD = max<double>(sqrt(Vy) * CellHeight, sqrt(Vx) * CellWidth);
1130 double NewRadius = 1.4 * max<double>(MinRowColSpan * max<double>(CellWidth, CellHeight), 4.5 * DD);
1131 NewRadius = mult * min<double>(baseRCRadius, NewRadius);
1132 // 1.4 is needed to get more background cells. In rectangle the corners were
1133 // background
1134
1135 NewRadius = min<double>(MaxRowColSpan * max<double>(CellWidth, CellHeight), NewRadius);
1136
1137 return NewRadius;
1138}
1139
1149void DataModeHandler::setHeightHalfWidthInfo(const std::vector<double> &xvals, const std::vector<double> &yvals,
1150 const std::vector<double> &counts) {
1151 double minCount, maxCount;
1152 const auto &X = xvals;
1153 const auto &Y = yvals;
1154 const auto &C = counts;
1155 VarxHW = -1;
1156 VaryHW = -1;
1157 auto N = static_cast<int>(X.size());
1158
1160
1161 if (N <= 2)
1162 return;
1163
1164 minCount = maxCount = C[0];
1165 double MaxX = -1;
1166 double MaxY = -1;
1167 int nmax = 0;
1168 double lowX, lowY, highX, highY;
1169 lowX = highX = X[0];
1170 lowY = highY = Y[0];
1171
1172 for (int i = 1; i < N; i++) {
1173 if (X[i] < lowX)
1174 lowX = X[i];
1175 else if (X[i] > highX)
1176 highX = X[i];
1177
1178 if (Y[i] < lowY)
1179 lowY = Y[i];
1180 else if (Y[i] > highY)
1181 highY = Y[i];
1182
1183 if (C[i] > maxCount) {
1184 maxCount = C[i];
1185 MaxX = X[i];
1186 MaxY = Y[i];
1187 nmax = 1;
1188 } else if (C[i] < minCount) {
1189 minCount = C[i];
1190
1191 } else if (C[i] == maxCount) // Get a tolerance on this
1192 {
1193 MaxX += X[i];
1194 MaxY += Y[i];
1195 nmax++;
1196 }
1197 }
1198 if (minCount == maxCount)
1199 return;
1200
1201 MaxX /= nmax;
1202 MaxY /= nmax;
1203
1204 double dCount = std::max(.51, (maxCount - minCount) / 6.2);
1205 double CountUp = (maxCount + minCount) / 2 + dCount;
1206 double CountLow = (maxCount + minCount) / 2 - dCount;
1207 double dSpanx = (highX - lowX) / 6.;
1208 double dSpany = (highY - lowY) / 6.0;
1209
1210 int nMax = 0;
1211 int nMin = 0;
1212 double TotMax = 0;
1213 double TotMin = 0;
1214 double offset = std::max(.2, (maxCount - minCount) / 20);
1215 double TotR_max = 0;
1216 double TotR_min = 0;
1217 double TotRx0 = 0;
1218 double TotRy0 = 0;
1219 double TotCx = 0;
1220 double TotCy = 0;
1221 for (int i = 0; i < N; i++) {
1222 if (C[i] > maxCount - offset) {
1223 TotMax += C[i];
1224 nMax++;
1225 TotR_max += C[i] * sqrt((X[i] - MaxX) * (X[i] - MaxX) + (Y[i] - MaxY) * (Y[i] - MaxY));
1226 }
1227 if (C[i] < minCount + offset)
1228
1229 {
1230 TotMin += C[i];
1231 nMin++;
1232
1233 TotR_min += C[i] * sqrt((X[i] - MaxX) * (X[i] - MaxX) + (Y[i] - MaxY) * (Y[i] - MaxY));
1234 }
1235
1236 if (fabs(MaxY - Y[i]) < 1.2 && fabs(MaxX - X[i]) > 1.2 && C[i] >= CountLow && C[i] <= CountUp &&
1237 fabs(MaxX - X[i]) < dSpanx) {
1238 TotRx0 += (C[i] - minCount) * (X[i] - MaxX) * (X[i] - MaxX);
1239 TotCx += C[i] - minCount;
1240 }
1241
1242 if (fabs(MaxX - X[i]) < 1.2 && fabs(MaxY - Y[i]) > 1.2 && C[i] >= CountLow && C[i] <= CountUp &&
1243 fabs(MaxY - Y[i]) < dSpany) {
1244 TotRy0 += (C[i] - minCount) * (Y[i] - MaxY) * (Y[i] - MaxY);
1245 TotCy += C[i] - minCount;
1246 }
1247 }
1248
1249 if (nMax + nMin == N) // all data are on two levels essentially
1250 {
1251 if (TotMax <= 0)
1252 TotMax = 1;
1253 if (TotMin <= 0)
1254 TotMin = 1;
1255 double AvR = .5 * (TotR_max / TotMax + TotR_min / TotMin);
1256 HalfWidthAtHalfHeightRadius = AvR / .8326;
1257
1260 return;
1261 }
1262
1263 double TotR = 0, nR = -1, nRx = -1, nRy = -1;
1264 double MidVal = (TotMax / nMax + TotMin / nMin) / 2.0;
1265 double TotRx = 0, TotRy = 0;
1266 while ((nR <= 0 || nRy <= 0 || nRx <= 0) && offset < MidVal) {
1267 TotR = 0;
1268 nR = 0;
1269 TotRx = 0;
1270 TotRy = 0;
1271 nRx = 0;
1272 nRy = 0;
1273
1274 for (int i = 0; i < N; i++)
1275 if (C[i] < MidVal + offset && C[i] > MidVal - offset) {
1276 double X1 = X[i] - MaxX;
1277 double Y1 = Y[i] - MaxY;
1278 TotR += sqrt(X1 * X1 + Y1 * Y1);
1279 nR++;
1280 if ((X1 >= -1.2 && X1 <= 1.2) && fabs(Y1) > 1.2 && fabs(Y1) < dSpany) {
1281 nRy++;
1282 TotRy += abs(Y1);
1283 }
1284 if ((Y1 >= -1.2 && Y1 <= 1.2) && fabs(X1) > 1.2 && fabs(X1) < dSpanx) {
1285 nRx++;
1286 TotRx += fabs(X1);
1287 }
1288 }
1289 offset *= 1.1;
1290 }
1291
1292 double AvR = TotR / nR;
1293 HalfWidthAtHalfHeightRadius = AvR / .8326;
1294
1295 if (nRx > 0)
1296 VarxHW = (TotRx / nRx) * (TotRx / nRx) / .8326 / .8326;
1297 else if (TotCx > 0)
1298 VarxHW = TotRx0 * TotRx0 / TotCx / TotCx / .8326 / .8326;
1299 else if (HalfWidthAtHalfHeightRadius > 0)
1301 else
1302 VarxHW = -1;
1303
1304 if (nRy > 0)
1305 VaryHW = (TotRy / nRy) * (TotRy / nRy) / .8326 / .8326;
1306 else if (TotCy > 0)
1307 VaryHW = TotRy0 * TotRy0 / TotCy / TotCy / .8326 / .8326;
1308 else if (HalfWidthAtHalfHeightRadius > 0)
1310 else
1311 VaryHW = -1;
1312}
1333 const std::shared_ptr<Geometry::IComponent> &comp, const int chanMin,
1334 const int chanMax, double CentX, double CentY, Kernel::V3D &CentNghbr,
1335 double &neighborRadius, // from CentDetspec
1336 double Radius, string &spec_idList) {
1337
1338 Kernel::V3D CentPos1 = m_center + m_xvec * (CentX - m_COL) * m_cellWidth + m_yvec * (CentY - m_ROW) * m_cellHeight;
1339
1340 int NBadEdgeCells = getProperty("NBadEdgePixels");
1341
1342 auto X = std::make_shared<DataModeHandler>(Radius, Radius, CentY, CentX, m_cellWidth, m_cellHeight,
1343 getProperty("CalculateVariances"), NBadEdgeCells, m_NCOLS - NBadEdgeCells,
1344 NBadEdgeCells, m_NROWS - NBadEdgeCells);
1345
1347 m_AttributeValues->setCurrentRadius(Radius);
1348 m_AttributeValues->setCurrentCenter(CentPos1);
1349
1350 SetUpData1(Data, inpWkSpace, chanMin, chanMax, Radius, CentPos1, spec_idList);
1351
1352 if (m_AttributeValues->StatBaseVals(ISSIxx) < 0) // Not enough data
1353 return;
1354
1355 double NewRadius = m_AttributeValues->getNewRCRadius();
1356 if (m_R0 > 0) {
1357 NewRadius = m_R0;
1358 } else {
1359 m_R0 = NewRadius;
1360 }
1361
1362 CentX = m_ParameterValues[IXMEAN];
1363 CentY = m_ParameterValues[IYMEAN];
1364 Kernel::V3D CentPos = m_center + m_xvec * (CentX - m_COL) * m_cellWidth + m_yvec * (CentY - m_ROW) * m_cellHeight;
1365
1366 double DD = (CentPos - CentNghbr).norm();
1367
1368 if (DD + NewRadius > neighborRadius) {
1369 auto NN = int(NStdDevPeakSpan * NeighborhoodRadiusDivPeakRadius * NewRadius / m_cellWidth * NStdDevPeakSpan *
1370 NeighborhoodRadiusDivPeakRadius * NewRadius / m_cellHeight);
1371 if (m_NeighborIDs[0] < NN) {
1372 delete[] m_NeighborIDs;
1373 m_NeighborIDs = new int[NN + 2];
1374 m_NeighborIDs[0] = NN + 2;
1375 } // else
1376 // NN= m_NeighborIDs[0]-2;
1377 m_NeighborIDs[1] = 2;
1378 neighborRadius = NeighborhoodRadiusDivPeakRadius * NewRadius;
1379 CentNghbr = CentPos;
1380 getNeighborPixIDs(comp, CentPos, neighborRadius, m_NeighborIDs);
1381
1382 } else // big enough neighborhood so
1383 neighborRadius -= DD;
1384
1385 // if( changed) CentNghbr = CentPos.
1386 auto X1 = std::make_shared<DataModeHandler>(Radius, NewRadius, CentY, CentX, m_cellWidth, m_cellHeight,
1387 getProperty("CalculateVariances"), NBadEdgeCells, m_NCOLS - NBadEdgeCells,
1388 NBadEdgeCells, m_NROWS - NBadEdgeCells);
1389
1390 m_AttributeValues = X1;
1391 m_AttributeValues->setCurrentRadius(NewRadius);
1392 m_AttributeValues->setCurrentCenter(CentPos);
1393 SetUpData1(Data, inpWkSpace, chanMin, chanMax, NewRadius, CentPos, spec_idList);
1394}
1395
1408 API::MatrixWorkspace_const_sptr const &inpWkSpace, const int chanMin,
1409 const int chanMax, double Radius, const Kernel::V3D &CentPos,
1410 string &spec_idList) {
1412 if (m_NeighborIDs[1] < 10) {
1413 return;
1414 }
1415 std::vector<double> StatBase(NAttributes);
1416 std::shared_ptr<Workspace2D> ws = std::dynamic_pointer_cast<Workspace2D>(Data);
1417
1418 int NBadEdges = getProperty("NBadEdgePixels");
1419 spec_idList.clear();
1420
1421 for (int i = 0; i < NAttributes + 2; i++)
1422 StatBase.emplace_back(0);
1423
1424 std::vector<double> yvalB;
1425 std::vector<double> errB;
1426 std::vector<double> xvalB;
1427 std::vector<double> YvalB;
1428
1429 double TotBoundaryIntensities = 0;
1430 int nBoundaryCells = 0;
1431 double TotBoundaryVariances = 0;
1432
1433 double BoundaryRadius = min<double>(.90 * Radius, Radius - 1.5 * max<double>(m_cellWidth, m_cellHeight));
1434 double minRow = 20000, maxRow = -1, minCol = 20000, maxCol = -1;
1435
1436 int jj = 0;
1437
1438 std::vector<double> xRef;
1439 for (int i = 2; i < m_NeighborIDs[1]; i++) {
1440 int DetID = m_NeighborIDs[i];
1441
1442 size_t workspaceIndex;
1443 if (m_wi_to_detid_map.count(DetID) > 0)
1444 workspaceIndex = m_wi_to_detid_map.find(DetID)->second;
1445 else {
1446 throw std::runtime_error("No workspaceIndex for detID=" + std::to_string(DetID));
1447 }
1448
1449 IDetector_const_sptr Det = inpWkSpace->getDetector(workspaceIndex);
1450 V3D pixPos = Det->getPos();
1451
1452 if (i > 2)
1453 spec_idList += ",";
1454
1455 V3D dist = pixPos - CentPos;
1456 if (dist.scalar_prod(dist) < Radius * Radius)
1457
1458 {
1459 spec_idList += std::to_string(inpWkSpace->getSpectrum(workspaceIndex).getSpectrumNo());
1460
1461 double R1 = dist.scalar_prod(m_yvec);
1462 double R1a = R1 / m_cellHeight;
1463
1464 double row = m_ROW + R1a;
1465
1466 double C1 = dist.scalar_prod(m_xvec);
1467 double C1a = C1 / m_cellWidth;
1468
1469 double col = m_COL + C1a;
1470
1471 if (row > NBadEdges && col > NBadEdges && (m_NROWS < 0 || row < m_NROWS - NBadEdges) &&
1472 (m_NCOLS < 0 || col < m_NCOLS - NBadEdges)) {
1473 const auto &histogram = inpWkSpace->y(workspaceIndex);
1474
1475 const auto &histoerrs = inpWkSpace->e(workspaceIndex);
1476 double intensity = 0;
1477 double variance = 0;
1478 for (int chan = chanMin; chan <= chanMax; chan++) {
1479 intensity += histogram[chan];
1480 variance += histoerrs[chan] * histoerrs[chan];
1481 }
1482
1483 yvalB.emplace_back(intensity);
1484 double sigma = 1;
1485
1486 errB.emplace_back(sigma);
1487 xvalB.emplace_back(col);
1488 YvalB.emplace_back(row);
1489
1490 xRef.emplace_back(static_cast<double>(jj));
1491 jj++;
1492
1493 updateStats(intensity, variance, row, col, StatBase);
1494
1495 if ((pixPos - CentPos).norm() > BoundaryRadius) {
1496 TotBoundaryIntensities += intensity;
1497 nBoundaryCells++;
1498
1499 TotBoundaryVariances += variance;
1500 }
1501
1502 if (row < minRow)
1503 minRow = row;
1504 if (col < minCol)
1505 minCol = col;
1506 if (row > maxRow)
1507 maxRow = row;
1508 if (col > maxCol)
1509 maxCol = col;
1510
1511 } // if not bad edge
1512
1513 } // peak within radius
1514 } // for each neighbor
1515
1516 m_AttributeValues->EdgeY =
1517 max<double>(0.0, max<double>(-m_ROW + minRow + Radius / m_cellHeight, -maxRow + m_ROW + Radius / m_cellHeight));
1518 m_AttributeValues->EdgeX =
1519 max<double>(0.0, max<double>(-m_COL + minCol + Radius / m_cellWidth, -maxCol + m_COL + Radius / m_cellWidth));
1520 if (m_AttributeValues->EdgeY <= 1)
1521 m_AttributeValues->EdgeY = 0;
1522 if (m_AttributeValues->EdgeX <= 1)
1523 m_AttributeValues->EdgeX = 0;
1524
1525 auto pX = Kernel::make_cow<HistogramData::HistogramX>(std::move(xRef));
1526 // Set the shared X and the counts together so the Histogram size invariant holds. The
1527 // workspace was allocated with an upper-bound number of points and is resized here to the
1528 // number of valid neighbour pixels actually collected. Calling setSharedX on its own would
1529 // be rejected, because the not-yet-resized Y still has the original (larger) length.
1530 ws->setHistogram(0, Points(pX), Counts(yvalB), CountStandardDeviations(errB));
1531 ws->setHistogram(1, Points(pX), Counts(xvalB));
1532 ws->setHistogram(2, Points(pX), Counts(YvalB));
1533 m_AttributeValues->setHeightHalfWidthInfo(xvalB, YvalB, yvalB);
1534
1535 StatBase[IStartRow] = minRow;
1536 StatBase[IStartCol] = minCol;
1537 StatBase[INRows] = maxRow - minRow + 1;
1538 StatBase[INCol] = maxCol - minCol + 1;
1539
1540 StatBase[ITotBoundary] = TotBoundaryIntensities;
1541 StatBase[INBoundary] = nBoundaryCells;
1542 StatBase[IVarBoundary] = TotBoundaryVariances;
1543 m_EdgePeak = m_AttributeValues->setStatBase(StatBase);
1544
1545 m_ParameterValues[IBACK] = m_AttributeValues->getInitBackground();
1546 m_ParameterValues[ITINTENS] = m_AttributeValues->getInitIntensity();
1549 m_ParameterValues[IVXX] = m_AttributeValues->getInitVarx();
1550 m_ParameterValues[IVYY] = m_AttributeValues->getInitVary();
1551 m_ParameterValues[IVXY] = m_AttributeValues->getInitVarxy();
1552}
1553
1560int IntegratePeakTimeSlices::findTimeChannel(const HistogramX &X, const double time) {
1561 int sgn = 1;
1562
1563 if (X[0] > X[1])
1564 sgn = -1;
1565
1566 if (sgn * (X[0] - time) >= 0)
1567 return 0;
1568
1569 if (sgn * (time - X[X.size() - 1u]) >= 0)
1570 return static_cast<int>(X.size()) - 1;
1571
1572 size_t end = X.size() - 1u;
1573 for (size_t i = 0; i < end; i++) {
1574 if (sgn * (time - X[i]) >= 0 && sgn * (X[i + 1u] - time) >= 0)
1575 return static_cast<int>(i);
1576 }
1577
1578 return -1;
1579}
1580
1588bool DataModeHandler::isEdgePeak(const double *params, int nparams) {
1590 double Vary = Varx;
1591 if (nparams > 4) {
1592 Varx = params[IVXX];
1593 Vary = params[IVYY];
1594 }
1595
1596 if (Varx <= 0 || Vary <= 0 || HalfWidthAtHalfHeightRadius <= 0)
1597 return true;
1598
1599 double Rx = lastRCRadius / CellWidth - EdgeX; // span from center in x direction
1600 double Ry = lastRCRadius / CellHeight - EdgeY; // span from center in y direction
1601
1602 return Rx * Rx < NStdDevPeakSpan * NStdDevPeakSpan * std::max(Varx, VarxHW) ||
1603 Ry * Ry < NStdDevPeakSpan * NStdDevPeakSpan * std::max(Vary, VaryHW);
1604}
1605
1612
1613 std::ostringstream fun_str;
1614
1615 fun_str << "name=BivariateNormal,";
1616
1617 if (m_AttributeValues->CalcVariances())
1618 fun_str << "CalcVariances=1";
1619 else
1620 fun_str << "CalcVariances=-1";
1621
1622 int NN = NParameters;
1623 if (m_AttributeValues->CalcVariances())
1624 NN -= 3;
1625
1626 for (int i = 0; i < NN; i++) {
1627 fun_str << "," << m_ParameterNames[i] << "=" << m_ParameterValues[i];
1628 }
1629
1630 return fun_str.str();
1631}
1632
1641int IntegratePeakTimeSlices::findNameInVector(std::string const &oneName, std::vector<std::string> const &nameList)
1642
1643{
1644 const auto it = std::find(nameList.cbegin(), nameList.cend(), oneName);
1645 if (it != nameList.cend()) {
1646 return static_cast<int>(std::distance(nameList.cbegin(), it));
1647 }
1648 return -1;
1649}
1650
1657
1658 this->baseRCRadius = handler.baseRCRadius;
1659 this->lastRCRadius = handler.lastRCRadius;
1661 this->calcNewRCRadius = handler.calcNewRCRadius;
1662 this->lastRow = handler.lastRow;
1663 this->lastCol = handler.lastCol;
1664 this->time = handler.time;
1665 this->CellWidth = handler.CellWidth;
1666 this->CellHeight = handler.CellHeight;
1667 this->currentRadius = handler.currentRadius;
1668 this->currentPosition = handler.currentPosition;
1669 this->StatBase = handler.StatBase;
1670 this->EdgeX = handler.EdgeX;
1671 this->EdgeY = handler.EdgeY;
1672 this->CalcVariance = handler.CalcVariance;
1673 this->VarxHW = handler.VarxHW;
1674 this->VaryHW = handler.VaryHW;
1675 this->MaxRow = handler.MaxRow;
1676 this->MaxCol = handler.MaxCol;
1677 this->MinRow = handler.MinRow;
1678 this->MinCol = handler.MinCol;
1679 this->lastISAWIntensity = handler.lastISAWIntensity;
1680 this->lastISAWVariance = handler.lastISAWIntensity;
1681 this->back_calc = handler.back_calc;
1682 this->Intensity_calc = handler.Intensity_calc;
1683 this->row_calc = handler.row_calc;
1684 this->col_calc = handler.col_calc;
1685 this->Vx_calc = handler.Vx_calc;
1686 this->Vy_calc = handler.Vy_calc;
1687 this->Vxy_calc = handler.Vxy_calc;
1688 this->case4 = handler.case4;
1689}
1704void DataModeHandler::CalcVariancesFromData(double background, double meanx, double meany, double &Varxx, double &Varxy,
1705 double &Varyy, const std::vector<double> &StatBase) {
1706
1707 double Den = StatBase[IIntensities] - background * StatBase[ISS1];
1708 Varxx = (StatBase[ISSIxx] - 2 * meanx * StatBase[ISSIx] + meanx * meanx * StatBase[IIntensities] -
1709 background * (StatBase[ISSxx] - 2 * meanx * StatBase[ISSx] + meanx * meanx * StatBase[ISS1])) /
1710 Den;
1711
1712 Varyy = (StatBase[ISSIyy] - 2 * meany * StatBase[ISSIy] + meany * meany * StatBase[IIntensities] -
1713 background * (StatBase[ISSyy] - 2 * meany * StatBase[ISSy] + meany * meany * StatBase[ISS1])) /
1714 Den;
1715
1716 Varxy =
1717 (StatBase[ISSIxy] - meanx * StatBase[ISSIy] - meany * StatBase[ISSIx] + meanx * meany * StatBase[IIntensities] -
1718 background *
1719 (StatBase[ISSxy] - meanx * StatBase[ISSy] - meany * StatBase[ISSx] + meanx * meany * StatBase[ISS1])) /
1720 Den;
1721
1722 if (CalcVariances()) {
1723
1724 Varxx = std::min(Varxx, 1.21 * getInitVarx()); // copied from BiVariateNormal
1725 Varxx = std::max(Varxx, .79 * getInitVarx());
1726 Varyy = std::min(Varyy, 1.21 * getInitVary());
1727 Varyy = std::max(Varyy, .79 * getInitVary());
1728 }
1729}
1736std::string DataModeHandler::CalcConstraints(std::vector<std::pair<double, double>> &Bounds, bool CalcVariances) {
1737 double TotIntensity = StatBase[IIntensities];
1738 double ncells = StatBase[ISS1];
1739 double Variance = StatBase[IVariance];
1740 double TotBoundaryIntensities = StatBase[ITotBoundary];
1741 double TotBoundaryVariances = StatBase[IVarBoundary];
1742
1743 double nBoundaryCells = StatBase[INBoundary];
1744 double back = TotBoundaryIntensities / nBoundaryCells;
1745 double backVar = std::max(nBoundaryCells / 50.0, TotBoundaryVariances) / nBoundaryCells / nBoundaryCells;
1746 double IntensVar = Variance + ncells * ncells * backVar;
1747
1748 double relError = .25;
1749
1750 if (back_calc != back)
1751 relError = .45;
1752
1753 int N = NParameters;
1754 if (CalcVariances)
1755 N = N - 3;
1756
1757 double NSigs = NStdDevPeakSpan;
1758 if (back_calc > 0)
1759 NSigs = std::max(NStdDevPeakSpan,
1760 7 - 5 * back_calc / back); // background too high
1761 ostringstream str;
1762
1763 NSigs *= max<double>(1.0, Intensity_calc / (TotIntensity - ncells * back_calc));
1764 str << max<double>(0.0, back_calc - NSigs * (1 + relError) * sqrt(backVar)) << "<Background<"
1765 << (back + NSigs * (1.8 + relError) * sqrt(backVar)) << ","
1766 << max<double>(0.0, Intensity_calc - NSigs * (1 + relError) * sqrt(IntensVar)) << "<Intensity<"
1767 << Intensity_calc + NSigs * (1 + relError) * sqrt(IntensVar);
1768
1769 double min = max<double>(0.0, back_calc - NSigs * (1 + relError) * sqrt(backVar));
1770 double maxx = back + NSigs * (1.8 + relError) * sqrt(backVar);
1771 Bounds.emplace_back(min, maxx);
1772 Bounds.emplace_back(max<double>(0.0, Intensity_calc - NSigs * (1 + relError) * sqrt(IntensVar)),
1773 Intensity_calc + NSigs * (1 + relError) * sqrt(IntensVar));
1774 double relErr1 = relError * .75;
1775 double val = col_calc;
1776 double minn = std::max(MinCol - .5, (1 - relErr1) * val);
1777 maxx = std::min((1 + relErr1) * val, MaxCol + .5);
1778
1779 str << "," << minn << "<"
1780 << "Mcol"
1781 << "<" << maxx;
1782 Bounds.emplace_back(minn, maxx);
1783
1784 val = row_calc;
1785
1786 minn = std::max(MinRow - .5, (1 - relErr1) * val);
1787 maxx = std::min((1 + relErr1) * val, MaxRow + .5);
1788 str << "," << minn << "<"
1789 << "Mrow"
1790 << "<" << maxx;
1791 Bounds.emplace_back(minn, maxx);
1792
1793 if (N >= 5) {
1794 val = Vx_calc;
1795 double valmin = val;
1796 double valmax = val;
1797 if (VarxHW > 0) {
1798 valmin = std::min(val, VarxHW);
1799 valmax = std::max(val, VarxHW);
1800 }
1801
1802 relErr1 *= .6; // Edge peaks: need to restrict sigmas.
1803 str << "," << (1 - relErr1) * valmin << "<"
1804 << "SScol"
1805 << "<" << (1 + relErr1) * valmax;
1806 Bounds.emplace_back((1 - relErr1) * valmin, (1 + relErr1) * valmax);
1807
1808 val = Vy_calc;
1809 valmin = val;
1810 valmax = val;
1811 if (VaryHW > 0) {
1812 valmin = std::min(val, VaryHW);
1813 valmax = std::max(val, VaryHW);
1814 }
1815 str << "," << (1 - relErr1) * valmin << "<"
1816 << "SSrow"
1817 << "<" << (1 + relErr1) * valmax;
1818 Bounds.emplace_back((1 - relErr1) * valmin, (1 + relErr1) * valmax);
1819 }
1820
1821 return str.str();
1822}
1823
1838void IntegratePeakTimeSlices::Fit(const MatrixWorkspace_sptr &Data, double &chisqOverDOF, bool &done,
1839 std::vector<string> &names, std::vector<double> &params, std::vector<double> &errs,
1840 double lastRow, double lastCol, double neighborRadius) {
1841
1842 bool CalcVars = m_AttributeValues->CalcVariances();
1843 std::vector<std::pair<double, double>> Bounds;
1844 std::string Constraints = m_AttributeValues->CalcConstraints(Bounds, CalcVars);
1845 auto fit_alg = createChildAlgorithm("Fit");
1846 std::string fun_str = CalculateFunctionProperty_Fit();
1847
1848 std::string SSS(" Fit string ");
1849 SSS += fun_str;
1850 g_log.debug(SSS);
1851 g_log.debug() << " TotCount=" << m_AttributeValues->StatBase[IIntensities] << '\n';
1852
1853 fit_alg->setPropertyValue("Function", fun_str);
1854
1855 fit_alg->setProperty("InputWorkspace", Data);
1856 fit_alg->setProperty("WorkspaceIndex", 0);
1857 fit_alg->setProperty("StartX", 0.0);
1858 fit_alg->setProperty("EndX", 0.0 + static_cast<double>(m_NeighborIDs[1]));
1859 fit_alg->setProperty("MaxIterations", 5000);
1860 fit_alg->setProperty("CreateOutput", true);
1861
1862 fit_alg->setProperty("Output", "out");
1863
1864 fit_alg->setProperty("MaxIterations", 50);
1865
1866 std::string tie = getProperty("Ties");
1867 if (tie.length() > static_cast<size_t>(0))
1868 fit_alg->setProperty("Ties", tie);
1869 if (Constraints.length() > static_cast<size_t>(0))
1870 fit_alg->setProperty("Constraints", Constraints);
1871 try {
1872 fit_alg->executeAsChildAlg();
1873
1874 chisqOverDOF = fit_alg->getProperty("OutputChi2overDoF");
1875 std::string outputStatus = fit_alg->getProperty("OutputStatus");
1876 g_log.debug() << "Chisq/OutputStatus=" << chisqOverDOF << "/" << outputStatus << '\n';
1877
1878 names.clear();
1879 params.clear();
1880 errs.clear();
1881 ITableWorkspace_sptr RRes = fit_alg->getProperty("OutputParameters");
1882 for (int prm = 0; prm < static_cast<int>(RRes->rowCount()) - 1; prm++) {
1883 names.emplace_back(RRes->getRef<string>("Name", prm));
1884 params.emplace_back(RRes->getRef<double>("Value", prm));
1885 double error = RRes->getRef<double>("Error", prm);
1886 errs.emplace_back(error);
1887 }
1888 if (names.size() < 5) {
1889 names.emplace_back(m_ParameterNames[IVXX]);
1890 names.emplace_back(m_ParameterNames[IVYY]);
1891 names.emplace_back(m_ParameterNames[IVXY]);
1892 double Varxx, Varxy, Varyy;
1893 m_AttributeValues->CalcVariancesFromData(params[IBACK], params[IXMEAN], params[IYMEAN], Varxx, Varxy, Varyy,
1894 m_AttributeValues->StatBase);
1895 params.emplace_back(Varxx);
1896 params.emplace_back(Varyy);
1897 params.emplace_back(Varxy);
1898 errs.emplace_back(0);
1899 errs.emplace_back(0);
1900 errs.emplace_back(0);
1901 }
1902
1903 } catch (std::exception &Ex1) // ties or something else went wrong in BivariateNormal
1904 {
1905 done = true;
1906 g_log.error() << "Bivariate Error for PeakNum=" << static_cast<int>(getProperty("PeakIndex")) << ":"
1907 << std::string(Ex1.what()) << '\n';
1908 } catch (...) {
1909 done = true;
1910 g_log.error() << "Bivariate Error A for peakNum=" << static_cast<int>(getProperty("PeakIndex")) << '\n';
1911 }
1912 if (!done) // Bivariate error happened
1913 {
1914
1915 g_log.debug() << " Thru Algorithm: chiSq=" << setw(7) << chisqOverDOF << '\n';
1916 g_log.debug() << " Row,Col Radius=" << lastRow << "," << lastCol << "," << neighborRadius << '\n';
1917
1918 double sqrtChisq = -1;
1919 if (chisqOverDOF >= 0)
1920 sqrtChisq = (chisqOverDOF);
1921
1922 sqrtChisq =
1923 max<double>(sqrtChisq, m_AttributeValues->StatBaseVals(IIntensities) / m_AttributeValues->StatBaseVals(ISS1));
1924 sqrtChisq = SQRT(sqrtChisq);
1925
1926 for (size_t kk = 0; kk < params.size(); kk++) {
1927 g_log.debug() << " Parameter " << setw(8) << names[kk] << " " << setw(8) << params[kk];
1928 // if (names[kk].substr(0, 2) != string("SS"))
1929 g_log.debug() << "(" << setw(8) << (errs[kk] * sqrtChisq) << ")";
1930 if (Bounds.size() > kk) {
1931 pair<double, double> upLow = Bounds[kk];
1932 g_log.debug() << " Bounds(" << upLow.first << "," << upLow.second << ")";
1933 }
1934 g_log.debug() << '\n';
1935 }
1936
1937 double intensity = m_AttributeValues->CalcISAWIntensity(params.data());
1938 g_log.debug() << "IsawIntensity= " << intensity << '\n';
1939 }
1940}
1941
1958void IntegratePeakTimeSlices::PreFit(const MatrixWorkspace_sptr &Data, double &chisqOverDOF, bool &done,
1959 std::vector<string> &names, std::vector<double> &params, std::vector<double> &errs,
1960 double lastRow, double lastCol, double neighborRadius) {
1961
1963 int N = 3;
1964 if (background <= 0) {
1965 background = 0;
1966 N = 1;
1967 }
1968 bool CalcVars = m_AttributeValues->CalcVariances();
1969 int NParams = 4;
1970 if (!CalcVars)
1971 NParams += 3;
1972
1973 double minChiSqOverDOF = -1;
1974 double Bestparams[7];
1975 std::string Bestnames[7];
1976 for (int i = 0; i < N; i++) {
1977 Fit(Data, chisqOverDOF, done, names, params, errs, lastRow, lastCol, neighborRadius);
1978 g_log.debug() << "-----------------------" << i << "--------------------------\n";
1979 if ((minChiSqOverDOF < 0 || chisqOverDOF < minChiSqOverDOF) && (chisqOverDOF > 0) && !done) {
1980 for (int j = 0; j < NParams; j++) {
1981 Bestparams[j] = m_ParameterValues[j];
1982 Bestnames[j] = m_ParameterNames[j];
1983 }
1984 minChiSqOverDOF = chisqOverDOF;
1985 }
1986
1987 // Next round, reduce background
1988 background = background / 2;
1989 if (i + 1 == N - 1)
1990 background = 0;
1991
1992 std::vector<double> prms = m_AttributeValues->GetParams(background);
1993
1994 for (int j = 0; j < NParams; j++)
1995 m_ParameterValues[j] = prms[j];
1996 }
1997 vector<std::string> ParNames(m_ParameterNames, m_ParameterNames + NParams);
1998 for (int i = 0; i < NParams; i++) {
1999 int k = findNameInVector(Bestnames[i], ParNames);
2000 if (k >= 0 && k < NParams)
2001 m_ParameterValues[k] = Bestparams[k];
2002 }
2003
2004 Fit(Data, chisqOverDOF, done, names, params, errs, lastRow, lastCol, neighborRadius);
2005}
2006
2017bool IntegratePeakTimeSlices::isGoodFit(std::vector<double> const &params, std::vector<double> const &errs,
2018 std::vector<std::string> const &names, double chisqOverDOF) {
2019 int Ibk = findNameInVector("Background", names);
2020 if (Ibk < 0)
2021 throw std::runtime_error("Irrecoverable inconsistency found. The index for the "
2022 "parameter 'Background' is lower than zero.");
2023
2024 int IIntensity = findNameInVector("Intensity", names);
2025 if (IIntensity < 0)
2026 throw std::runtime_error("Irrecoverable inconsistency found. The index for the "
2027 "parameter 'Intensity' is lower than zero.");
2028
2029 if (chisqOverDOF < 0) {
2030
2031 g_log.debug() << " Bad Slice- negative chiSq= " << chisqOverDOF << '\n';
2032 ;
2033 return false;
2034 }
2035
2036 int NBadEdgeCells = getProperty("NBadEdgePixels");
2037 NBadEdgeCells = static_cast<int>(.6 * NBadEdgeCells);
2038 if (params[IXMEAN] < NBadEdgeCells || params[IYMEAN] < NBadEdgeCells || params[IXMEAN] > m_NCOLS - NBadEdgeCells ||
2039 params[IYMEAN] > m_NROWS - NBadEdgeCells)
2040 return false;
2041
2042 auto ncells = static_cast<int>(m_AttributeValues->StatBaseVals(ISS1));
2043
2044 if (m_AttributeValues->StatBaseVals(IIntensities) <= 0 ||
2045 (m_AttributeValues->StatBaseVals(IIntensities) - params[Ibk] * ncells) <= 0) {
2046
2047 g_log.debug() << " Bad Slice. Negative Counts= "
2048 << m_AttributeValues->StatBaseVals(IIntensities) - params[Ibk] * ncells << '\n';
2049 ;
2050 return false;
2051 }
2052
2053 double x = params[IIntensity] / (m_AttributeValues->StatBaseVals(IIntensities) - params[Ibk] * ncells);
2054
2055 if ((x < MinGoodRatioFitvsExpIntenisites || x > MaxGoodRatioFitvsExpIntenisites) &&
2056 !m_EdgePeak) // The fitted intensity should be close to tot intensity -
2057 // background
2058 {
2059 g_log.debug() << " Bad Slice. Fitted Intensity & Observed "
2060 "Intensity(-back) too different. ratio="
2061 << x << '\n';
2062
2063 return false;
2064 }
2065
2066 bool GoodNums = true;
2067 bool paramBad = false;
2068 auto BadParamNum = static_cast<size_t>(-1);
2069 for (size_t i = 0; i < errs.size(); i++)
2070 if (errs[i] != errs[i]) {
2071 GoodNums = false;
2072 paramBad = false;
2073 BadParamNum = i;
2074 } else if (errs[i] < 0) {
2075 GoodNums = false;
2076 paramBad = false;
2077 BadParamNum = i;
2078 } else if (params[i] != params[i]) {
2079 GoodNums = false;
2080 paramBad = true;
2081 BadParamNum = i;
2082 }
2083
2084 if (!GoodNums) {
2085 std::string obj = " parameter ";
2086 if (!paramBad)
2087 obj = " error ";
2088 g_log.debug() << " Bad Slice." << obj << BadParamNum << " is not a number\n";
2089 return false;
2090 }
2091
2092 GoodNums = true;
2093
2094 std::string Err("back ground is negative");
2095 if (params[Ibk] < -.002)
2096 GoodNums = false;
2097
2098 if (GoodNums)
2099 Err = "Intensity is negative";
2100 if (params[IIntensity] < 0)
2101 GoodNums = false;
2102
2103 double IsawIntensity = m_AttributeValues->CalcISAWIntensity(params.data());
2104 double IsawVariance = m_AttributeValues->CalcISAWIntensityVariance(params.data(), errs.data(), chisqOverDOF);
2105 if (GoodNums)
2106 Err = "Isaw Variance is negative";
2107 if (IsawVariance > 0) {
2108 if (GoodNums)
2109 Err = "I/sigI > 3";
2110 if (IsawIntensity * IsawIntensity / IsawVariance < MinGoodIoverSigI * MinGoodIoverSigI)
2111 GoodNums = false;
2112 } else
2113 GoodNums = false;
2114
2115 if (!GoodNums)
2116
2117 {
2118 g_log.debug() << Err << '\n';
2119
2120 return false;
2121 }
2122
2123 // Check weak peak. Max theoretical height should be more than 3
2124
2125 double maxPeakHeightTheoretical =
2126 params[ITINTENS] / 2 / M_PI / sqrt(params[IVXX] * params[IVYY] - params[IVXY] * params[IVXY]);
2127
2128 double AvHeight =
2129 m_AttributeValues->StatBaseVals(IIntensities) / m_AttributeValues->StatBaseVals(ISS1) - params[IBACK];
2130
2131 if (maxPeakHeightTheoretical < 2 * AvHeight || AvHeight < 0 || maxPeakHeightTheoretical < 0) {
2132
2133 g_log.debug() << " Bad Slice. Peak too small= " << maxPeakHeightTheoretical << "/" << AvHeight << '\n';
2134 return false;
2135 }
2136
2137 double Nrows = std::max(m_AttributeValues->StatBase[INRows], m_AttributeValues->StatBase[INCol]);
2138 if (maxPeakHeightTheoretical < 1 && (params[IVXX] > Nrows * Nrows / 4 || params[IVYY] > Nrows * Nrows / 4)) {
2139 g_log.debug() << "Peak is too flat \n";
2140 return false;
2141 }
2142
2143 // Exponential too steep, i.e. intensities at pixels 1 from center are <3*
2144 // intensity center
2145 if (params[IVXX] + params[IVYY] > 2.6 * (params[IVXX] * params[IVYY] - params[IVXY] * params[IVXY])) {
2146 g_log.debug() << " Bad Slice. Too steep of an exponential\n";
2147 return false;
2148 }
2149
2150 return true;
2151}
2152
2159bool DataModeHandler::IsEnoughData(const double *ParameterValues, Kernel::Logger & /*unused*/) {
2160 // Check if flat
2161 double Varx, Vary, Cov;
2162
2163 if (StatBase.empty())
2164 return false;
2165
2166 double ncells = static_cast<int>(StatBase[IIntensities]);
2167 if (ncells <= 0)
2168 return false;
2169
2170 double meanx = StatBase[ISSIx] / ncells;
2171 double meany = StatBase[ISSIy] / ncells;
2172
2173 if (!CalcVariances()) {
2174 Varx = ParameterValues[IVXX];
2175 Vary = ParameterValues[IVYY];
2176 Cov = ParameterValues[IVXY];
2177
2178 } else
2179 CalcVariancesFromData(ParameterValues[0], meanx, meany, Varx, Cov, Vary, StatBase);
2180
2181 if (Varx < MinVariationInXYvalues || Vary < MinVariationInXYvalues) // All data essentially the same.
2182 return false;
2183
2184 if (Cov * Cov > MaxCorrCoeffinXY * Varx * Vary) // All data on a obtuse line
2185 return false;
2186
2187 return true;
2188}
2189
2202double IntegratePeakTimeSlices::CalculateIsawIntegrateError(const double background, const double backError,
2203 const double ChiSqOverDOF, const double TotVariance,
2204 const int ncells) {
2205
2206 double B = TotVariance / ncells;
2207 if (B < ChiSqOverDOF)
2208 B = ChiSqOverDOF;
2209
2210 double Variance = TotVariance + (backError * backError * B) * ncells * ncells + background * ncells;
2211
2212 return SQRT(Variance);
2213}
2214
2221 // TabWS->setName("Log Table");
2222 TabWS->addColumn("double", "Time");
2223 TabWS->addColumn("double", "Channel");
2224 TabWS->addColumn("double", "Background");
2225 TabWS->addColumn("double", "Intensity");
2226 TabWS->addColumn("double", "Mcol");
2227 TabWS->addColumn("double", "Mrow");
2228 TabWS->addColumn("double", "SScol");
2229 TabWS->addColumn("double", "SSrow");
2230 TabWS->addColumn("double", "SSrc");
2231 TabWS->addColumn("double", "NCells");
2232 TabWS->addColumn("double", "ChiSqrOverDOF");
2233 TabWS->addColumn("double", "TotIntensity");
2234 TabWS->addColumn("double", "BackgroundError");
2235 TabWS->addColumn("double", "FitIntensityError");
2236 TabWS->addColumn("double", "ISAWIntensity");
2237 TabWS->addColumn("double", "ISAWIntensityError");
2238 TabWS->addColumn("double", "TotalBoundary");
2239 TabWS->addColumn("double", "NBoundaryCells");
2240 TabWS->addColumn("double", "Start Row");
2241 TabWS->addColumn("double", "End Row");
2242 TabWS->addColumn("double", "Start Col");
2243 TabWS->addColumn("double", "End Col");
2244 TabWS->addColumn("double", "TotIntensityError");
2245 TabWS->addColumn("str", "SpecIDs");
2246}
2247
2266 std::vector<double> const &params, std::vector<double> const &errs,
2267 std::vector<std::string> const &names, const double Chisq,
2268 const double time, string spec_idList) {
2269 int Ibk = findNameInVector("Background", names);
2270 int IIntensity = findNameInVector("Intensity", names);
2271 int IVx = findNameInVector("SScol", names);
2272 int IVy = findNameInVector("SSrow", names);
2273 int IVxy = findNameInVector("SSrc", names);
2274 int Irow = findNameInVector("Mrow", names);
2275 int Icol = findNameInVector("Mcol", names);
2276
2277 if (Ibk < 0 || IIntensity < 0 || IVx < 0 || IVy < 0 || IVxy < 0 || Irow < 0 || Icol < 0) {
2278 throw std::runtime_error("Inconsistency found when updating output "
2279 "workspace. None of the indices for the "
2280 "parameters 'Background', 'Intensity', 'SScol', "
2281 "'SSrow', 'SSrc', 'Mrow', 'Mcol' can be "
2282 "negative.");
2283 }
2284
2285 int newRowIndex = 0;
2286
2287 if (dir > 0)
2288 newRowIndex = static_cast<int>(TabWS->rowCount());
2289
2290 auto TableRow = static_cast<int>(TabWS->insertRow(newRowIndex));
2291
2292 auto ncells = static_cast<int>(m_AttributeValues->StatBaseVals(ISS1));
2293 double chisq = max<double>(Chisq, m_AttributeValues->StatBaseVals(IIntensities) / max<int>(ncells, 1));
2294
2295 TabWS->getRef<double>(std::string("Background"), TableRow) = params[Ibk];
2296 TabWS->getRef<double>(std::string("Channel"), TableRow) = chan;
2297
2298 TabWS->getRef<double>(std::string("Intensity"), TableRow) = params[IIntensity];
2299 TabWS->getRef<double>(std::string("FitIntensityError"), TableRow) = errs[IIntensity] * sqrt(chisq);
2300 TabWS->getRef<double>(std::string("Mcol"), TableRow) = params[Icol];
2301 TabWS->getRef<double>(std::string("Mrow"), TableRow) = params[Irow];
2302
2303 TabWS->getRef<double>(std::string("SScol"), TableRow) = params[IVx];
2304 TabWS->getRef<double>(std::string("SSrow"), TableRow) = params[IVy];
2305
2306 TabWS->getRef<double>(std::string("SSrc"), TableRow) = params[IVxy];
2307 TabWS->getRef<double>(std::string("NCells"), TableRow) = ncells;
2308 TabWS->getRef<double>(std::string("ChiSqrOverDOF"), TableRow) = chisq;
2309
2310 TabWS->getRef<double>(std::string("TotIntensity"), TableRow) = m_AttributeValues->StatBaseVals(IIntensities);
2311 TabWS->getRef<double>(std::string("BackgroundError"), TableRow) = errs[Ibk] * SQRT(chisq);
2312 TabWS->getRef<double>(std::string("ISAWIntensity"), TableRow) = m_AttributeValues->CalcISAWIntensity(params.data());
2313 // m_AttributeValues->StatBaseVals(IIntensities)
2314 // -
2315 // params[Ibk]
2316 // * ncells;
2317
2318 TabWS->getRef<double>(std::string("ISAWIntensityError"), TableRow) =
2319 sqrt(m_AttributeValues->CalcISAWIntensityVariance(params.data(), errs.data(), Chisq));
2320
2321 // CalculateIsawIntegrateError(
2322 // params[Ibk], errs[Ibk], chisq, m_AttributeValues->StatBaseVals(IVariance),
2323 // ncells);
2324
2325 TabWS->getRef<double>(std::string("Time"), TableRow) = time;
2326
2327 TabWS->getRef<double>(std::string("TotalBoundary"), TableRow) = m_AttributeValues->StatBaseVals(ITotBoundary);
2328 TabWS->getRef<double>(std::string("NBoundaryCells"), TableRow) = m_AttributeValues->StatBaseVals(INBoundary);
2329
2330 TabWS->getRef<double>(std::string("Start Row"), TableRow) = m_AttributeValues->StatBaseVals(IStartRow);
2331 TabWS->getRef<double>(std::string("End Row"), TableRow) =
2332 m_AttributeValues->StatBaseVals(IStartRow) + m_AttributeValues->StatBaseVals(INRows) - 1;
2333
2334 TabWS->getRef<double>(std::string("Start Col"), TableRow) = m_AttributeValues->StatBaseVals(IStartCol);
2335 TabWS->getRef<double>(std::string("End Col"), TableRow) =
2336 m_AttributeValues->StatBaseVals(IStartCol) + m_AttributeValues->StatBaseVals(INCol) - 1;
2337 TabWS->getRef<double>(std::string("TotIntensityError"), TableRow) = SQRT(m_AttributeValues->StatBaseVals(IVariance));
2338 TabWS->getRef<string>(std::string("SpecIDs"), TableRow) = std::move(spec_idList);
2339
2340 return newRowIndex;
2341}
2342
2357void IntegratePeakTimeSlices::updatePeakInformation(std::vector<double> const &params, std::vector<double> const &errs,
2358 std::vector<std::string> const &names, double &TotVariance,
2359 double &TotIntensity, double const TotSliceIntensity,
2360 double const TotSliceVariance, double const chisqdivDOF,
2361 const int ncells) {
2362 UNUSED_ARG(TotSliceIntensity);
2363 UNUSED_ARG(TotSliceVariance);
2364 UNUSED_ARG(names);
2365 UNUSED_ARG(ncells);
2366
2367 double err = 0;
2368 double intensity = 0;
2369
2370 err = m_AttributeValues->CalcISAWIntensityVariance(params.data(), errs.data(), chisqdivDOF);
2371
2372 intensity = m_AttributeValues->CalcISAWIntensity(params.data());
2373 TotIntensity += intensity;
2374
2375 TotVariance += err;
2376 g_log.debug() << "TotIntensity/TotVariance=" << TotIntensity << "/" << TotVariance << '\n';
2377}
2378
2388 if (!CalcVariance)
2389 return false;
2390
2391 const double param[7] = {back_calc, Intensity_calc, col_calc, row_calc, Vx_calc, Vy_calc, Vxy_calc};
2392 return !isEdgePeak(param, 7);
2393}
2394
2404double DataModeHandler::CalcISAWIntensity(const double *params) {
2405
2406 double ExperimentalIntensity = StatBase[IIntensities] - params[IBACK] * StatBase[ISS1];
2407
2408 double r = CalcSampleIntensityMultiplier(params);
2409
2410 double alpha = .5 * (r - 1.0);
2411 alpha = std::min(1.0, alpha);
2412
2413 lastISAWIntensity = ExperimentalIntensity * r; //*( 1-alpha )+ alpha * FitIntensity;
2414 return lastISAWIntensity;
2415}
2426double DataModeHandler::CalcISAWIntensityVariance(const double *params, const double *errs, double chiSqOvDOF) {
2427
2428 auto ncells = static_cast<int>(StatBase[ISS1]);
2429 double B = StatBase[IVariance] / ncells;
2430 if (B < chiSqOvDOF)
2431 B = chiSqOvDOF;
2432
2433 double ExperimVar = StatBase[IVariance];
2434 double IntensityBackError = errs[IBACK] * sqrt(B);
2435
2436 ExperimVar += IntensityBackError * IntensityBackError * ncells * ncells + params[IBACK] * ncells;
2437
2438 double r = CalcSampleIntensityMultiplier(params);
2439 double alpha = .5 * (r - 1.0);
2440 alpha = std::min(1.0, alpha);
2441
2442 lastISAWVariance = ExperimVar * r * r; //*( 1 - alpha ) + alpha * FitVar;
2443 return lastISAWVariance;
2444}
2445
2454double DataModeHandler::CalcSampleIntensityMultiplier(const double *params) const {
2455 auto minRow = static_cast<int>(StatBase[IStartRow]);
2456 int maxRow = minRow + static_cast<int>(StatBase[INRows]) - 1;
2457 auto minCol = static_cast<int>(StatBase[IStartCol]);
2458 int maxCol = minCol + static_cast<int>(StatBase[INCol]) - 1;
2459 double r = 1;
2460
2461 if (params[IVXX] <= 0 || params[IVYY] <= 0)
2462 return 1.0;
2463
2464 // NstdX iand NstdY are the number of 1/4 standard deviations. Elements of
2465 // probs are in
2466 // 1/4 standard deviations
2467 double NstdX = 4 * min<double>(params[IXMEAN] - minCol, maxCol - params[IXMEAN]) / sqrt(params[IVXX]);
2468
2469 double NstdY = 4 * min<double>(params[IYMEAN] - minRow, maxRow - params[IYMEAN]) / sqrt(params[IVYY]);
2470
2471 double sgn = 1;
2472 if (NstdX < 0) {
2473 sgn = -1;
2474 }
2475 double P = 1;
2476 if (sgn * NstdX < 9) {
2477 auto xx = static_cast<int>(sgn * NstdX);
2478 double a = probs[xx];
2479 double b = 1;
2480 if (xx + 1 <= 8)
2481 b = probs[xx + 1];
2482 P = a + (b - a) * (sgn * NstdX - xx);
2483 }
2484 if (NstdX >= 7.5)
2485 r = 1.0;
2486 else if (sgn > 0)
2487 r = 1 / P;
2488 else
2489 r = 1 / (1 - P);
2490
2491 if (NstdY < 0) {
2492 sgn = -1;
2493 }
2494 P = 1;
2495 if (sgn * NstdY < 9) {
2496 auto xx = static_cast<int>(sgn * NstdY);
2497 double a = probs[xx];
2498 double b = 1;
2499 if (xx + 1 <= 8)
2500 b = probs[xx + 1];
2501 P = a + (b - a) * (sgn * NstdY - xx);
2502 }
2503 if (NstdY >= 7.5)
2504 r *= 1.0;
2505 else if (sgn > 0)
2506 r *= 1 / P;
2507 else
2508 r *= 1 / (1 - P);
2509
2510 r = std::max(r, 1.0);
2511 return r;
2512}
2513
2514} // namespace Mantid::Crystal
2515// 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:165
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