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];
79 if (diffpulse && difftof)
88 bool same = (!diffpulse) && (!difftof) && (!diffweight);
92 std::stringstream outss;
93 outss <<
"Spectrum ? Event " << i <<
": ";
95 outss <<
"Diff-Pulse: " << e1.pulseTime() <<
" vs. " << e2.pulseTime() <<
"; ";
97 outss <<
"Diff-TOF: " << e1.tof() <<
" vs. " << e2.tof() <<
";";
99 outss <<
"Diff-Weight: " << e1.weight() <<
" vs. " << e2.weight() <<
";";
115 "The name of the first input workspace.");
117 "The name of the second input workspace.");
119 declareProperty(
"Tolerance", 1e-10,
"The maximum amount by which values may differ between the workspaces.");
122 "Whether to check that the y-value uncertainties (E) match "
123 "(only for matrix workspaces). ");
125 "Whether to check that the data types "
126 "(Workspace2D vs EventWorkspace) match.");
127 declareProperty(
"CheckAxes",
true,
"Whether to check that the axes match.");
128 declareProperty(
"CheckSpectraMap",
true,
"Whether to check that the spectra-detector maps match. ");
129 declareProperty(
"CheckInstrument",
true,
"Whether to check that the instruments match. ");
130 declareProperty(
"CheckMasking",
true,
"Whether to check that the bin masking matches. ");
133 declareProperty(
"CheckSample",
false,
"Whether to check that the sample (e.g. logs).");
136 "Treat tolerance as relative error rather then the absolute error.\n"
137 "This is only applicable to Matrix workspaces.");
141 "Usually checking data ends when first mismatch occurs. This "
142 "forces algorithm to check all data and print mismatch to "
144 "Very often such logs are huge so making it true should be "
147 declareProperty(
"NaNsEqual",
false,
"Whether NaN values should compare as equal with other NaN values.");
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))
187 std::string message =
m_messages->cell<std::string>(0, 0);
188 g_log.
warning() <<
"The workspaces did not match: " << message <<
'\n';
192 g_log.
notice() <<
"The workspaces \"" << ws1 <<
"\" and \"" << ws2 <<
"\" matched!\n";
220 }
else if (!ws1 && !ws2) {
222 throw std::runtime_error(
"CompareWorkspaces::processGroups - Neither "
223 "input is a WorkspaceGroup. This is a logical "
224 "error in the code.");
225 }
else if (!ws1 || !ws2) {
226 recordMismatch(
"Type mismatch. One workspace is a group, the other is not.");
230 g_log.
notice() <<
"All workspaces in workspace groups \"" << ws1->getName() <<
"\" and \"" << ws2->getName()
247 const std::shared_ptr<const API::WorkspaceGroup> &groupTwo) {
250 const auto totalNum =
static_cast<size_t>(groupOne->getNumberOfEntries());
251 if (groupOne->getNumberOfEntries() != groupTwo->getNumberOfEntries()) {
257 const std::vector<Property *> &allProps = this->
getProperties();
258 std::vector<Property *> nonDefaultProps;
259 nonDefaultProps.reserve(allProps.size());
260 for (
auto p : allProps) {
261 const std::string &propName = p->name();
263 if (p->isDefault() || propName ==
"Workspace1" || propName ==
"Workspace2")
265 nonDefaultProps.emplace_back(p);
267 const size_t numNonDefault = nonDefaultProps.size();
269 const double progressFraction = 1.0 /
static_cast<double>(totalNum);
270 std::vector<std::string> namesOne = groupOne->getNames();
271 std::vector<std::string> namesTwo = groupTwo->getNames();
272 for (
size_t i = 0; i < totalNum; ++i) {
277 progressFraction *
static_cast<double>(i + 1),
false, this->
version());
278 checker->setPropertyValue(
"Workspace1", namesOne[i]);
279 checker->setPropertyValue(
"Workspace2", namesTwo[i]);
280 for (
size_t j = 0; j < numNonDefault; ++j) {
281 Property const *p = nonDefaultProps[j];
282 checker->setPropertyValue(p->
name(), p->
value());
286 bool success = checker->getProperty(
"Result");
289 recordMismatch(table->cell<std::string>(0, 0), namesOne[i], namesTwo[i]);
305 if (w1->id() ==
"PeaksWorkspace" || w2->id() ==
"PeaksWorkspace") {
313 if ((pws1 && !pws2) || (!pws1 && pws2)) {
314 recordMismatch(
"One workspace is a PeaksWorkspace and the other is not.");
328 if (w1->id() ==
"LeanElasticPeaksWorkspace" || w2->id() ==
"LeanElasticPeaksWorkspace") {
329 auto lpws1 = std::dynamic_pointer_cast<LeanElasticPeaksWorkspace>(w1);
330 auto lpws2 = std::dynamic_pointer_cast<LeanElasticPeaksWorkspace>(w2);
332 if ((lpws1 && !lpws2) || (!lpws1 && lpws2)) {
333 recordMismatch(
"One workspace is a LeanElasticPeaksWorkspace and the other is not.");
336 if (lpws1 && lpws2) {
347 auto tws1 = std::dynamic_pointer_cast<const ITableWorkspace>(w1);
348 auto tws2 = std::dynamic_pointer_cast<const ITableWorkspace>(w2);
349 if ((tws1 && !tws2) || (!tws1 && tws2)) {
350 recordMismatch(
"One workspace is a TableWorkspace and the other is not.");
365 if ((mdews1 && !mdews2) || (!mdews1 && mdews2)) {
366 recordMismatch(
"One workspace is an IMDEventWorkspace and the other is not.");
372 if ((mdhws1 && !mdhws2) || (!mdhws1 && mdhws2)) {
373 recordMismatch(
"One workspace is an IMDHistoWorkspace and the other is not.");
377 if (mdhws1 || mdews1)
394 if ((ews1 && !ews2) || (!ews1 && ews2)) {
395 recordMismatch(
"One workspace is an EventWorkspace and the other is not.");
397 }
else if (w1 && w2 && (w1->id() != w2->id())) {
398 std::stringstream msg;
399 msg <<
"Workspace ids do not match: \"" << w1->id() <<
"\" != \"" << w2->id() <<
"\"";
405 size_t numhist = ws1->getNumberHistograms();
411 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0, numhist * 5);
416 m_progress = std::make_unique<Progress>(
this, 0.0, 1.0, numhist * 2);
428 m_progress->reportIncrement(numhist / 5,
"Axes");
431 m_progress->reportIncrement(numhist / 5,
"SpectraMap");
434 m_progress->reportIncrement(numhist / 5,
"Instrument");
437 m_progress->reportIncrement(numhist / 5,
"Masking");
440 m_progress->reportIncrement(numhist / 5,
"Sample");
441 if (
static_cast<bool>(
getProperty(
"CheckSample"))) {
454 bool checkallspectra =
getProperty(
"CheckAllData");
455 int numspec2print =
getProperty(
"NumberMismatchedSpectraToPrint");
456 int wsindex2print =
getProperty(
"DetailedPrintIndex");
465 recordMismatch(
"Mismatched type of events in the EventWorkspaces.");
476 throw std::runtime_error(
"The progress pointer was found to be null!");
481 int64_t tolerancePulse = 1;
482 double toleranceTOF = 0.05;
483 if ((ews1.
getAxis(0)->
unit()->label().ascii() !=
"microsecond") ||
484 (ews2.
getAxis(0)->
unit()->label().ascii() !=
"microsecond")) {
486 << ews2.
getAxis(0)->
unit()->label().ascii() <<
". Tolerance of TOF is set to 0.05 still. "
490 g_log.
notice() <<
"TOF Tolerance = " << toleranceTOF <<
"\n";
492 bool mismatchedEvent =
false;
493 int mismatchedEventWI = 0;
495 size_t numUnequalNumEventsSpectra = 0;
496 size_t numUnequalEvents = 0;
497 size_t numUnequalTOFEvents = 0;
498 size_t numUnequalPulseEvents = 0;
499 size_t numUnequalBothEvents = 0;
500 size_t numUnequalWeights = 0;
502 std::vector<int> vec_mismatchedwsindex;
507 if (!mismatchedEvent || checkallspectra)
511 bool printdetail = (i == wsindex2print);
513 g_log.
information() <<
"Spectrum " << i <<
" is set to print out in details. "
517 if (!el1.
equals(el2, toleranceTOF, toleranceWeight, tolerancePulse)) {
518 size_t tempNumTof = 0;
519 size_t tempNumPulses = 0;
520 size_t tempNumBoth = 0;
521 size_t tempNumWeight = 0;
523 int tempNumUnequal = 0;
531 tempNumPulses, tempNumTof, tempNumBoth, tempNumWeight);
534 mismatchedEvent =
true;
535 mismatchedEventWI = i;
537 if (tempNumUnequal == -1) {
539 ++numUnequalNumEventsSpectra;
542 numUnequalEvents +=
static_cast<size_t>(tempNumUnequal);
543 numUnequalTOFEvents += tempNumTof;
544 numUnequalPulseEvents += tempNumPulses;
545 numUnequalBothEvents += tempNumBoth;
546 numUnequalWeights += tempNumWeight;
549 vec_mismatchedwsindex.emplace_back(i);
559 if (mismatchedEvent) {
560 std::ostringstream mess;
561 if (checkallspectra) {
562 if (numUnequalNumEventsSpectra > 0)
563 mess <<
"Total " << numUnequalNumEventsSpectra <<
" spectra have different number of events. "
566 mess <<
"Total " << numUnequalEvents <<
" (in " << ews1.
getNumberEvents() <<
") events are differrent. "
567 << numUnequalTOFEvents <<
" have different TOF; " << numUnequalPulseEvents <<
" have different pulse time; "
568 << numUnequalBothEvents <<
" have different in both TOF and pulse time; " << numUnequalWeights
569 <<
" have different weights."
572 mess <<
"Mismatched event lists include " << vec_mismatchedwsindex.size() <<
" of "
576 std::sort(vec_mismatchedwsindex.begin(), vec_mismatchedwsindex.end());
577 numspec2print = std::min(numspec2print,
static_cast<int>(vec_mismatchedwsindex.size()));
578 for (
int i = 0; i < numspec2print; ++i) {
579 mess << vec_mismatchedwsindex[i] <<
", ";
580 if ((i + 1) % 10 == 0)
584 mess <<
"Quick comparison shows 2 workspaces do not match. "
585 <<
"First found mismatched event list is at workspace index " << mismatchedEventWI;
606 const size_t numHists = ws1->getNumberHistograms();
607 bool raggedWorkspace{
false};
610 numBins = ws1->blocksize();
611 }
catch (std::length_error &) {
612 raggedWorkspace =
true;
614 const bool histogram = ws1->isHistogramData();
615 const bool checkAllData =
getProperty(
"CheckAllData");
616 const bool checkError =
getProperty(
"CheckUncertainty");
619 if (numHists != ws2->getNumberHistograms() ||
620 (raggedWorkspace ? !ws2->isRaggedWorkspace() : numBins != ws2->blocksize())) {
626 if (histogram != ws2->isHistogramData()) {
631 bool resultBool =
true;
632 bool logDebug =
g_log.
is(Logger::Priority::PRIO_DEBUG);
636 for (
long i = 0; i < static_cast<long>(numHists); ++i) {
640 if (resultBool || checkAllData)
643 const auto &X1 = ws1->x(i);
644 const auto &Y1 = ws1->y(i);
645 const auto &
E1 = ws1->e(i);
646 const auto &X2 = ws2->x(i);
647 const auto &Y2 = ws2->y(i);
648 const auto &E2 = ws2->e(i);
650 if (Y1.size() != Y2.size()) {
651 g_log.
debug() <<
"Spectra " << i <<
" have different lenghts, " << X1.size() <<
" vs " << X2.size() <<
"\n";
657 for (
int j = 0; j < static_cast<int>(Y1.size()); ++j) {
662 if (checkError && !err)
666 g_log.
debug() <<
"Data mismatch at cell (hist#,bin#): (" << i <<
"," << j <<
")\n";
667 g_log.
debug() <<
" Dataset #1 (X,Y,E) = (" << X1[j] <<
"," << Y1[j] <<
"," <<
E1[j] <<
")\n";
668 g_log.
debug() <<
" Dataset #2 (X,Y,E) = (" << X2[j] <<
"," << Y2[j] <<
"," << E2[j] <<
")\n";
669 g_log.
debug() <<
" Difference (X,Y,E) = (" << std::abs(X1[j] - X2[j]) <<
"," << std::abs(Y1[j] - Y2[j])
670 <<
"," << std::abs(
E1[j] - E2[j]) <<
")\n";
678 if (histogram && !
m_compare(X1.back(), X2.back())) {
680 g_log.
debug() <<
" Data ranges mismatch for spectra N: (" << i <<
")\n";
681 g_log.
debug() <<
" Last bin ranges (X1_end vs X2_end) = (" << X1.back() <<
"," << X2.back() <<
")\n";
708 const int numAxes = ws1->axes();
710 if (numAxes != ws2->axes()) {
715 for (
int i = 0; i < numAxes; ++i) {
716 std::ostringstream axis_name_ss;
717 axis_name_ss <<
"Axis " << i;
718 std::string axis_name = axis_name_ss.str();
720 const Axis *
const ax1 = ws1->getAxis(i);
721 const Axis *
const ax2 = ws2->getAxis(i);
736 if ((ax1_unit ==
nullptr && ax2_unit !=
nullptr) || (ax1_unit !=
nullptr && ax2_unit ==
nullptr) ||
737 (ax1_unit && ax1_unit->unitID() != ax2_unit->unitID())) {
746 const auto *na1 =
static_cast<const NumericAxis *
>(ax1);
748 if (!na1->equalWithinTolerance(*ax2,
tolerance)) {
752 }
else if (!ax1->
isSpectra() && !ax1->operator==(*ax2)) {
758 if (ws1->YUnit() != ws2->YUnit()) {
759 g_log.
debug() <<
"YUnit strings : WS1 = " << ws1->YUnit() <<
" WS2 = " << ws2->YUnit() <<
"\n";
765 if (ws1->isDistribution() != ws2->isDistribution()) {
766 g_log.
debug() <<
"Distribution flags: WS1 = " << ws1->isDistribution() <<
" WS2 = " << ws2->isDistribution()
783 if (ws1->getNumberHistograms() != ws2->getNumberHistograms()) {
788 for (
size_t i = 0; i < ws1->getNumberHistograms(); i++) {
789 const auto &spec1 = ws1->getSpectrum(i);
790 const auto &spec2 = ws2->getSpectrum(i);
791 if (spec1.getSpectrumNo() != spec2.getSpectrumNo()) {
795 if (spec1.getDetectorIDs().size() != spec2.getDetectorIDs().size()) {
796 std::ostringstream out;
797 out <<
"Number of detector IDs mismatch: " << spec1.getDetectorIDs().size() <<
" vs "
798 << spec2.getDetectorIDs().size() <<
" at workspace index " << i;
802 auto it2 = spec2.getDetectorIDs().cbegin();
803 for (
auto it1 = spec1.getDetectorIDs().cbegin(); it1 != spec1.getDetectorIDs().cend(); ++it1, ++it2) {
834 if (ws1->getInstrument()->getName() != ws2->getInstrument()->getName()) {
835 g_log.
debug() <<
"Instrument names: WS1 = " << ws1->getInstrument()->getName()
836 <<
" WS2 = " << ws2->getInstrument()->getName() <<
"\n";
841 if (!ws1->detectorInfo().isEquivalent(ws2->detectorInfo())) {
842 recordMismatch(
"DetectorInfo mismatch (position differences larger than "
843 "1e-9 m or other difference found)");
847 if (!ws1->componentInfo().hasEquivalentSource(ws2->componentInfo())) {
848 recordMismatch(
"Source mismatch: either one workspace has a source and the "
849 "other does not, or the sources are at different positions");
853 if (!ws1->componentInfo().hasEquivalentSample(ws2->componentInfo())) {
854 recordMismatch(
"Sample mismatch: either one workspace has a sample and the "
855 "other does not, or the samples are at different positions");
862 const bool checkAllData =
getProperty(
"CheckAllData");
863 auto errorStr = ws1_parmap.
diff(ws2_parmap, !checkAllData);
864 if (!errorStr.empty()) {
865 g_log.
debug() <<
"Here information to help understand parameter map differences:\n";
867 recordMismatch(
"Instrument ParameterMap mismatch (differences in ordering ignored)");
883 const auto numHists =
static_cast<int>(ws1->getNumberHistograms());
885 for (
int i = 0; i < numHists; ++i) {
886 const bool ws1_masks = ws1->hasMaskedBins(i);
887 if (ws1_masks != ws2->hasMaskedBins(i)) {
888 g_log.
debug() <<
"Only one workspace has masked bins for spectrum " << i <<
"\n";
894 if (ws1_masks && ws1->maskedBins(i) != ws2->maskedBins(i)) {
895 g_log.
debug() <<
"Mask lists for spectrum " << i <<
" do not match\n";
912 std::string
const name1 = sample1.
getName();
913 std::string
const name2 = sample2.
getName();
914 if (name1 != name2) {
934 double run1Charge(-1.0);
939 double run2Charge(-1.0);
945 if (run1Charge != run2Charge) {
946 g_log.
debug() <<
"WS1 proton charge: " << run1Charge <<
"\n";
947 g_log.
debug() <<
"WS2 proton charge: " << run2Charge <<
"\n";
952 std::vector<Kernel::Property *> ws1logs = run1.
getLogData();
953 std::vector<Kernel::Property *> ws2logs = run2.
getLogData();
955 if (ws1logs.size() != ws2logs.size()) {
956 g_log.
debug() <<
"WS1 number of logs: " << ws1logs.size() <<
"\n";
957 g_log.
debug() <<
"WS2 number of logs: " << ws2logs.size() <<
"\n";
963 std::sort(ws1logs.begin(), ws1logs.end(), compareNames);
964 std::sort(ws2logs.begin(), ws2logs.end(), compareNames);
965 for (
size_t i = 0; i < ws1logs.size(); ++i) {
966 if (*(ws1logs[i]) != *(ws2logs[i])) {
967 if (
g_log.
is(Logger::Priority::PRIO_DEBUG)) {
995 double tolWeight, int64_t tolPulse,
bool printdetails,
996 size_t &numdiffpulse,
size_t &numdifftof,
size_t &numdiffboth,
997 size_t &numdiffweight)
const {
1000 throw std::runtime_error(
"compareEventsListInDetails only work on 2 event lists with same "
1001 "number of events.");
1004 case EventType::TOF:
1005 return compareEventLists<Types::Event::TofEvent>(
g_log, el1, el2, tolTof, tolWeight, tolPulse, printdetails,
1006 numdiffpulse, numdifftof, numdiffboth, numdiffweight);
1007 case EventType::WEIGHTED:
1008 return compareEventLists<DataObjects::WeightedEvent>(
g_log, el1, el2, tolTof, tolWeight, tolPulse, printdetails,
1009 numdiffpulse, numdifftof, numdiffboth, numdiffweight);
1010 case EventType::WEIGHTED_NOTIME:
1011 return compareEventLists<DataObjects::WeightedEventNoTime>(
g_log, el1, el2, tolTof, tolWeight, tolPulse,
1012 printdetails, numdiffpulse, numdifftof, numdiffboth,
1015 throw std::runtime_error(
"Cannot compare event lists: unknown event type.");
1022 if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) {
1026 if (tws1->columnCount() != tws2->columnCount()) {
1034 sortPeaks->setProperty(
"InputWorkspace", tws1);
1035 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1036 sortPeaks->setProperty(
"SortAscending",
true);
1037 sortPeaks->executeAsChildAlg();
1039 tws1 = std::dynamic_pointer_cast<PeaksWorkspace>(tmp1);
1042 sortPeaks->setProperty(
"InputWorkspace", tws2);
1043 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1044 sortPeaks->setProperty(
"SortAscending",
true);
1045 sortPeaks->executeAsChildAlg();
1047 tws2 = std::dynamic_pointer_cast<PeaksWorkspace>(tmp2);
1050 const bool isRelErr =
getProperty(
"ToleranceRelErr");
1051 const bool checkAllData =
getProperty(
"CheckAllData");
1052 for (
int i = 0; i < tws1->getNumberPeaks(); i++) {
1053 const Peak &peak1 = tws1->getPeak(i);
1054 const Peak &peak2 = tws2->getPeak(i);
1055 for (std::size_t j = 0; j < tws1->columnCount(); j++) {
1056 std::shared_ptr<const API::Column> col = tws1->getColumn(j);
1057 std::string
name = col->name();
1062 if (
name ==
"RunNumber") {
1065 }
else if (
name ==
"DetId") {
1068 }
else if (
name ==
"h") {
1071 }
else if (
name ==
"k") {
1074 }
else if (
name ==
"l") {
1077 }
else if (
name ==
"Wavelength") {
1080 }
else if (
name ==
"Energy") {
1083 }
else if (
name ==
"TOF") {
1086 }
else if (
name ==
"DSpacing") {
1089 }
else if (
name ==
"Intens") {
1092 }
else if (
name ==
"SigInt") {
1095 }
else if (
name ==
"BinCount") {
1098 }
else if (
name ==
"Row") {
1101 }
else if (
name ==
"Col") {
1104 }
else if (
name ==
"IntHKL") {
1107 }
else if (
name ==
"IntMNP") {
1113 bool mismatch =
false;
1126 <<
"cell (row#, col#): (" << i <<
"," << j <<
")\n"
1127 <<
"value1 = " << s1 <<
"\n"
1128 <<
"value2 = " << s2 <<
"\n";
1141 if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) {
1145 if (tws1->columnCount() != tws2->columnCount()) {
1152 sortPeaks->setProperty(
"InputWorkspace", tws1);
1153 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1154 sortPeaks->setProperty(
"SortAscending",
true);
1155 sortPeaks->executeAsChildAlg();
1159 sortPeaks->setProperty(
"InputWorkspace", tws2);
1160 sortPeaks->setProperty(
"ColumnNameToSortBy",
"DSpacing");
1161 sortPeaks->setProperty(
"SortAscending",
true);
1162 sortPeaks->executeAsChildAlg();
1166 const bool isRelErr =
getProperty(
"ToleranceRelErr");
1167 const bool checkAllData =
getProperty(
"CheckAllData");
1169 for (
int peakIndex = 0; peakIndex < ipws1->getNumberPeaks(); peakIndex++) {
1170 for (std::size_t j = 0; j < ipws1->columnCount(); j++) {
1171 std::shared_ptr<const API::Column> col = ipws1->getColumn(j);
1172 const std::string
name = col->name();
1175 if (
name ==
"RunNumber") {
1176 s1 = double(ipws1->getPeak(peakIndex).getRunNumber());
1177 s2 = double(ipws2->getPeak(peakIndex).getRunNumber());
1178 }
else if (
name ==
"h") {
1179 s1 = ipws1->getPeak(peakIndex).getH();
1180 s2 = ipws2->getPeak(peakIndex).getH();
1181 }
else if (
name ==
"k") {
1182 s1 = ipws1->getPeak(peakIndex).getK();
1183 s2 = ipws2->getPeak(peakIndex).getK();
1184 }
else if (
name ==
"l") {
1185 s1 = ipws1->getPeak(peakIndex).getL();
1186 s2 = ipws2->getPeak(peakIndex).getL();
1187 }
else if (
name ==
"Wavelength") {
1188 s1 = ipws1->getPeak(peakIndex).getWavelength();
1189 s2 = ipws2->getPeak(peakIndex).getWavelength();
1190 }
else if (
name ==
"DSpacing") {
1191 s1 = ipws1->getPeak(peakIndex).getDSpacing();
1192 s2 = ipws2->getPeak(peakIndex).getDSpacing();
1193 }
else if (
name ==
"Intens") {
1194 s1 = ipws1->getPeak(peakIndex).getIntensity();
1195 s2 = ipws2->getPeak(peakIndex).getIntensity();
1196 }
else if (
name ==
"SigInt") {
1197 s1 = ipws1->getPeak(peakIndex).getSigmaIntensity();
1198 s2 = ipws2->getPeak(peakIndex).getSigmaIntensity();
1199 }
else if (
name ==
"BinCount") {
1200 s1 = ipws1->getPeak(peakIndex).getBinCount();
1201 s2 = ipws2->getPeak(peakIndex).getBinCount();
1202 }
else if (
name ==
"QLab") {
1203 V3D q1 = ipws1->getPeak(peakIndex).getQLabFrame();
1204 V3D q2 = ipws2->getPeak(peakIndex).getQLabFrame();
1206 for (
int i = 0; i < 3; ++i) {
1207 s1 += (q1[i] - q2[i]) * (q1[i] - q2[i]);
1212 s1 /= 0.5 * (q1.
norm() + q2.
norm());
1214 }
else if (
name ==
"QSample") {
1215 V3D q1 = ipws1->getPeak(peakIndex).getQSampleFrame();
1216 V3D q2 = ipws2->getPeak(peakIndex).getQSampleFrame();
1218 for (
int i = 0; i < 3; ++i) {
1219 s1 += (q1[i] - q2[i]) * (q1[i] - q2[i]);
1224 s1 /= 0.5 * (q1.
norm() + q2.
norm());
1229 bool mismatch =
false;
1234 if (isRelErr &&
name !=
"QLab" &&
name !=
"QSample") {
1244 <<
"cell (row#, col#): (" << peakIndex <<
"," << j <<
")\n"
1245 <<
"value1 = " << s1 <<
"\n"
1246 <<
"value2 = " << s2 <<
"\n";
1259 const auto numCols = tws1->columnCount();
1260 if (numCols != tws2->columnCount()) {
1261 g_log.
debug() <<
"Number of columns mismatch (" << numCols <<
" vs " << tws2->columnCount() <<
")\n";
1265 const auto numRows = tws1->rowCount();
1266 if (numRows != tws2->rowCount()) {
1267 g_log.
debug() <<
"Number of rows mismatch (" << numRows <<
" vs " << tws2->rowCount() <<
")\n";
1272 for (
size_t i = 0; i < numCols; ++i) {
1273 auto c1 = tws1->getColumn(i);
1274 auto c2 = tws2->getColumn(i);
1276 if (c1->name() != c2->name()) {
1277 g_log.
debug() <<
"Column name mismatch at column " << i <<
" (" << c1->name() <<
" vs " << c2->name() <<
")\n";
1281 if (c1->type() != c2->type()) {
1282 g_log.
debug() <<
"Column type mismatch at column " << i <<
" (" << c1->type() <<
" vs " << c2->type() <<
")\n";
1288 const bool checkAllData =
getProperty(
"CheckAllData");
1289 const bool isRelErr =
getProperty(
"ToleranceRelErr");
1293 for (std::size_t i = 0; i < numCols; ++i) {
1294 const auto c1 = tws1->getColumn(i);
1295 const auto c2 = tws2->getColumn(i);
1298 mismatch = !c1->equalsRelErr(*c2,
tolerance, nanEqual);
1300 mismatch = !c1->equals(*c2,
tolerance, nanEqual);
1303 g_log.
debug() <<
"Table data mismatch at column " << i <<
"\n";
1304 for (std::size_t j = 0; j < c1->size(); j++) {
1305 g_log.
debug() <<
"\t" << j <<
" | " << c1->cell<
double>(j) <<
", " << c2->cell<
double>(j) <<
"\n";
1308 if (!checkAllData) {
1318 mdws1 = std::dynamic_pointer_cast<IMDWorkspace>(w1);
1319 mdws2 = std::dynamic_pointer_cast<IMDWorkspace>(w2);
1325 alg->setProperty(
"Tolerance",
tolerance);
1326 alg->executeAsChildAlg();
1327 bool doesMatch = alg->getProperty(
"Equals");
1328 std::string algResult = alg->getProperty(
"Result");
1347 ws1 = w1->getName();
1351 ws2 = w2->getName();
1356 row << msg << ws1 << ws2;
1372 bool const nanEqual) {
1373 if (nanEqual && std::isnan(x1) && std::isnan(x2))
1391 bool const nanEqual) {
1392 if (nanEqual && std::isnan(x1) && std::isnan(x2))
#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 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.
bool checkInstrument(const API::MatrixWorkspace_const_sptr &ws1, const API::MatrixWorkspace_const_sptr &ws2)
static bool withinAbsoluteTolerance(double x1, double x2, double atol, bool const nanEqual=false)
Function which calculates absolute error between two values and analyses if this error is within the ...
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.
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.
void doLeanElasticPeaksComparison(const DataObjects::LeanElasticPeaksWorkspace_sptr &tws1, const DataObjects::LeanElasticPeaksWorkspace_sptr &tws2)
void doComparison()
CompareWorkspaces::doComparison.
std::function< bool(const double, const double)> m_compare
The comparison method to use (true if equal, false otherwise)
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.
static bool withinRelativeTolerance(double x1, double x2, double rtol, bool const nanEqual=false)
Function which calculates relative error between two values and analyses if this error is within the ...
bool checkAxes(const API::MatrixWorkspace_const_sptr &ws1, const API::MatrixWorkspace_const_sptr &ws2)
Checks that the axes matches.
Mantid::Kernel::V3D getIntMNP() const override
Return the int MNP vector.
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.
Mantid::Kernel::V3D getIntHKL() const override
Return the int HKL vector.
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.
int getDetectorID() const override
Get the ID of the detector at the center of the peak
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...
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.
MANTID_KERNEL_DLL bool withinRelativeDifference(T const x, T const y, S const tolerance)
Test whether x, y are within relative tolerance tol.
std::shared_ptr< const Unit > Unit_const_sptr
Shared pointer to the Unit base class (const version)
MANTID_KERNEL_DLL bool withinAbsoluteDifference(T const x, T const y, S const tolerance)
Test whether x, y are within absolute tolerance tol.
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.