Mantid
Loading...
Searching...
No Matches
IntegrateEllipsoidsV1.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 +
11#include "MantidAPI/Run.h"
12#include "MantidAPI/Sample.h"
23#include "MantidHistogramData/LinearGenerator.h"
31
32#include <boost/math/special_functions/round.hpp>
33#include <cmath>
34
35using namespace Mantid::API;
36using namespace Mantid::HistogramData;
37using namespace Mantid::Kernel;
38using namespace Mantid::Geometry;
39using namespace Mantid::DataObjects;
40
41namespace Mantid {
42namespace MDAlgorithms {
43
45const std::string ELASTIC("Elastic");
46
48const std::string Q3D("Q3D");
49
51const std::size_t DIMS(3);
52
62 DblMatrix const &UBinv, bool hkl_integ) {
63 // loop through the eventlists
64
65 auto numSpectra = static_cast<int>(wksp->getNumberHistograms());
67 for (int i = 0; i < numSpectra; ++i) {
69
70 // units conversion helper
71 UnitsConversionHelper unitConverter;
72 unitConverter.initialize(m_targWSDescr, "Momentum");
73
74 // initialize the MD coordinates conversion class
75 MDTransfQ3D qConverter;
76 qConverter.initialize(m_targWSDescr);
77
78 std::vector<double> buffer(DIMS);
79 // get a reference to the event list
80 EventList &events = wksp->getSpectrum(i);
81
83 events.compressEvents(1e-5, &events);
84
85 // check to see if the event list is empty
86 if (events.empty()) {
87 prog.report();
88 continue; // nothing to do
89 }
90
91 // update which pixel is being converted
92 std::vector<Mantid::coord_t> locCoord(DIMS, 0.);
93 unitConverter.updateConversion(i);
94 qConverter.calcYDepCoordinates(locCoord, i);
95
96 // loop over the events
97 double signal(1.); // ignorable garbage
98 double errorSq(1.); // ignorable garbage
99 const std::vector<WeightedEventNoTime> &raw_events = events.getWeightedEventsNoTime();
100 std::vector<std::pair<std::pair<double, double>, V3D>> qList;
101 for (const auto &raw_event : raw_events) {
102 double val = unitConverter.convertUnits(raw_event.tof());
103 qConverter.calcMatrixCoord(val, locCoord, signal, errorSq);
104 for (size_t dim = 0; dim < DIMS; ++dim) {
105 buffer[dim] = locCoord[dim];
106 }
107 V3D qVec(buffer[0], buffer[1], buffer[2]);
108 if (hkl_integ)
109 qVec = UBinv * qVec;
110 qList.emplace_back(std::pair<double, double>(raw_event.m_weight, raw_event.m_errorSquared), qVec);
111 } // end of loop over events in list
112 PARALLEL_CRITICAL(addEvents) { integrator.addEvents(qList, hkl_integ); }
113
114 prog.report();
116 } // end of loop over spectra
118}
119
130 DblMatrix const &UBinv, bool hkl_integ) {
131
132 // loop through the eventlists
133
134 auto numSpectra = static_cast<int>(wksp->getNumberHistograms());
136 for (int i = 0; i < numSpectra; ++i) {
138
139 // units conversion helper
140 UnitsConversionHelper unitConverter;
141 unitConverter.initialize(m_targWSDescr, "Momentum");
142
143 // initialize the MD coordinates conversion class
144 MDTransfQ3D qConverter;
145 qConverter.initialize(m_targWSDescr);
146
147 std::vector<double> buffer(DIMS);
148 // get tof and y values
149 const auto &xVals = wksp->points(i);
150 const auto &yVals = wksp->y(i);
151 const auto &eVals = wksp->e(i);
152
153 // update which pixel is being converted
154 std::vector<Mantid::coord_t> locCoord(DIMS, 0.);
155 unitConverter.updateConversion(i);
156 qConverter.calcYDepCoordinates(locCoord, i);
157
158 // loop over the events
159 double signal(1.); // ignorable garbage
160 double errorSq(1.); // ignorable garbage
161
162 std::vector<std::pair<std::pair<double, double>, V3D>> qList;
163
164 for (size_t j = 0; j < yVals.size(); ++j) {
165 const double &yVal = yVals[j];
166 const double &esqVal = eVals[j] * eVals[j]; // error squared (variance)
167 if (yVal > 0) // TODO, is this condition right?
168 {
169 double val = unitConverter.convertUnits(xVals[j]);
170 qConverter.calcMatrixCoord(val, locCoord, signal, errorSq);
171 for (size_t dim = 0; dim < DIMS; ++dim) {
172 buffer[dim] = locCoord[dim]; // TODO. Looks un-necessary to me. Can't
173 // we just add localCoord directly to
174 // qVec
175 }
176 V3D qVec(buffer[0], buffer[1], buffer[2]);
177 if (hkl_integ)
178 qVec = UBinv * qVec;
179
180 if (std::isnan(qVec[0]) || std::isnan(qVec[1]) || std::isnan(qVec[2]))
181 continue;
182 // Account for counts in histograms by increasing the qList with the
183 // same q-point
184 qList.emplace_back(std::pair<double, double>(yVal, esqVal), qVec);
185 }
186 }
187 PARALLEL_CRITICAL(addHisto) { integrator.addEvents(qList, hkl_integ); }
188 prog.report();
190 } // end of loop over spectra
192}
193
197// Register the algorithm into the AlgorithmFactory
199
200//---------------------------------------------------------------------
202const std::string IntegrateEllipsoidsV1::name() const { return "IntegrateEllipsoids"; }
203
205int IntegrateEllipsoidsV1::version() const { return 1; }
206
208const std::string IntegrateEllipsoidsV1::category() const { return "Crystal\\Integration"; }
209
210//---------------------------------------------------------------------
211
212//---------------------------------------------------------------------
218 auto ws_valid = std::make_shared<CompositeValidator>();
219 ws_valid->add<WorkspaceUnitValidator>("TOF");
220 ws_valid->add<InstrumentValidator>();
221 // the validator which checks if the workspace has axis
222
223 alg.declareProperty(
224 std::make_unique<WorkspaceProperty<MatrixWorkspace>>("InputWorkspace", "", Direction::Input, ws_valid),
225 "An input MatrixWorkspace with time-of-flight units along "
226 "X-axis and defined instrument with defined sample");
227
228 alg.declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>("PeaksWorkspace", "", Direction::InOut),
229 "Workspace with Peaks to be integrated. NOTE: The peaks MUST "
230 "be indexed with integer HKL values.");
231
232 std::shared_ptr<BoundedValidator<double>> mustBePositive(new BoundedValidator<double>());
233 mustBePositive->setLower(0.0);
234
235 alg.declareProperty("RegionRadius", .35, mustBePositive,
236 "Only events at most this distance from a peak will be "
237 "considered when integrating");
238
239 alg.declareProperty("SpecifySize", false, "If true, use the following for the major axis sizes, else use 3-sigma");
240
241 alg.declareProperty("PeakSize", .18, mustBePositive, "Half-length of major axis for peak ellipsoid");
242
243 alg.declareProperty("BackgroundInnerSize", .18, mustBePositive,
244 "Half-length of major axis for inner ellipsoidal surface of "
245 "background region");
246
247 alg.declareProperty("BackgroundOuterSize", .23, mustBePositive,
248 "Half-length of major axis for outer ellipsoidal surface of "
249 "background region");
250
251 alg.declareProperty(std::make_unique<WorkspaceProperty<PeaksWorkspace>>("OutputWorkspace", "", Direction::Output),
252 "The output PeaksWorkspace will be a copy of the input PeaksWorkspace "
253 "with the peaks' integrated intensities.");
254
255 alg.declareProperty("CutoffIsigI", EMPTY_DBL(), mustBePositive,
256 "Cuttoff for I/sig(i) when finding mean of half-length of "
257 "major radius in first pass when SpecifySize is false."
258 "Default is no second pass.");
259
260 alg.declareProperty("NumSigmas", 3,
261 "Number of sigmas to add to mean of half-length of "
262 "major radius for second pass when SpecifySize is false.");
263
264 alg.declareProperty("IntegrateInHKL", false, "If true, integrate in HKL space not Q space.");
265
266 alg.declareProperty("IntegrateIfOnEdge", true,
267 "Set to false to not integrate if peak radius is off edge of detector."
268 "Background will be scaled if background radius is off edge.");
269
270 alg.declareProperty("AdaptiveQBackground", false,
271 "Default is false. If true, "
272 "BackgroundOuterRadius + AdaptiveQMultiplier * **|Q|** and "
273 "BackgroundInnerRadius + AdaptiveQMultiplier * **|Q|**");
274
275 alg.declareProperty("AdaptiveQMultiplier", 0.0,
276 "PeakRadius + AdaptiveQMultiplier * **|Q|** "
277 "so each peak has a "
278 "different integration radius. Q includes the 2*pi factor.");
279
280 alg.declareProperty("UseOnePercentBackgroundCorrection", true,
281 "If this options is enabled, then the the top 1% of the "
282 "background will be removed"
283 "before the background subtraction.");
284
285 alg.declareProperty("SatelliteRegionRadius", .1, mustBePositive,
286 "Only events at most this distance from a peak will be "
287 "considered when integrating");
288
289 alg.declareProperty("SatellitePeakSize", .08, mustBePositive,
290 "Half-length of major axis for satellite peak ellipsoid");
291
292 alg.declareProperty("SatelliteBackgroundInnerSize", .08, mustBePositive,
293 "Half-length of major axis for inner ellipsoidal surface of "
294 "satellite background region");
295
296 alg.declareProperty("SatelliteBackgroundOuterSize", .09, mustBePositive,
297 "Half-length of major axis for outer ellipsoidal surface of "
298 "satellite background region");
299
300 alg.declareProperty("GetUBFromPeaksWorkspace", false, "If true, UB is taken from peak workspace.");
301}
302
303//---------------------------------------------------------------------
307 // get the input workspace
308 MatrixWorkspace_sptr wksp = getProperty("InputWorkspace");
309
310 EventWorkspace_sptr eventWS = std::dynamic_pointer_cast<EventWorkspace>(wksp);
311 Workspace2D_sptr histoWS = std::dynamic_pointer_cast<Workspace2D>(wksp);
312 if (!eventWS && !histoWS) {
313 throw std::runtime_error("IntegrateEllipsoidsV1 needs either a "
314 "EventWorkspace or Workspace2D as input.");
315 }
316
317 // error out if there are not events
318 if (eventWS && eventWS->getNumberEvents() <= 0) {
319 throw std::runtime_error("IntegrateEllipsoidsV1 does not work for empty event lists");
320 }
321
322 PeaksWorkspace_sptr in_peak_ws = getProperty("PeaksWorkspace");
323 if (!in_peak_ws) {
324 throw std::runtime_error("Could not read the peaks workspace");
325 }
326
327 double radius_m = getProperty("RegionRadius");
328 double radius_s = getProperty("SatelliteRegionRadius");
329 int numSigmas = getProperty("NumSigmas");
330 double cutoffIsigI = getProperty("CutoffIsigI");
331 bool specify_size = getProperty("SpecifySize");
332 double peak_radius = getProperty("PeakSize");
333 double sate_peak_radius = getProperty("SatellitePeakSize");
334 double back_inner_radius = getProperty("BackgroundInnerSize");
335 double sate_back_inner_radius = getProperty("SatelliteBackgroundInnerSize");
336 double back_outer_radius = getProperty("BackgroundOuterSize");
337 double sate_back_outer_radius = getProperty("SatelliteBackgroundOuterSize");
338 bool hkl_integ = getProperty("IntegrateInHKL");
339 bool integrateEdge = getProperty("IntegrateIfOnEdge");
340 bool adaptiveQBackground = getProperty("AdaptiveQBackground");
341 double adaptiveQMultiplier = getProperty("AdaptiveQMultiplier");
342 double adaptiveQBackgroundMultiplier = 0.0;
343 bool useOnePercentBackgroundCorrection = getProperty("UseOnePercentBackgroundCorrection");
344 bool getUB = getProperty("GetUBFromPeaksWorkspace");
345
346 // getUB only valid if peak workspace has a UB matrix
347 if (!(in_peak_ws->sample().hasOrientedLattice()) && getUB) {
348 throw std::runtime_error("Peaks workspace needs a oriented lattice for "
349 "GetUBFromPeaksWorkspace is true");
350 }
351
352 if (adaptiveQBackground)
353 adaptiveQBackgroundMultiplier = adaptiveQMultiplier;
354 if (!integrateEdge) {
355 // This only fails in the unit tests which say that MaskBTP is not
356 // registered
357 try {
358 runMaskDetectors(in_peak_ws, "Tube", "edges");
359 runMaskDetectors(in_peak_ws, "Pixel", "edges");
360 } catch (...) {
361 g_log.error("Can't execute MaskBTP algorithm for this instrument to set "
362 "edge for IntegrateIfOnEdge option");
363 }
364 calculateE1(in_peak_ws->detectorInfo()); // fill E1Vec for use in detectorQ
365 }
366
367 Mantid::DataObjects::PeaksWorkspace_sptr peak_ws = getProperty("OutputWorkspace");
368 if (peak_ws != in_peak_ws)
369 peak_ws = in_peak_ws->clone();
370
371 // get UBinv and the list of
372 // peak Q's for the integrator
373 std::vector<Peak> &peaks = peak_ws->getPeaks();
374 size_t n_peaks = peak_ws->getNumberPeaks();
375 size_t indexed_count = 0;
376 std::vector<V3D> peak_q_list;
377 std::vector<std::pair<std::pair<double, double>, V3D>> qList;
378 std::vector<V3D> hkl_vectors;
379 std::vector<V3D> mnp_vectors;
380 int ModDim = 0;
381 for (size_t i = 0; i < n_peaks; i++) // Note: we skip un-indexed peaks
382 {
383 V3D hkl(peaks[i].getIntHKL());
384 V3D mnp(peaks[i].getIntMNP());
385
386 if (mnp[0] != 0 && ModDim == 0)
387 ModDim = 1;
388 if (mnp[1] != 0 && ModDim == 1)
389 ModDim = 2;
390 if (mnp[2] != 0 && ModDim == 2)
391 ModDim = 3;
392
393 // use tolerance == 1 to just check for (0,0,0,0,0,0)
395 peak_q_list.emplace_back(peaks[i].getQLabFrame());
396 qList.emplace_back(std::pair<double, double>(1., 1.), V3D(peaks[i].getQLabFrame()));
397 hkl_vectors.emplace_back(hkl);
398 mnp_vectors.emplace_back(mnp);
399 indexed_count++;
400 }
401 }
402
403 // Get UB using indexed peaks and
404 // lab-Q vectors
405 Matrix<double> UB(3, 3, false);
406 Matrix<double> modUB(3, 3, false);
407 Matrix<double> modHKL(3, 3, false);
408 int maxOrder = 0;
409 bool CT = false;
410 if (getUB & peak_ws->sample().hasOrientedLattice()) {
411 if (indexed_count < 1)
412 throw std::runtime_error("At least one indexed peak required.");
413 OrientedLattice lattice = peak_ws->mutableSample().getOrientedLattice();
414 auto goniometerMatrix = peak_ws->run().getGoniometerMatrix();
415 // get UB etc. and rotate by goniometer matrix
416 UB = goniometerMatrix * lattice.getUB();
417 modUB = goniometerMatrix * lattice.getModUB();
418 modHKL = lattice.getModHKL();
419 maxOrder = lattice.getMaxOrder();
420 CT = lattice.getCrossTerm();
421 } else {
422 if (indexed_count < 3)
423 throw std::runtime_error("At least three linearly independent indexed peaks are needed.");
424 Geometry::IndexingUtils::Optimize_6dUB(UB, modUB, hkl_vectors, mnp_vectors, ModDim, peak_q_list);
425 if (peak_ws->sample().hasOrientedLattice()) {
426 OrientedLattice lattice = peak_ws->mutableSample().getOrientedLattice();
427 lattice.setUB(UB);
428 lattice.setModUB(modUB);
429 modHKL = lattice.getModHKL();
430 maxOrder = lattice.getMaxOrder();
431 CT = lattice.getCrossTerm();
432 }
433 }
434
435 Matrix<double> UBinv(UB);
436 UBinv.Invert();
437 UBinv *= (1.0 / (2.0 * M_PI)); // if loaded is it already in these units?
438
439 std::vector<double> PeakRadiusVector(n_peaks, peak_radius);
440 std::vector<double> BackgroundInnerRadiusVector(n_peaks, back_inner_radius);
441 std::vector<double> BackgroundOuterRadiusVector(n_peaks, back_outer_radius);
442 if (specify_size) {
443 if (back_outer_radius > radius_m)
444 throw std::runtime_error("BackgroundOuterSize must be less than or equal to the RegionRadius");
445
446 if (back_inner_radius >= back_outer_radius)
447 throw std::runtime_error("BackgroundInnerSize must be less BackgroundOuterSize");
448
449 if (peak_radius > back_inner_radius)
450 throw std::runtime_error("PeakSize must be less than or equal to the BackgroundInnerSize");
451 }
452
453 // make the integrator
454 Integrate3DEvents integrator(qList, hkl_vectors, mnp_vectors, UBinv, modHKL, radius_m, radius_s, maxOrder, CT,
455 useOnePercentBackgroundCorrection);
456
457 // get the events and add
458 // them to the inegrator
459 // set up a descripter of where we are going
460 this->initTargetWSDescr(wksp);
461
462 // set up the progress bar
463 const size_t numSpectra = wksp->getNumberHistograms();
464 Progress prog(this, 0.5, 1.0, numSpectra);
465
466 if (eventWS) {
467 // process as EventWorkspace
468 qListFromEventWS(integrator, prog, eventWS, UBinv, hkl_integ);
469 } else {
470 // process as Workspace2D
471 qListFromHistoWS(integrator, prog, histoWS, UBinv, hkl_integ);
472 }
473
474 double inti;
475 double sigi;
476 std::vector<double> principalaxis1, principalaxis2, principalaxis3;
477 std::vector<double> sateprincipalaxis1, sateprincipalaxis2, sateprincipalaxis3;
478 for (size_t i = 0; i < n_peaks; i++) {
479 const V3D hkl(peaks[i].getIntHKL());
480 const V3D mnp(peaks[i].getIntMNP());
481
483 const V3D peak_q = peaks[i].getQLabFrame();
484 // modulus of Q
485 const double lenQpeak = adaptiveQMultiplier != 0.0 ? peak_q.norm() : 0.0;
486
487 double adaptiveRadius = adaptiveQMultiplier * lenQpeak + peak_radius;
488 if (mnp != V3D(0, 0, 0))
489 adaptiveRadius = adaptiveQMultiplier * lenQpeak + sate_peak_radius;
490
491 if (adaptiveRadius <= 0.0) {
492 g_log.error() << "Error: Radius for integration sphere of peak " << i << " is negative = " << adaptiveRadius
493 << '\n';
494 peaks[i].setIntensity(0.0);
495 peaks[i].setSigmaIntensity(0.0);
496 PeakRadiusVector[i] = 0.0;
497 BackgroundInnerRadiusVector[i] = 0.0;
498 BackgroundOuterRadiusVector[i] = 0.0;
499 continue;
500 }
501
502 double adaptiveBack_inner_radius;
503 double adaptiveBack_outer_radius;
504 if (mnp == V3D(0, 0, 0)) {
505 adaptiveBack_inner_radius = adaptiveQBackgroundMultiplier * lenQpeak + back_inner_radius;
506 adaptiveBack_outer_radius = adaptiveQBackgroundMultiplier * lenQpeak + back_outer_radius;
507 } else {
508 adaptiveBack_inner_radius = adaptiveQBackgroundMultiplier * lenQpeak + sate_back_inner_radius;
509 adaptiveBack_outer_radius = adaptiveQBackgroundMultiplier * lenQpeak + sate_back_outer_radius;
510 }
511 PeakRadiusVector[i] = adaptiveRadius;
512 BackgroundInnerRadiusVector[i] = adaptiveBack_inner_radius;
513 BackgroundOuterRadiusVector[i] = adaptiveBack_outer_radius;
514
515 std::vector<double> axes_radii;
517 E1Vec, peak_q, hkl, mnp, specify_size, adaptiveRadius, adaptiveBack_inner_radius, adaptiveBack_outer_radius,
518 axes_radii, inti, sigi);
519 peaks[i].setIntensity(inti);
520 peaks[i].setSigmaIntensity(sigi);
521 peaks[i].setPeakShape(shape);
522 if (axes_radii.size() == 3) {
523 if (inti / sigi > cutoffIsigI || cutoffIsigI == EMPTY_DBL()) {
524 if (mnp == V3D(0, 0, 0)) {
525 principalaxis1.emplace_back(axes_radii[0]);
526 principalaxis2.emplace_back(axes_radii[1]);
527 principalaxis3.emplace_back(axes_radii[2]);
528 } else {
529 sateprincipalaxis1.emplace_back(axes_radii[0]);
530 sateprincipalaxis2.emplace_back(axes_radii[1]);
531 sateprincipalaxis3.emplace_back(axes_radii[2]);
532 }
533 }
534 }
535 } else {
536 peaks[i].setIntensity(0.0);
537 peaks[i].setSigmaIntensity(0.0);
538 }
539 }
540 if (principalaxis1.size() > 1) {
541 Statistics stats1 = getStatistics(principalaxis1);
542 g_log.notice() << "principalaxis1: "
543 << " mean " << stats1.mean << " standard_deviation " << stats1.standard_deviation << " minimum "
544 << stats1.minimum << " maximum " << stats1.maximum << " median " << stats1.median << "\n";
545 Statistics stats2 = getStatistics(principalaxis2);
546 g_log.notice() << "principalaxis2: "
547 << " mean " << stats2.mean << " standard_deviation " << stats2.standard_deviation << " minimum "
548 << stats2.minimum << " maximum " << stats2.maximum << " median " << stats2.median << "\n";
549 Statistics stats3 = getStatistics(principalaxis3);
550 g_log.notice() << "principalaxis3: "
551 << " mean " << stats3.mean << " standard_deviation " << stats3.standard_deviation << " minimum "
552 << stats3.minimum << " maximum " << stats3.maximum << " median " << stats3.median << "\n";
553
554 if (sateprincipalaxis1.size() > 1) {
555 Statistics satestats1 = getStatistics(sateprincipalaxis1);
556 g_log.notice() << "sateprincipalaxis1: "
557 << " mean " << satestats1.mean << " standard_deviation " << satestats1.standard_deviation
558 << " minimum " << satestats1.minimum << " maximum " << satestats1.maximum << " median "
559 << satestats1.median << "\n";
560 Statistics satestats2 = getStatistics(sateprincipalaxis2);
561 g_log.notice() << "sateprincipalaxis2: "
562 << " mean " << satestats2.mean << " standard_deviation " << satestats2.standard_deviation
563 << " minimum " << satestats2.minimum << " maximum " << satestats2.maximum << " median "
564 << satestats2.median << "\n";
565 Statistics satestats3 = getStatistics(sateprincipalaxis3);
566 g_log.notice() << "sateprincipalaxis3: "
567 << " mean " << satestats3.mean << " standard_deviation " << satestats3.standard_deviation
568 << " minimum " << satestats3.minimum << " maximum " << satestats3.maximum << " median "
569 << satestats3.median << "\n";
570 }
571
572 constexpr size_t histogramNumber = 3;
573 Workspace_sptr wsProfile = WorkspaceFactory::Instance().create("Workspace2D", histogramNumber,
574 principalaxis1.size(), principalaxis1.size());
575 Workspace2D_sptr wsProfile2D = std::dynamic_pointer_cast<Workspace2D>(wsProfile);
576 AnalysisDataService::Instance().addOrReplace("EllipsoidAxes", wsProfile2D);
577
578 // set output workspace
579 Points points(principalaxis1.size(), LinearGenerator(0, 1));
580 wsProfile2D->setHistogram(0, points, Counts(std::move(principalaxis1)));
581 wsProfile2D->setHistogram(1, points, Counts(std::move(principalaxis2)));
582 wsProfile2D->setHistogram(2, points, Counts(std::move(principalaxis3)));
583
584 if (cutoffIsigI != EMPTY_DBL()) {
585 principalaxis1.clear();
586 principalaxis2.clear();
587 principalaxis3.clear();
588 sateprincipalaxis1.clear();
589 sateprincipalaxis2.clear();
590 sateprincipalaxis3.clear();
591 specify_size = true;
592 peak_radius = std::max(std::max(stats1.mean, stats2.mean), stats3.mean) +
593 numSigmas * std::max(std::max(stats1.standard_deviation, stats2.standard_deviation),
594 stats3.standard_deviation);
595 back_inner_radius = peak_radius;
596 back_outer_radius = peak_radius * 1.25992105; // A factor of 2 ^ (1/3)
597 // will make the background
598 // shell volume equal to the peak region volume.
599 for (size_t i = 0; i < n_peaks; i++) {
600 V3D hkl(peaks[i].getIntHKL());
601 V3D mnp(peaks[i].getIntMNP());
603 const V3D peak_q = peaks[i].getQLabFrame();
604 std::vector<double> axes_radii;
605 integrator.ellipseIntegrateModEvents(E1Vec, peak_q, hkl, mnp, specify_size, peak_radius, back_inner_radius,
606 back_outer_radius, axes_radii, inti, sigi);
607 peaks[i].setIntensity(inti);
608 peaks[i].setSigmaIntensity(sigi);
609 if (axes_radii.size() == 3) {
610 if (mnp == V3D(0, 0, 0)) {
611 principalaxis1.emplace_back(axes_radii[0]);
612 principalaxis2.emplace_back(axes_radii[1]);
613 principalaxis3.emplace_back(axes_radii[2]);
614 } else {
615 sateprincipalaxis1.emplace_back(axes_radii[0]);
616 sateprincipalaxis2.emplace_back(axes_radii[1]);
617 sateprincipalaxis3.emplace_back(axes_radii[2]);
618 }
619 }
620 } else {
621 peaks[i].setIntensity(0.0);
622 peaks[i].setSigmaIntensity(0.0);
623 }
624 }
625 if (principalaxis1.size() > 1) {
626 Workspace_sptr wsProfile2 = WorkspaceFactory::Instance().create("Workspace2D", histogramNumber,
627 principalaxis1.size(), principalaxis1.size());
628 Workspace2D_sptr wsProfile2D2 = std::dynamic_pointer_cast<Workspace2D>(wsProfile2);
629 AnalysisDataService::Instance().addOrReplace("EllipsoidAxes_2ndPass", wsProfile2D2);
630
631 Points profilePoints(principalaxis1.size(), LinearGenerator(0, 1));
632 wsProfile2D->setHistogram(0, profilePoints, Counts(std::move(principalaxis1)));
633 wsProfile2D->setHistogram(1, profilePoints, Counts(std::move(principalaxis2)));
634 wsProfile2D->setHistogram(2, profilePoints, Counts(std::move(principalaxis3)));
635 }
636 }
637 }
638
639 // This flag is used by the PeaksWorkspace to evaluate whether it has been
640 // integrated.
641 peak_ws->mutableRun().addProperty("PeaksIntegrated", 1, true);
642 // These flags are specific to the algorithm.
643 peak_ws->mutableRun().addProperty("PeakRadius", PeakRadiusVector, true);
644 peak_ws->mutableRun().addProperty("BackgroundInnerRadius", BackgroundInnerRadiusVector, true);
645 peak_ws->mutableRun().addProperty("BackgroundOuterRadius", BackgroundOuterRadiusVector, true);
646
647 setProperty("OutputWorkspace", peak_ws);
648}
649
657 m_targWSDescr.setMinMax(std::vector<double>(3, -2000.), std::vector<double>(3, 2000.));
660
661 // generate the detectors table
662 Mantid::API::Algorithm_sptr childAlg = createChildAlgorithm("PreprocessDetectorsToMD", 0.,
663 .5); // HACK. soft dependency on non-dependent package.
664 childAlg->setProperty("InputWorkspace", wksp);
665 childAlg->executeAsChildAlg();
666
667 DataObjects::TableWorkspace_sptr table = childAlg->getProperty("OutputWorkspace");
668 if (!table)
669 throw(std::runtime_error("Can not retrieve results of \"PreprocessDetectorsToMD\""));
670 else
672}
673
674/*
675 * Define edges for each instrument by masking. For CORELLI, tubes 1 and 16, and
676 *pixels 0 and 255.
677 * Get Q in the lab frame for every peak, call it C
678 * For every point on the edge, the trajectory in reciprocal space is a straight
679 *line, going through O=V3D(0,0,0).
680 * Calculate a point at a fixed momentum, say k=1. Q in the lab frame
681 *E=V3D(-k*sin(tt)*cos(ph),-k*sin(tt)*sin(ph),k-k*cos(ph)).
682 * Normalize E to 1: E=E*(1./E.norm())
683 *
684 * @param inst: instrument
685 */
686
688 for (size_t i = 0; i < detectorInfo.size(); ++i) {
689 if (detectorInfo.isMonitor(i))
690 continue; // skip monitor
691 if (!detectorInfo.isMasked(i))
692 continue; // edge is masked so don't check if not masked
693 const auto &det = detectorInfo.detector(i);
694 double tt1 = det.getTwoTheta(V3D(0, 0, 0), V3D(0, 0, 1)); // two theta
695 double ph1 = det.getPhi(); // phi
696 V3D E1 = V3D(-std::sin(tt1) * std::cos(ph1), -std::sin(tt1) * std::sin(ph1),
697 1. - std::cos(tt1)); // end of trajectory
698 E1 = E1 * (1. / E1.norm()); // normalize
699 E1Vec.emplace_back(E1);
700 }
701}
702
704 const std::string &property, const std::string &values) {
705 IAlgorithm_sptr alg = createChildAlgorithm("MaskBTP");
706 alg->setProperty<Workspace_sptr>("Workspace", peakWS);
707 alg->setProperty(property, values);
708 if (!alg->execute())
709 throw std::runtime_error("MaskDetectors Child Algorithm has not executed successfully");
710}
711} // namespace MDAlgorithms
712} // namespace Mantid
#define DECLARE_ALGORITHM(classname)
Definition: Algorithm.h:576
const int maxOrder
Definition: IndexPeaks.cpp:55
#define PARALLEL_START_INTERRUPT_REGION
Begins a block to skip processing is the algorithm has been interupted Note the end of the block if n...
Definition: MultiThreaded.h:94
#define PARALLEL_CRITICAL(name)
#define PARALLEL_END_INTERRUPT_REGION
Ends a block to skip processing is the algorithm has been interupted Note the start of the block if n...
#define PARALLEL_FOR_IF(condition)
Empty definitions - to enable set your complier to enable openMP.
#define PARALLEL_CHECK_INTERRUPT_REGION
Adds a check after a Parallel region to see if it was interupted.
Base class from which all concrete algorithm classes should be derived.
Definition: Algorithm.h:85
void declareProperty(std::unique_ptr< Kernel::Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
Definition: Algorithm.cpp:1913
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
Definition: Algorithm.cpp:2076
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.
Definition: Algorithm.cpp:842
Kernel::Logger & g_log
Definition: Algorithm.h:451
A validator which checks that a workspace has a valid instrument.
Helper class for reporting progress from algorithms.
Definition: Progress.h:25
A property class for workspaces.
A validator which checks that the unit of the workspace referred to by a WorkspaceProperty is the exp...
A class for holding :
Definition: EventList.h:56
void compressEvents(double tolerance, EventList *destination)
Compress the event list by grouping events with the same TOF (within a given tolerance).
Definition: EventList.cpp:1676
std::vector< WeightedEventNoTime > & getWeightedEventsNoTime()
Return the list of WeightedEvent contained.
Definition: EventList.cpp:823
void switchTo(Mantid::API::EventType newType) override
Switch the EventList to use the given EventType (TOF, WEIGHTED, or WEIGHTED_NOTIME)
Definition: EventList.cpp:649
bool empty() const
Much like stl containers, returns true if there is nothing in the event list.
Definition: EventList.cpp:1158
Geometry::DetectorInfo is an intermediate step towards a DetectorInfo that is part of Instrument-2....
Definition: DetectorInfo.h:49
bool isMasked(const size_t index) const
Returns true if the detector is masked.
const Geometry::IDetector & detector(const size_t index) const
Return a const reference to the detector with given index.
size_t size() const
Returns the size of the DetectorInfo, i.e., the number of detectors in the instrument.
bool isMonitor(const size_t index) const
Returns true if the detector is a monitor.
virtual double getTwoTheta(const Kernel::V3D &observer, const Kernel::V3D &axis) const =0
Gives the angle of this detector object with respect to an axis.
static double Optimize_6dUB(Kernel::DblMatrix &UB, Kernel::DblMatrix &ModUB, const std::vector< Kernel::V3D > &hkl_vectors, const std::vector< Kernel::V3D > &mnp_vectors, const int &ModDim, const std::vector< Kernel::V3D > &q_vectors, std::vector< double > &sigabc, std::vector< double > &sigq)
STATIC method Optimize_UB: Calculates the matrix that most nearly maps the specified hkl_vectors to t...
static bool ValidIndex(const Kernel::V3D &hkl, double tolerance)
Check is hkl is within tolerance of integer (h,k,l) non-zero values.
Class to implement UB matrix.
void setModUB(const Kernel::DblMatrix &newModUB)
Sets the Modulation UB matrix.
void setUB(const Kernel::DblMatrix &newUB)
Sets the UB matrix and recalculates lattice parameters.
const Kernel::DblMatrix & getUB() const
Get the UB matrix.
const Kernel::DblMatrix & getModUB() const
int getMaxOrder() const
Get max order.
Definition: UnitCell.cpp:596
const Kernel::DblMatrix & getModHKL() const
Get modulation vectors for satellites.
Definition: UnitCell.cpp:548
bool getCrossTerm() const
Get cross term boolean.
Definition: UnitCell.cpp:602
BoundedValidator is a validator that requires the values to be between upper or lower bounds,...
IPropertyManager * setProperty(const std::string &name, const T &value)
Templated method to set the value of a PropertyWithValue.
void notice(const std::string &msg)
Logs at notice level.
Definition: Logger.cpp:95
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
T Invert()
LU inversion routine.
Definition: Matrix.cpp:924
void report()
Increments the loop counter by 1, then sends the progress notification on behalf of its algorithm.
Definition: ProgressBase.h:51
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
double norm() const noexcept
Definition: V3D.h:263
This is a low-level class to construct a map with lists of events near each peak Q-vector,...
std::shared_ptr< const Mantid::Geometry::PeakShape > ellipseIntegrateModEvents(const std::vector< Kernel::V3D > &E1Vec, Mantid::Kernel::V3D const &peak_q, Mantid::Kernel::V3D const &hkl, Mantid::Kernel::V3D const &mnp, bool specify_size, double peak_radius, double back_inner_radius, double back_outer_radius, std::vector< double > &axes_radii, double &inti, double &sigi)
Find the net integrated intensity of a modulated peak, using ellipsoidal volumes.
void addEvents(std::vector< std::pair< std::pair< double, double >, Mantid::Kernel::V3D > > const &event_qs, bool hkl_integ)
Add event Q's to lists of events near peaks.
int version() const override
Algorithm's version for identification.
std::vector< Kernel::V3D > E1Vec
save for all detector pixels
void runMaskDetectors(const Mantid::DataObjects::PeaksWorkspace_sptr &peakWS, const std::string &property, const std::string &values)
void initTargetWSDescr(API::MatrixWorkspace_sptr &wksp)
IntegrateEllipsoidsV1::initTargetWSDescr Initialize the output information for the MD conversion fram...
void qListFromEventWS(Integrate3DEvents &integrator, API::Progress &prog, DataObjects::EventWorkspace_sptr &wksp, Kernel::DblMatrix const &UBinv, bool hkl_integ)
qListFromEventWS creates qlist from events
void calculateE1(const Geometry::DetectorInfo &detectorInfo)
Calculate if this Q is on a detector.
void qListFromHistoWS(Integrate3DEvents &integrator, API::Progress &prog, DataObjects::Workspace2D_sptr &wksp, Kernel::DblMatrix const &UBinv, bool hkl_integ)
qListFromHistoWS creates qlist from input workspaces of type Workspace2D
void exec() override
Execute the algorithm.
const std::string category() const override
Algorithm's category for identification.
void init() override
Initialize the algorithm's properties.
Class responsible for conversion of input workspace data into proper number of output dimensions for ...
Definition: MDTransfQ3D.h:31
bool calcMatrixCoord(const double &deltaEOrK0, std::vector< coord_t > &Coord, double &s, double &err) const override
Calculates 3D transformation of the variable coordinates and (if applicable) signal and error dependi...
Definition: MDTransfQ3D.cpp:47
void initialize(const MDWSDescription &ConvParams) override
function initalizes all variables necessary for converting workspace variables into MD variables in M...
bool calcYDepCoordinates(std::vector< coord_t > &Coord, size_t i) override
Method updates the value of preprocessed detector coordinates in Q-space, used by other functions.
void setMinMax(const std::vector< double > &minVal, const std::vector< double > &maxVal)
function sets up min-max values to the dimensions, described by the class
void buildFromMatrixWS(const API::MatrixWorkspace_sptr &pWS, const std::string &QMode, const std::string &dEMode, const std::vector< std::string > &dimPropertyNames=std::vector< std::string >())
method builds MD Event ws description from a matrix workspace and the transformations,...
DataObjects::TableWorkspace_const_sptr m_PreprDetTable
void setLorentsCorr(bool On=false)
do we need to perform Lorentz corrections
void initialize(const MDWSDescription &targetWSDescr, const std::string &unitsTo, bool forceViaTOF=false)
Initialize unit conversion helper This method is interface to internal initialize method,...
std::shared_ptr< IAlgorithm > IAlgorithm_sptr
shared pointer to Mantid::API::IAlgorithm
std::complex< double > MANTID_API_DLL E1(std::complex< double > z)
Integral for Gamma.
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
Definition: Workspace_fwd.h:20
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
Definition: Algorithm.h:61
@ WEIGHTED_NOTIME
Definition: IEventList.h:18
std::shared_ptr< MatrixWorkspace > MatrixWorkspace_sptr
shared pointer to the matrix workspace base class
std::shared_ptr< Workspace2D > Workspace2D_sptr
shared pointer to Mantid::DataObjects::Workspace2D
std::shared_ptr< TableWorkspace > TableWorkspace_sptr
shared pointer to Mantid::DataObjects::TableWorkspace
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< EventWorkspace > EventWorkspace_sptr
shared pointer to the EventWorkspace class
std::shared_ptr< const PeakShape > PeakShape_const_sptr
Definition: PeakShape.h:43
Statistics getStatistics(const std::vector< TYPE > &data, const unsigned int flags=StatOptions::AllStats)
Return a statistics object for the given data set.
Definition: Statistics.cpp:167
std::enable_if< std::is_pointer< Arg >::value, bool >::type threadSafe(Arg workspace)
Thread-safety check Checks the workspace to ensure it is suitable for multithreaded access.
Definition: MultiThreaded.h:22
const std::string Q3D("Q3D")
Only convert to Q-vector.
const std::size_t DIMS(3)
Q-vector is always three dimensional.
const std::string ELASTIC("Elastic")
This only works for diffraction.
Helper class which provides the Collimation Length for SANS instruments.
constexpr double EMPTY_DBL() noexcept
Returns what we consider an "empty" double within a property.
Definition: EmptyValues.h:43
STL namespace.
@ InOut
Both an input & output workspace.
Definition: Property.h:55
@ Input
An input workspace.
Definition: Property.h:53
@ Output
An output workspace.
Definition: Property.h:54
Simple struct to store statistics.
Definition: Statistics.h:25
double mean
Mean value.
Definition: Statistics.h:31
double median
Median value.
Definition: Statistics.h:33
double minimum
Minimum value.
Definition: Statistics.h:27
double maximum
Maximum value.
Definition: Statistics.h:29
double standard_deviation
standard_deviation of the values
Definition: Statistics.h:35