Newer
Older
// Check that the number of separate logs is the same
if (ws1logs.size() != ws2logs.size()) {
g_log.debug() << "WS1 number of logs: " << ws1logs.size() << "\n";
g_log.debug() << "WS2 number of logs: " << ws2logs.size() << "\n";
recordMismatch("Different numbers of logs");
// Sort logs by name before one-by-one comparison
auto compareNames = [](Kernel::Property *p1, Kernel::Property *p2) {
return p1->name() < p2->name();
};
std::sort(ws1logs.begin(), ws1logs.end(), compareNames);
std::sort(ws2logs.begin(), ws2logs.end(), compareNames);
for (size_t i = 0; i < ws1logs.size(); ++i) {
if (*(ws1logs[i]) != *(ws2logs[i])) {
if (g_log.is(Logger::Priority::PRIO_DEBUG)) {
g_log.debug("WS1 log entry mismatch: " + ws1logs[i]->name());
g_log.debug("WS2 log entry mismatch: " + ws2logs[i]->name());
recordMismatch("Log mismatch");
}
//------------------------------------------------------------------------------------------------
/** Compare 2 different events list with detailed information output (Linear)
* It assumes that the number of events between these 2 are identical
* el1 :: event list 1
* el2 :: event list 2
* tolfTOF :: tolerance of Time-of-flight (in micro-second)
* tolWeight :: tolerance of weight for weighted neutron events
* tolPulse :: tolerance of pulse time (in nanosecond)
* NOTE: there is no need to compare the event type as it has been done by
* other tjype of check
* printdetails :: option for comparing. -1: simple, 0: full but no print, 1:
* full with print
* @return :: int. -1: different number of events; N > 0 : some
* events are not same
*/
int CompareWorkspaces::compareEventsListInDetails(
const EventList &el1, const EventList &el2, double tolTof, double tolWeight,
int64_t tolPulse, bool printdetails, size_t &numdiffpulse,
size_t &numdifftof, size_t &numdiffboth, size_t &numdiffweight) const {
// Check
if (el1.getNumberEvents() != el2.getNumberEvents())
throw std::runtime_error(
"compareEventsListInDetails only work on 2 event lists with same "
"number of events.");
switch (el1.getEventType()) {
case EventType::TOF:
return compareEventLists<Types::Event::TofEvent>(
g_log, el1, el2, tolTof, tolWeight, tolPulse, printdetails,
numdiffpulse, numdifftof, numdiffboth, numdiffweight);
case EventType::WEIGHTED:
return compareEventLists<DataObjects::WeightedEvent>(
g_log, el1, el2, tolTof, tolWeight, tolPulse, printdetails,
numdiffpulse, numdifftof, numdiffboth, numdiffweight);
case EventType::WEIGHTED_NOTIME:
return compareEventLists<DataObjects::WeightedEventNoTime>(
g_log, el1, el2, tolTof, tolWeight, tolPulse, printdetails,
numdiffpulse, numdifftof, numdiffboth, numdiffweight);
default:
throw std::runtime_error("Cannot compare event lists: unknown event type.");
//------------------------------------------------------------------------------------------------
void CompareWorkspaces::doPeaksComparison(PeaksWorkspace_sptr tws1,
PeaksWorkspace_sptr tws2) {
// Check some table-based stuff
if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) {
recordMismatch("Mismatched number of rows.");
return;
}
if (tws1->columnCount() != tws2->columnCount()) {
recordMismatch("Mismatched number of columns.");
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
return;
}
// sort the workspaces before comparing
{
auto sortPeaks = createChildAlgorithm("SortPeaksWorkspace");
sortPeaks->setProperty("InputWorkspace", tws1);
sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing");
sortPeaks->setProperty("SortAscending", true);
sortPeaks->executeAsChildAlg();
tws1 = sortPeaks->getProperty("OutputWorkspace");
sortPeaks = createChildAlgorithm("SortPeaksWorkspace");
sortPeaks->setProperty("InputWorkspace", tws2);
sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing");
sortPeaks->setProperty("SortAscending", true);
sortPeaks->executeAsChildAlg();
tws2 = sortPeaks->getProperty("OutputWorkspace");
}
const double tolerance = getProperty("Tolerance");
for (int i = 0; i < tws1->getNumberPeaks(); i++) {
const Peak &peak1 = tws1->getPeak(i);
const Peak &peak2 = tws2->getPeak(i);
for (size_t j = 0; j < tws1->columnCount(); j++) {
std::shared_ptr<const API::Column> col = tws1->getColumn(j);
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
std::string name = col->name();
double s1 = 0.0;
double s2 = 0.0;
if (name == "runnumber") {
s1 = double(peak1.getRunNumber());
s2 = double(peak2.getRunNumber());
} else if (name == "detid") {
s1 = double(peak1.getDetectorID());
s2 = double(peak2.getDetectorID());
} else if (name == "h") {
s1 = peak1.getH();
s2 = peak2.getH();
} else if (name == "k") {
s1 = peak1.getK();
s2 = peak2.getK();
} else if (name == "l") {
s1 = peak1.getL();
s2 = peak2.getL();
} else if (name == "wavelength") {
s1 = peak1.getWavelength();
s2 = peak2.getWavelength();
} else if (name == "energy") {
s1 = peak1.getInitialEnergy();
s2 = peak2.getInitialEnergy();
} else if (name == "tof") {
s1 = peak1.getTOF();
s2 = peak2.getTOF();
} else if (name == "dspacing") {
s1 = peak1.getDSpacing();
s2 = peak2.getDSpacing();
} else if (name == "intens") {
s1 = peak1.getIntensity();
s2 = peak2.getIntensity();
} else if (name == "sigint") {
s1 = peak1.getSigmaIntensity();
s2 = peak2.getSigmaIntensity();
} else if (name == "bincount") {
s1 = peak1.getBinCount();
s2 = peak2.getBinCount();
} else if (name == "row") {
s1 = peak1.getRow();
s2 = peak2.getRow();
} else if (name == "col") {
s1 = peak1.getCol();
s2 = peak2.getCol();
}
if (std::fabs(s1 - s2) > tolerance) {
g_log.debug() << "Data mismatch at cell (row#,col#): (" << i << "," << j
<< ")\n";
recordMismatch("Data mismatch");
return;
}
}
}
}
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
//------------------------------------------------------------------------------------------------
void CompareWorkspaces::doLeanElasticPeaksComparison(
LeanElasticPeaksWorkspace_sptr tws1, LeanElasticPeaksWorkspace_sptr tws2) {
// Check some table-based stuff
if (tws1->getNumberPeaks() != tws2->getNumberPeaks()) {
recordMismatch("Mismatched number of rows.");
return;
}
if (tws1->columnCount() != tws2->columnCount()) {
recordMismatch("Mismatched number of columns.");
return;
}
// sort the workspaces before comparing
auto sortPeaks = createChildAlgorithm("SortPeaksWorkspace");
sortPeaks->setProperty("InputWorkspace", tws1);
sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing");
sortPeaks->setProperty("SortAscending", true);
sortPeaks->executeAsChildAlg();
IPeaksWorkspace_sptr ipws1 = sortPeaks->getProperty("OutputWorkspace");
sortPeaks = createChildAlgorithm("SortPeaksWorkspace");
sortPeaks->setProperty("InputWorkspace", tws2);
sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing");
sortPeaks->setProperty("SortAscending", true);
sortPeaks->executeAsChildAlg();
IPeaksWorkspace_sptr ipws2 = sortPeaks->getProperty("OutputWorkspace");
const double tolerance = getProperty("Tolerance");
for (int i = 0; i < ipws1->getNumberPeaks(); i++) {
for (size_t j = 0; j < ipws1->columnCount(); j++) {
std::shared_ptr<const API::Column> col = ipws1->getColumn(j);
std::string name = col->name();
double s1 = 0.0;
double s2 = 0.0;
if (name == "runnumber") {
s1 = double(ipws1->getPeak(i).getRunNumber());
s2 = double(ipws2->getPeak(i).getRunNumber());
} else if (name == "h") {
s1 = ipws1->getPeak(i).getH();
s2 = ipws2->getPeak(i).getH();
} else if (name == "k") {
s1 = ipws1->getPeak(i).getK();
s2 = ipws2->getPeak(i).getK();
} else if (name == "l") {
s1 = ipws1->getPeak(i).getL();
s2 = ipws2->getPeak(i).getL();
} else if (name == "wavelength") {
s1 = ipws1->getPeak(i).getWavelength();
s2 = ipws2->getPeak(i).getWavelength();
} else if (name == "energy") {
s1 = ipws1->getPeak(i).getFinalEnergy();
s2 = ipws2->getPeak(i).getFinalEnergy();
} else if (name == "tof") {
s1 = ipws1->getPeak(i).getTOF();
s2 = ipws2->getPeak(i).getTOF();
} else if (name == "dspacing") {
s1 = ipws1->getPeak(i).getDSpacing();
s2 = ipws2->getPeak(i).getDSpacing();
} else if (name == "intens") {
s1 = ipws1->getPeak(i).getIntensity();
s2 = ipws2->getPeak(i).getIntensity();
} else if (name == "sigint") {
s1 = ipws1->getPeak(i).getSigmaIntensity();
s2 = ipws2->getPeak(i).getSigmaIntensity();
} else if (name == "bincount") {
s1 = ipws1->getPeak(i).getBinCount();
s2 = ipws2->getPeak(i).getBinCount();
} else if (name == "row") {
s1 = ipws1->getPeak(i).getRow();
s2 = ipws2->getPeak(i).getRow();
} else if (name == "col") {
s1 = ipws1->getPeak(i).getCol();
s2 = ipws2->getPeak(i).getCol();
}
if (std::fabs(s1 - s2) > tolerance) {
g_log.debug() << "Data mismatch at cell (row#,col#): (" << i << "," << j
<< ")\n";
recordMismatch("Data mismatch");
return;
}
}
}
}
//------------------------------------------------------------------------------------------------
void CompareWorkspaces::doTableComparison(
const API::ITableWorkspace_const_sptr &tws1,
const API::ITableWorkspace_const_sptr &tws2) {
// First the easy things
const auto numCols = tws1->columnCount();
if (numCols != tws2->columnCount()) {
g_log.debug() << "Number of columns mismatch (" << numCols << " vs "
<< tws2->columnCount() << ")\n";
recordMismatch("Number of columns mismatch");
return;
}
const auto numRows = tws1->rowCount();
if (numRows != tws2->rowCount()) {
g_log.debug() << "Number of rows mismatch (" << numRows << " vs "
<< tws2->rowCount() << ")\n";
recordMismatch("Number of rows mismatch");
return;
}
for (size_t i = 0; i < numCols; ++i) {
auto c1 = tws1->getColumn(i);
auto c2 = tws2->getColumn(i);
if (c1->name() != c2->name()) {
g_log.debug() << "Column name mismatch at column " << i << " ("
<< c1->name() << " vs " << c2->name() << ")\n";
recordMismatch("Column name mismatch");
return;
}
if (c1->type() != c2->type()) {
g_log.debug() << "Column type mismatch at column " << i << " ("
<< c1->type() << " vs " << c2->type() << ")\n";
recordMismatch("Column type mismatch");
return;
}
}
const bool checkAllData = getProperty("CheckAllData");
const bool relErr = getProperty("ToleranceRelErr");
const double tolerance = getProperty("Tolerance");
for (size_t i = 0; i < numCols; ++i) {
const auto c1 = tws1->getColumn(i);
const auto c2 = tws2->getColumn(i);
if (!c1->equalsRelErr(*c2, tolerance)) {
mismatch = true;
if (!c1->equals(*c2, tolerance)) {
mismatch = true;
}
}
if (mismatch) {
g_log.debug() << "Table data mismatch at column " << i << "\n";
recordMismatch("Table data mismatch");
mismatch = false;
if (!checkAllData) {
}
} // loop over columns
}
//------------------------------------------------------------------------------------------------
void CompareWorkspaces::doMDComparison(const Workspace_sptr &w1,
const Workspace_sptr &w2) {
IMDWorkspace_sptr mdws1, mdws2;
mdws1 = std::dynamic_pointer_cast<IMDWorkspace>(w1);
mdws2 = std::dynamic_pointer_cast<IMDWorkspace>(w2);
IAlgorithm_sptr alg = this->createChildAlgorithm("CompareMDWorkspaces");
alg->setProperty<IMDWorkspace_sptr>("Workspace1", mdws1);
alg->setProperty<IMDWorkspace_sptr>("Workspace2", mdws2);
const double tolerance = getProperty("Tolerance");
alg->setProperty("Tolerance", tolerance);
alg->executeAsChildAlg();
bool doesMatch = alg->getProperty("Equals");
std::string algResult = alg->getProperty("Result");
if (!doesMatch) {
recordMismatch(algResult);
//------------------------------------------------------------------------------------------------
/**
* Records a mismatch that has occurred in the output workspace and sets the
* Result to indicate that the input workspaces did not match.
*
* @param msg Mismatch message to be logged in output workspace
* @param ws1 Name of first workspace being compared
* @param ws2 Name of second workspace being compared
void CompareWorkspaces::recordMismatch(const std::string &msg, std::string ws1,
std::string ws2) {
// Workspace names default to the workspaces currently being compared
if (ws1.empty()) {
Workspace_const_sptr w1 = getProperty("Workspace1");
}
if (ws2.empty()) {
Workspace_const_sptr w2 = getProperty("Workspace2");
}
// Add new row and flag this comparison as a mismatch
TableRow row = m_messages->appendRow();
row << msg << ws1 << ws2;
//------------------------------------------------------------------------------------------------
/** Function which calculates relative error between two values and analyses if
this error is within the limits
* requested. When the absolute value of the difference is smaller then the value
of the error requested,
* absolute error is used instead of relative error.
@param x1 -- first value to check difference
@param x2 -- second value to check difference
@param errorVal -- the value of the error, to check against. Should be large
then 0
@returns true if error or false if the value is within the limits requested
*/
bool CompareWorkspaces::relErr(double x1, double x2, double errorVal) const {
double num = std::fabs(x1 - x2);
// how to treat x1<0 and x2 > 0 ? probably this way
double den = 0.5 * (std::fabs(x1) + std::fabs(x2));
if (den < errorVal)
return (num > errorVal);
return (num / den > errorVal);
}
Parallel::ExecutionMode CompareWorkspaces::getParallelExecutionMode(
const std::map<std::string, Parallel::StorageMode> &storageModes) const {
using namespace Parallel;
if (storageModes.at("Workspace1") == StorageMode::Cloned) {
if (storageModes.at("Workspace2") == StorageMode::Cloned)
return getCorrespondingExecutionMode(StorageMode::Cloned);
if (storageModes.at("Workspace2") == StorageMode::MasterOnly)
return getCorrespondingExecutionMode(StorageMode::MasterOnly);
}
if (storageModes.at("Workspace1") == StorageMode::MasterOnly) {
if (storageModes.at("Workspace2") != StorageMode::Distributed)
return getCorrespondingExecutionMode(StorageMode::MasterOnly);
}
return ExecutionMode::Invalid;
}
void CompareWorkspaces::execMasterOnly() {
if (communicator().rank() == 0)
exec();
else
setProperty("Result", true);
}
} // namespace Algorithms
} // namespace Mantid