26#include "MantidParallel/Communicator.h"
34using Types::Event::TofEvent;
41template <
class ET>
const std::vector<ET> &getEventVector(
const EventList &el);
43template <>
const std::vector<Types::Event::TofEvent> &getEventVector(
const EventList &el) {
return el.
getEvents(); }
45template <>
const std::vector<DataObjects::WeightedEvent> &getEventVector(
const EventList &el) {
49template <>
const std::vector<DataObjects::WeightedEventNoTime> &getEventVector(
const EventList &el) {
55 double tolWeight, int64_t tolPulse,
bool printdetails,
size_t &numdiffpulse,
size_t &numdifftof,
56 size_t &numdiffboth,
size_t &numdiffweight) {
65 const auto &events1 = getEventVector<ET>(el1);
66 const auto &events2 = getEventVector<ET>(el2);
69 size_t numevents = events1.size();
70 for (
size_t i = 0; i < numevents; ++i) {
72 const auto &e1 = events1[i];
73 const auto &e2 = events2[i];
75 bool diffpulse =
false;
77 bool diffweight =
false;
78 if (std::abs(e1.pulseTime().totalNanoseconds() - e2.pulseTime().totalNanoseconds()) > tolPulse) {
82 if (
fabs(e1.tof() - e2.tof()) > tolTof) {
86 if (diffpulse && difftof)
88 if (
fabs(e1.weight() - e2.weight()) > tolWeight) {
93 bool same = (!diffpulse) && (!difftof) && (!diffweight);
97 std::stringstream outss;
98 outss <<
"Spectrum ? Event " << i <<
": ";
100 outss <<
"Diff-Pulse: " << e1.pulseTime() <<
" vs. " << e2.pulseTime() <<
"; ";
102 outss <<
"Diff-TOF: " << e1.tof() <<
" vs. " << e2.tof() <<
";";
104 outss <<
"Diff-Weight: " << e1.weight() <<
" vs. " << e2.weight() <<
";";
120 "The name of the first input workspace.");
122 "The name of the second input workspace.");
124 declareProperty(
"Tolerance", 1e-10,
"The maximum amount by which values may differ between the workspaces.");
127 "Whether to check that the data types "
128 "(Workspace2D vs EventWorkspace) match.");
129 declareProperty(
"CheckAxes",
true,
"Whether to check that the axes match.");
130 declareProperty(
"CheckSpectraMap",
true,
"Whether to check that the spectra-detector maps match. ");
131 declareProperty(
"CheckInstrument",
true,
"Whether to check that the instruments match. ");
132 declareProperty(
"CheckMasking",
true,
"Whether to check that the bin masking matches. ");
135 declareProperty(
"CheckSample",
false,
"Whether to check that the sample (e.g. logs).");
138 "Treat tolerance as relative error rather then the absolute error.\n"
139 "This is only applicable to Matrix workspaces.");
143 "Usually checking data ends when first mismatch occurs. This "
144 "forces algorithm to check all data and print mismatch to "
146 "Very often such logs are huge so making it true should be "
149 declareProperty(
"NumberMismatchedSpectraToPrint", 1,
"Number of mismatched spectra from lowest to be listed. ");
155 "TableWorkspace containing messages about any mismatches detected");
157 m_messages = std::make_shared<TableWorkspace>();
169 if (
g_log.
is(Logger::Priority::PRIO_DEBUG))
175 std::string message =
m_messages->cell<std::string>(0, 0);
176 g_log.
warning() <<
"The workspaces did not match: " << message <<
'\n';
180 g_log.
notice() <<
"The workspaces \"" << ws1 <<
"\" and \"" << ws2 <<
"\" matched!\n";
208 }
else if (!ws1 && !ws2) {
210 throw std::runtime_error(
"CompareWorkspaces::processGroups - Neither "
211 "input is a WorkspaceGroup. This is a logical "
212 "error in the code.");
213 }
else if (!ws1 || !ws2) {
214 recordMismatch(
"Type mismatch. One workspace is a group, the other is not.");
218 g_log.
notice() <<
"All workspaces in workspace groups \"" << ws1->getName() <<
"\" and \"" << ws2->getName()
235 const std::shared_ptr<const API::WorkspaceGroup> &groupTwo) {
238 const auto totalNum =
static_cast<size_t>(groupOne->getNumberOfEntries());
239 if (groupOne->getNumberOfEntries() != groupTwo->getNumberOfEntries()) {
245 const std::vector<Property *> &allProps = this->
getProperties();
246 std::vector<Property *> nonDefaultProps;
247 nonDefaultProps.reserve(allProps.size());
248 for (
auto p : allProps) {
249 const std::string &propName = p->name();
251 if (p->isDefault() || propName ==
"Workspace1" || propName ==
"Workspace2")
253 nonDefaultProps.emplace_back(p);
255 const size_t numNonDefault = nonDefaultProps.size();
257 const double progressFraction = 1.0 /
static_cast<double>(totalNum);
258 std::vector<std::string> namesOne = groupOne->getNames();
259 std::vector<std::string> namesTwo = groupTwo->getNames();
260 for (
size_t i = 0; i < totalNum; ++i) {
265 progressFraction *
static_cast<double>(i + 1),
false, this->
version());
266 checker->setPropertyValue(
"Workspace1", namesOne[i]);
267 checker->setPropertyValue(
"Workspace2", namesTwo[i]);
268 for (
size_t j = 0; j < numNonDefault; ++j) {
270 checker->setPropertyValue(p->
name(), p->
value());
274 bool success = checker->getProperty(
"Result");
277 recordMismatch(table->cell<std::string>(0, 0), namesOne[i], namesTwo[i]);
293 if (w1->id() ==
"PeaksWorkspace" || w2->id() ==
"PeaksWorkspace") {
301 if ((pws1 && !pws2) || (!pws1 && pws2)) {
302 recordMismatch(
"One workspace is a PeaksWorkspace and the other is not.");
316 if (w1->id() ==
"LeanElasticPeaksWorkspace" || w2->id() ==
"LeanElasticPeaksWorkspace") {
317 auto lpws1 = std::dynamic_pointer_cast<LeanElasticPeaksWorkspace>(w1);
318 auto lpws2 = std::dynamic_pointer_cast<LeanElasticPeaksWorkspace>(w2);
320 if ((lpws1 && !lpws2) || (!lpws1 && lpws2)) {
321 recordMismatch(
"One workspace is a LeanElasticPeaksWorkspace and the other is not.");
324 if (lpws1 && lpws2) {
335 auto tws1 = std::dynamic_pointer_cast<const ITableWorkspace>(w1);
336 auto tws2 = std::dynamic_pointer_cast<const ITableWorkspace>(w2);
337 if ((tws1 && !tws2) || (!tws1 && tws2)) {
338 recordMismatch(
"One workspace is a TableWorkspace and the other is not.");
353 if ((mdews1 && !mdews2) || (!mdews1 && mdews2)) {
354 recordMismatch(
"One workspace is an IMDEventWorkspace and the other is not.");
360 if ((mdhws1 && !mdhws2) || (!mdhws1 && mdhws2)) {
361 recordMismatch(
"One workspace is an IMDHistoWorkspace and the other is not.");
365 if (mdhws1 || mdews1)
382 if ((ews1 && !ews2) || (!ews1 && ews2)) {
383 recordMismatch(
"One workspace is an EventWorkspace and the other is not.");
388 size_t numhist = ws1->getNumberHistograms();
394 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0, numhist * 5);
399 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0, numhist * 2);
411 m_progress->reportIncrement(numhist / 5,
"Axes");
414 m_progress->reportIncrement(numhist / 5,
"SpectraMap");
417 m_progress->reportIncrement(numhist / 5,
"Instrument");
420 m_progress->reportIncrement(numhist / 5,
"Masking");
423 m_progress->reportIncrement(numhist / 5,
"Sample");
424 if (
static_cast<bool>(
getProperty(
"CheckSample"))) {
437 bool checkallspectra =
getProperty(
"CheckAllData");
438 int numspec2print =
getProperty(
"NumberMismatchedSpectraToPrint");
439 int wsindex2print =
getProperty(
"DetailedPrintIndex");
448 recordMismatch(
"Mismatched type of events in the EventWorkspaces.");
459 throw std::runtime_error(
"The progress pointer was found to be null!");
464 int64_t tolerancePulse = 1;
465 double toleranceTOF = 0.05;
466 if ((ews1.
getAxis(0)->
unit()->label().ascii() !=
"microsecond") ||
467 (ews2.
getAxis(0)->
unit()->label().ascii() !=
"microsecond")) {
469 << ews2.
getAxis(0)->
unit()->label().ascii() <<
". Tolerance of TOF is set to 0.05 still. "
473 g_log.
notice() <<
"TOF Tolerance = " << toleranceTOF <<
"\n";
475 bool mismatchedEvent =
false;
476 int mismatchedEventWI = 0;
478 size_t numUnequalNumEventsSpectra = 0;
479 size_t numUnequalEvents = 0;
480 size_t numUnequalTOFEvents = 0;
481 size_t numUnequalPulseEvents = 0;
482 size_t numUnequalBothEvents = 0;
483 size_t numUnequalWeights = 0;
485 std::vector<int> vec_mismatchedwsindex;
490 if (!mismatchedEvent || checkallspectra)
494 bool printdetail = (i == wsindex2print);
496 g_log.
information() <<
"Spectrum " << i <<
" is set to print out in details. "
500 if (!el1.
equals(el2, toleranceTOF, toleranceWeight, tolerancePulse)) {
501 size_t tempNumTof = 0;
502 size_t tempNumPulses = 0;
503 size_t tempNumBoth = 0;
504 size_t tempNumWeight = 0;
506 int tempNumUnequal = 0;
514 tempNumPulses, tempNumTof, tempNumBoth, tempNumWeight);
517 mismatchedEvent =
true;
518 mismatchedEventWI = i;
520 if (tempNumUnequal == -1) {
522 ++numUnequalNumEventsSpectra;
525 numUnequalEvents +=
static_cast<size_t>(tempNumUnequal);
526 numUnequalTOFEvents += tempNumTof;
527 numUnequalPulseEvents += tempNumPulses;
528 numUnequalBothEvents += tempNumBoth;
529 numUnequalWeights += tempNumWeight;
532 vec_mismatchedwsindex.emplace_back(i);
542 if (mismatchedEvent) {
543 std::ostringstream mess;
544 if (checkallspectra) {
545 if (numUnequalNumEventsSpectra > 0)
546 mess <<
"Total " << numUnequalNumEventsSpectra <<
" spectra have different number of events. "
549 mess <<
"Total " << numUnequalEvents <<
" (in " << ews1.
getNumberEvents() <<
") events are differrent. "
550 << numUnequalTOFEvents <<
" have different TOF; " << numUnequalPulseEvents <<
" have different pulse time; "
551 << numUnequalBothEvents <<
" have different in both TOF and pulse time; " << numUnequalWeights
552 <<
" have different weights."
555 mess <<
"Mismatched event lists include " << vec_mismatchedwsindex.size() <<
" of "
559 std::sort(vec_mismatchedwsindex.begin(), vec_mismatchedwsindex.end());
560 numspec2print = std::min(numspec2print,
static_cast<int>(vec_mismatchedwsindex.size()));
561 for (
int i = 0; i < numspec2print; ++i) {
562 mess << vec_mismatchedwsindex[i] <<
", ";
563 if ((i + 1) % 10 == 0)
567 mess <<
"Quick comparison shows 2 workspaces do not match. "
568 <<
"First found mismatched event list is at workspace index " << mismatchedEventWI;
589 const size_t numHists = ws1->getNumberHistograms();
590 const size_t numBins = ws1->blocksize();
591 const bool histogram = ws1->isHistogramData();
592 const bool checkAllData =
getProperty(
"CheckAllData");
593 const bool RelErr =
getProperty(
"ToleranceRelErr");
596 if (numHists != ws2->getNumberHistograms() || numBins != ws2->blocksize()) {
602 if (histogram != ws2->isHistogramData()) {
608 bool resultBool =
true;
612 for (
long i = 0; i < static_cast<long>(numHists); ++i) {
616 if (resultBool || checkAllData)
619 const auto &X1 = ws1->x(i);
620 const auto &Y1 = ws1->y(i);
621 const auto &
E1 = ws1->e(i);
622 const auto &X2 = ws2->x(i);
623 const auto &Y2 = ws2->y(i);
624 const auto &E2 = ws2->e(i);
626 for (
int j = 0; j < static_cast<int>(numBins); ++j) {
631 err = (std::fabs(X1[j] - X2[j]) >
tolerance || std::fabs(Y1[j] - Y2[j]) >
tolerance ||
635 g_log.
debug() <<
"Data mismatch at cell (hist#,bin#): (" << i <<
"," << j <<
")\n";
636 g_log.
debug() <<
" Dataset #1 (X,Y,E) = (" << X1[j] <<
"," << Y1[j] <<
"," <<
E1[j] <<
")\n";
637 g_log.
debug() <<
" Dataset #2 (X,Y,E) = (" << X2[j] <<
"," << Y2[j] <<
"," << E2[j] <<
")\n";
638 g_log.
debug() <<
" Difference (X,Y,E) = (" << std::fabs(X1[j] - X2[j]) <<
"," << std::fabs(Y1[j] - Y2[j])
639 <<
"," << std::fabs(
E1[j] - E2[j]) <<
")\n";
646 if (histogram && std::fabs(X1.back() - X2.back()) >
tolerance) {
647 g_log.
debug() <<
" Data ranges mismatch for spectra N: (" << i <<
")\n";
648 g_log.
debug() <<
" Last bin ranges (X1_end vs X2_end) = (" << X1.back() <<
"," << X2.back() <<
")\n";
673 const int numAxes = ws1->axes();
675 if (numAxes != ws2->axes()) {
680 for (
int i = 0; i < numAxes; ++i) {
681 std::ostringstream axis_name_ss;
682 axis_name_ss <<
"Axis " << i;
683 std::string axis_name = axis_name_ss.str();
685 const Axis *
const ax1 = ws1->getAxis(i);
686 const Axis *
const ax2 = ws2->getAxis(i);
701 if ((ax1_unit ==
nullptr && ax2_unit !=
nullptr) || (ax1_unit !=
nullptr && ax2_unit ==
nullptr) ||
702 (ax1_unit && ax1_unit->unitID() != ax2_unit->unitID())) {
711 const auto *na1 =
static_cast<const NumericAxis *
>(ax1);
713 if (!na1->equalWithinTolerance(*ax2,
tolerance)) {
717 }
else if (!ax1->
isSpectra() && !ax1->operator==(*ax2)) {
723 if (ws1->YUnit() != ws2->YUnit()) {
724 g_log.
debug() <<
"YUnit strings : WS1 = " << ws1->YUnit() <<
" WS2 = " << ws2->YUnit() <<
"\n";
730 if (ws1->isDistribution() != ws2->isDistribution()) {
731 g_log.
debug() <<
"Distribution flags: WS1 = " << ws1->isDistribution() <<
" WS2 = " << ws2->isDistribution()
748 if (ws1->getNumberHistograms() != ws2->getNumberHistograms()) {
753 for (
size_t i = 0; i < ws1->getNumberHistograms(); i++) {
754 const auto &spec1 = ws1->getSpectrum(i);
755 const auto &spec2 = ws2->getSpectrum(i);
756 if (spec1.getSpectrumNo() != spec2.getSpectrumNo()) {
760 if (spec1.getDetectorIDs().size() != spec2.getDetectorIDs().size()) {
761 std::ostringstream out;
762 out <<
"Number of detector IDs mismatch: " << spec1.getDetectorIDs().size() <<
" vs "
763 << spec2.getDetectorIDs().size() <<
" at workspace index " << i;
767 auto it2 = spec2.getDetectorIDs().cbegin();
768 for (
auto it1 = spec1.getDetectorIDs().cbegin(); it1 != spec1.getDetectorIDs().cend(); ++it1, ++it2) {
799 if (ws1->getInstrument()->getName() != ws2->getInstrument()->getName()) {
800 g_log.
debug() <<
"Instrument names: WS1 = " << ws1->getInstrument()->getName()
801 <<
" WS2 = " << ws2->getInstrument()->getName() <<
"\n";
806 if (!ws1->detectorInfo().isEquivalent(ws2->detectorInfo())) {
807 recordMismatch(
"DetectorInfo mismatch (position differences larger than "
808 "1e-9 m or other difference found)");
812 if (!ws1->componentInfo().hasEquivalentSource(ws2->componentInfo())) {
813 recordMismatch(
"Source mismatch: either one workspace has a source and the "
814 "other does not, or the sources are at different positions");
818 if (!ws1->componentInfo().hasEquivalentSample(ws2->componentInfo())) {
819 recordMismatch(
"Sample mismatch: either one workspace has a sample and the "
820 "other does not, or the samples are at different positions");
827 const bool checkAllData =
getProperty(
"CheckAllData");
828 auto errorStr = ws1_parmap.
diff(ws2_parmap, !checkAllData);
829 if (!errorStr.empty()) {
830 g_log.
debug() <<
"Here information to help understand parameter map differences:\n";
832 recordMismatch(
"Instrument ParameterMap mismatch (differences in ordering ignored)");
848 const auto numHists =
static_cast<int>(ws1->getNumberHistograms());
850 for (
int i = 0; i < numHists; ++i) {
851 const bool ws1_masks = ws1->hasMaskedBins(i);
852 if (ws1_masks != ws2->hasMaskedBins(i)) {
853 g_log.
debug() <<
"Only one workspace has masked bins for spectrum " << i <<
"\n";
859 if (ws1_masks && ws1->maskedBins(i) != ws2->maskedBins(i)) {
860 g_log.
debug() <<
"Mask lists for spectrum " << i <<
" do not match\n";
877 std::string
const name1 = sample1.
getName();
878 std::string
const name2 = sample2.
getName();
879 if (name1 != name2) {
899 double run1Charge(-1.0);
904 double run2Charge(-1.0);
910 if (run1Charge != run2Charge) {
911 g_log.
debug() <<
"WS1 proton charge: " << run1Charge <<
"\n";
912 g_log.
debug() <<
"WS2 proton charge: " << run2Charge <<
"\n";
917 std::vector<Kernel::Property *> ws1logs = run1.
getLogData();
918 std::vector<Kernel::Property *> ws2logs = run2.
getLogData();
920 if (ws1logs.size() != ws2logs.size()) {
921 g_log.
debug() <<
"WS1 number of logs: " << ws1logs.size() <<
"\n";
922 g_log.
debug() <<
"WS2 number of logs: " << ws2logs.size() <<
"\n";
928 std::sort(ws1logs.begin(), ws1logs.end(), compareNames);
929 std::sort(ws2logs.begin(), ws2logs.end(), compareNames);
930 for (
size_t i = 0; i < ws1logs.size(); ++i) {
931 if (*(ws1logs[i]) != *(ws2logs[i])) {
932 if (
g_log.
is(Logger::Priority::PRIO_DEBUG)) {
960 double tolWeight, int64_t tolPulse,
bool printdetails,
961 size_t &numdiffpulse,
size_t &numdifftof,
size_t &numdiffboth,
962 size_t &numdiffweight)
const {
965 throw std::runtime_error(
"compareEventsListInDetails only work on 2 event lists with same "
966 "number of events.");
970 return compareEventLists<Types::Event::TofEvent>(
g_log, el1, el2, tolTof, tolWeight, tolPulse, printdetails,
971 numdiffpulse, numdifftof, numdiffboth, numdiffweight);
972 case EventType::WEIGHTED:
973 return compareEventLists<DataObjects::WeightedEvent>(
g_log, el1, el2, tolTof, tolWeight, tolPulse, printdetails,
974 numdiffpulse, numdifftof, numdiffboth, numdiffweight);
975 case EventType::WEIGHTED_NOTIME:
976 return compareEventLists<DataObjects::WeightedEventNoTime>(
g_log, el1, el2, tolTof, tolWeight, tolPulse,
977 printdetails, numdiffpulse, numdifftof, numdiffboth,
980 throw std::runtime_error(
"Cannot compare event lists: unknown event type.");
987 if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) {
991 if (tws1->columnCount() != tws2->columnCount()) {
999 sortPeaks->setProperty(
"InputWorkspace", tws1);
1000 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1001 sortPeaks->setProperty(
"SortAscending",
true);
1002 sortPeaks->executeAsChildAlg();
1004 tws1 = std::dynamic_pointer_cast<PeaksWorkspace>(tmp1);
1007 sortPeaks->setProperty(
"InputWorkspace", tws2);
1008 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1009 sortPeaks->setProperty(
"SortAscending",
true);
1010 sortPeaks->executeAsChildAlg();
1012 tws2 = std::dynamic_pointer_cast<PeaksWorkspace>(tmp2);
1016 const bool isRelErr =
getProperty(
"ToleranceRelErr");
1017 for (
int i = 0; i < tws1->getNumberPeaks(); i++) {
1018 const Peak &peak1 = tws1->getPeak(i);
1019 const Peak &peak2 = tws2->getPeak(i);
1020 for (
size_t j = 0; j < tws1->columnCount(); j++) {
1021 std::shared_ptr<const API::Column> col = tws1->getColumn(j);
1022 std::string
name = col->name();
1025 if (
name ==
"RunNumber") {
1028 }
else if (
name ==
"DetId") {
1031 }
else if (
name ==
"h") {
1034 }
else if (
name ==
"k") {
1037 }
else if (
name ==
"l") {
1040 }
else if (
name ==
"Wavelength") {
1043 }
else if (
name ==
"Energy") {
1046 }
else if (
name ==
"TOF") {
1049 }
else if (
name ==
"DSpacing") {
1052 }
else if (
name ==
"Intens") {
1055 }
else if (
name ==
"SigInt") {
1058 }
else if (
name ==
"BinCount") {
1061 }
else if (
name ==
"Row") {
1064 }
else if (
name ==
"Col") {
1070 bool mismatch =
false;
1075 }
else if (std::fabs(s1 - s2) >
tolerance) {
1081 <<
"cell (row#, col#): (" << i <<
"," << j <<
")\n"
1082 <<
"value1 = " << s1 <<
"\n"
1083 <<
"value2 = " << s2 <<
"\n";
1095 if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) {
1099 if (tws1->columnCount() != tws2->columnCount()) {
1106 sortPeaks->setProperty(
"InputWorkspace", tws1);
1107 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1108 sortPeaks->setProperty(
"SortAscending",
true);
1109 sortPeaks->executeAsChildAlg();
1113 sortPeaks->setProperty(
"InputWorkspace", tws2);
1114 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1115 sortPeaks->setProperty(
"SortAscending",
true);
1116 sortPeaks->executeAsChildAlg();
1120 const bool isRelErr =
getProperty(
"ToleranceRelErr");
1121 for (
int peakIndex = 0; peakIndex < ipws1->getNumberPeaks(); peakIndex++) {
1122 for (
size_t j = 0; j < ipws1->columnCount(); j++) {
1123 std::shared_ptr<const API::Column> col = ipws1->getColumn(j);
1124 const std::string
name = col->name();
1127 if (
name ==
"RunNumber") {
1128 s1 = double(ipws1->getPeak(peakIndex).getRunNumber());
1129 s2 = double(ipws2->getPeak(peakIndex).getRunNumber());
1130 }
else if (
name ==
"h") {
1131 s1 = ipws1->getPeak(peakIndex).getH();
1132 s2 = ipws2->getPeak(peakIndex).getH();
1133 }
else if (
name ==
"k") {
1134 s1 = ipws1->getPeak(peakIndex).getK();
1135 s2 = ipws2->getPeak(peakIndex).getK();
1136 }
else if (
name ==
"l") {
1137 s1 = ipws1->getPeak(peakIndex).getL();
1138 s2 = ipws2->getPeak(peakIndex).getL();
1139 }
else if (
name ==
"Wavelength") {
1140 s1 = ipws1->getPeak(peakIndex).getWavelength();
1141 s2 = ipws2->getPeak(peakIndex).getWavelength();
1142 }
else if (
name ==
"DSpacing") {
1143 s1 = ipws1->getPeak(peakIndex).getDSpacing();
1144 s2 = ipws2->getPeak(peakIndex).getDSpacing();
1145 }
else if (
name ==
"Intens") {
1146 s1 = ipws1->getPeak(peakIndex).getIntensity();
1147 s2 = ipws2->getPeak(peakIndex).getIntensity();
1148 }
else if (
name ==
"SigInt") {
1149 s1 = ipws1->getPeak(peakIndex).getSigmaIntensity();
1150 s2 = ipws2->getPeak(peakIndex).getSigmaIntensity();
1151 }
else if (
name ==
"BinCount") {
1152 s1 = ipws1->getPeak(peakIndex).getBinCount();
1153 s2 = ipws2->getPeak(peakIndex).getBinCount();
1154 }
else if (
name ==
"QLab") {
1155 V3D q1 = ipws1->getPeak(peakIndex).getQLabFrame();
1156 V3D q2 = ipws2->getPeak(peakIndex).getQLabFrame();
1158 for (
int i = 0; i < 3; ++i) {
1159 s1 += (q1[i] - q2[i]) * (q1[i] - q2[i]);
1164 s1 /= 0.5 * (q1.
norm() + q2.
norm());
1166 }
else if (
name ==
"QSample") {
1167 V3D q1 = ipws1->getPeak(peakIndex).getQSampleFrame();
1168 V3D q2 = ipws2->getPeak(peakIndex).getQSampleFrame();
1170 for (
int i = 0; i < 3; ++i) {
1171 s1 += (q1[i] - q2[i]) * (q1[i] - q2[i]);
1176 s1 /= 0.5 * (q1.
norm() + q2.
norm());
1181 bool mismatch =
false;
1182 if (isRelErr &&
name !=
"QLab" &&
name !=
"QSample") {
1186 }
else if (std::fabs(s1 - s2) >
tolerance) {
1192 <<
"cell (row#, col#): (" << peakIndex <<
"," << j <<
")\n"
1193 <<
"value1 = " << s1 <<
"\n"
1194 <<
"value2 = " << s2 <<
"\n";
1206 const auto numCols = tws1->columnCount();
1207 if (numCols != tws2->columnCount()) {
1208 g_log.
debug() <<
"Number of columns mismatch (" << numCols <<
" vs " << tws2->columnCount() <<
")\n";
1212 const auto numRows = tws1->rowCount();
1213 if (numRows != tws2->rowCount()) {
1214 g_log.
debug() <<
"Number of rows mismatch (" << numRows <<
" vs " << tws2->rowCount() <<
")\n";
1219 for (
size_t i = 0; i < numCols; ++i) {
1220 auto c1 = tws1->getColumn(i);
1221 auto c2 = tws2->getColumn(i);
1223 if (c1->name() != c2->name()) {
1224 g_log.
debug() <<
"Column name mismatch at column " << i <<
" (" << c1->name() <<
" vs " << c2->name() <<
")\n";
1228 if (c1->type() != c2->type()) {
1229 g_log.
debug() <<
"Column type mismatch at column " << i <<
" (" << c1->type() <<
" vs " << c2->type() <<
")\n";
1235 const bool checkAllData =
getProperty(
"CheckAllData");
1238 bool mismatch =
false;
1239 for (
size_t i = 0; i < numCols; ++i) {
1240 const auto c1 = tws1->getColumn(i);
1241 const auto c2 = tws2->getColumn(i);
1244 if (!c1->equalsRelErr(*c2,
tolerance)) {
1254 g_log.
debug() <<
"Table data mismatch at column " << i <<
"\n";
1257 if (!checkAllData) {
1267 mdws1 = std::dynamic_pointer_cast<IMDWorkspace>(w1);
1268 mdws2 = std::dynamic_pointer_cast<IMDWorkspace>(w2);
1274 alg->setProperty(
"Tolerance",
tolerance);
1275 alg->executeAsChildAlg();
1276 bool doesMatch = alg->getProperty(
"Equals");
1277 std::string algResult = alg->getProperty(
"Result");
1296 ws1 = w1->getName();
1300 ws2 = w2->getName();
1305 row << msg << ws1 << ws2;
1324 double num = std::fabs(x1 - x2);
1326 double den = 0.5 * (std::fabs(x1) + std::fabs(x2));
1328 return (num > errorVal);
1330 return (num / den > errorVal);
1333Parallel::ExecutionMode
1335 using namespace Parallel;
1336 if (storageModes.at(
"Workspace1") == StorageMode::Cloned) {
1337 if (storageModes.at(
"Workspace2") == StorageMode::Cloned)
1338 return getCorrespondingExecutionMode(StorageMode::Cloned);
1339 if (storageModes.at(
"Workspace2") == StorageMode::MasterOnly)
1340 return getCorrespondingExecutionMode(StorageMode::MasterOnly);
1342 if (storageModes.at(
"Workspace1") == StorageMode::MasterOnly) {
1343 if (storageModes.at(
"Workspace2") != StorageMode::Distributed)
1344 return getCorrespondingExecutionMode(StorageMode::MasterOnly);
1346 return ExecutionMode::Invalid;
#define DECLARE_ALGORITHM(classname)
#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...
#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.
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.
const Parallel::Communicator & communicator() const
Returns a const reference to the (MPI) communicator of the algorithm.
const std::vector< Kernel::Property * > & getProperties() const override
Get the list of managed properties.
Class to represent the axis of a workspace.
const std::string & title() const
Returns the user-defined title for this axis.
virtual bool isNumeric() const
Returns true if the axis is numeric.
const std::shared_ptr< Kernel::Unit > & unit() const
The unit for this axis.
virtual bool isSpectra() const
Returns true is the axis is a Spectra axis.
Kernel::Property * getLogData(const std::string &name) const
Access a single log entry.
virtual Axis * getAxis(const std::size_t &axisIndex) const
Get a non owning pointer to a workspace axis.
Class to represent a numeric axis of a workspace.
This class stores information regarding an experimental run as a series of log entries.
double getProtonCharge() const
Get the proton charge.
This class stores information about the sample used in particular run.
const std::string & getName() const
Returns the name of the sample.
TableRow represents a row in a TableWorkspace.
A property class for workspaces.
Compares two workspaces for equality.
bool compareEventWorkspaces(const DataObjects::EventWorkspace &ews1, const DataObjects::EventWorkspace &ews2)
Check whether 2 event lists are identical.
void execMasterOnly() override
Runs the algorithm in master-only execution mode.
bool checkInstrument(const API::MatrixWorkspace_const_sptr &ws1, const API::MatrixWorkspace_const_sptr &ws2)
int compareEventsListInDetails(const DataObjects::EventList &el1, const DataObjects::EventList &el2, double tolTof, double tolWeight, int64_t tolPulse, bool printdetails, size_t &numdiffpulse, size_t &numdifftof, size_t &numdiffboth, size_t &numdiffweight) const
Compare 2 EventsList.
bool m_parallelComparison
Variable states if one wants to compare workspaces in parallell.
std::unique_ptr< API::Progress > m_progress
Report progress of comparison.
void init() override
Initialise algorithm.
bool checkSample(const API::Sample &sample1, const API::Sample &sample2)
Checks that the sample matches.
void doPeaksComparison(DataObjects::PeaksWorkspace_sptr tws1, DataObjects::PeaksWorkspace_sptr tws2)
void exec() override
Execute algorithm.
bool m_result
Result of comparison (true if equal, false otherwise)
int version() const override
Algorithm's version for identification.
Parallel::ExecutionMode getParallelExecutionMode(const std::map< std::string, Parallel::StorageMode > &storageModes) const override
Get correct execution mode based on input storage modes for an MPI run.
void doMDComparison(const API::Workspace_sptr &w1, const API::Workspace_sptr &w2)
API::ITableWorkspace_sptr m_messages
Mismatch messages that resulted from comparison.
bool checkRunProperties(const API::Run &run1, const API::Run &run2)
Checks that the Run matches.
bool checkSpectraMap(const API::MatrixWorkspace_const_sptr &ws1, const API::MatrixWorkspace_const_sptr &ws2)
Checks that the spectra maps match.
bool processGroups() override
Process two groups and ensure the Result string is set properly on the final algorithm.
bool relErr(double x1, double x2, double errorVal) const
Function which calculates relative error between two values and analyses if this error is within the ...
void doLeanElasticPeaksComparison(const DataObjects::LeanElasticPeaksWorkspace_sptr &tws1, const DataObjects::LeanElasticPeaksWorkspace_sptr &tws2)
void doComparison()
CompareWorkspaces::doComparison.
bool checkMasking(const API::MatrixWorkspace_const_sptr &ws1, const API::MatrixWorkspace_const_sptr &ws2)
Checks that the bin masking matches.
const std::string name() const override
Algorithm's name.
void doTableComparison(const API::ITableWorkspace_const_sptr &tws1, const API::ITableWorkspace_const_sptr &tws2)
bool checkData(const API::MatrixWorkspace_const_sptr &ws1, const API::MatrixWorkspace_const_sptr &ws2)
Checks that the data matches.
void recordMismatch(const std::string &msg, std::string ws1="", std::string ws2="")
Records a mismatch in the Messages workspace and sets Result to false.
bool checkAxes(const API::MatrixWorkspace_const_sptr &ws1, const API::MatrixWorkspace_const_sptr &ws2)
Checks that the axes matches.
double getL() const override
Get the L index of the peak.
double getIntensity() const override
Return the integrated peak intensity.
double getSigmaIntensity() const override
Return the error on the integrated peak intensity.
double getK() const override
Get the K index of the peak.
int getRunNumber() const override
Return the run number this peak was measured at.
double getH() const override
Get the H index of the peak.
double getBinCount() const override
Return the # of counts in the bin at its peak.
std::vector< Types::Event::TofEvent > & getEvents()
Return the list of TofEvents contained.
bool equals(const EventList &rhs, const double tolTof, const double tolWeight, const int64_t tolPulse) const
std::size_t getNumberEvents() const override
Return the number of events in the list.
Mantid::API::EventType getEventType() const override
Return the type of Event vector contained within.
std::vector< WeightedEventNoTime > & getWeightedEventsNoTime()
Return the list of WeightedEvent contained.
std::vector< WeightedEvent > & getWeightedEvents()
Return the list of WeightedEvent contained.
This class is intended to fulfill the design specified in <https://github.com/mantidproject/documents...
EventList & getSpectrum(const size_t index) override
Return the underlying ISpectrum ptr at the given workspace index.
std::size_t getNumberHistograms() const override
Get the number of histograms, usually the same as the number of pixels or detectors.
bool threadSafe() const override
Returns true if the EventWorkspace is safe for multithreaded operations.
void sortAll(EventSortType sortType, Mantid::API::Progress *prog) const
Mantid::API::EventType getEventType() const override
Get the EventType of the most-specialized EventList in the workspace.
std::size_t getNumberEvents() const override
The total number of events across all of the spectra.
Structure describing a single-crystal peak.
int getCol() const override
For RectangularDetectors only, returns the column (x) of the pixel of the detector or -1 if not found...
double getDSpacing() const override
Calculate the d-spacing of the peak, in 1/Angstroms
int getRow() const override
For RectangularDetectors only, returns the row (y) of the pixel of the detector or -1 if not found.
double getInitialEnergy() const override
Get the initial (incident) neutron energy in meV.
double getWavelength() const override
Calculate the neutron wavelength (in angstroms) at the peak (Note for inelastic scattering - it is th...
double getTOF() const override
Calculate the time of flight (in microseconds) of the neutrons for this peak, using the geometry of t...
int getDetectorID() const
Get the ID of the detector at the center of the peak
const std::string diff(const ParameterMap &rhs, const bool &firstDiffOnly=false, const bool relative=false, const double doubleTolerance=Kernel::Tolerance) const
Output information that helps understanding the mismatch between two parameter maps.
Exception for when an item is not found in a collection.
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.
void debug(const std::string &msg)
Logs at debug level.
void notice(const std::string &msg)
Logs at notice level.
void warning(const std::string &msg)
Logs at warning level.
bool is(int level) const
Returns true if at least the given log level is set.
void information(const std::string &msg)
Logs at information level.
Base class for properties.
const std::string & name() const
Get the property's name.
virtual std::string value() const =0
Returns the value of the property as a string.
double norm() const noexcept
std::shared_ptr< const IMDEventWorkspace > IMDEventWorkspace_const_sptr
Shared pointer to Mantid::API::IMDEventWorkspace (const version)
std::shared_ptr< IPeaksWorkspace > IPeaksWorkspace_sptr
shared pointer to Mantid::API::IPeaksWorkspace
std::complex< double > MANTID_API_DLL E1(std::complex< double > z)
Integral for Gamma.
std::shared_ptr< ITableWorkspace > ITableWorkspace_sptr
shared pointer to Mantid::API::ITableWorkspace
std::shared_ptr< Workspace > Workspace_sptr
shared pointer to Mantid::API::Workspace
std::shared_ptr< const ITableWorkspace > ITableWorkspace_const_sptr
shared pointer to Mantid::API::ITableWorkspace (const version)
std::shared_ptr< const Workspace > Workspace_const_sptr
shared pointer to Mantid::API::Workspace (const version)
std::shared_ptr< const MatrixWorkspace > MatrixWorkspace_const_sptr
shared pointer to the matrix workspace base class (const version)
std::shared_ptr< IMDWorkspace > IMDWorkspace_sptr
Shared pointer to the IMDWorkspace base class.
std::shared_ptr< const WorkspaceGroup > WorkspaceGroup_const_sptr
shared pointer to Mantid::API::WorkspaceGroup, pointer to const version
std::shared_ptr< Algorithm > Algorithm_sptr
Typedef for a shared pointer to an Algorithm.
std::shared_ptr< const IMDHistoWorkspace > IMDHistoWorkspace_const_sptr
shared pointer to Mantid::API::IMDHistoWorkspace (const version)
std::shared_ptr< LeanElasticPeaksWorkspace > LeanElasticPeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< const EventWorkspace > EventWorkspace_const_sptr
shared pointer to a const Workspace2D
std::shared_ptr< PeaksWorkspace > PeaksWorkspace_sptr
Typedef for a shared pointer to a peaks workspace.
std::shared_ptr< const Unit > Unit_const_sptr
Shared pointer to the Unit base class (const version)
constexpr double Tolerance
Standard tolerance value.
constexpr int EMPTY_INT() noexcept
Returns what we consider an "empty" integer within a property.
@ Input
An input workspace.
@ Output
An output workspace.