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.");
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 tmp1 = sortPeaks->getProperty("OutputWorkspace");
tws1 = std::dynamic_pointer_cast<PeaksWorkspace>(tmp1);
sortPeaks = createChildAlgorithm("SortPeaksWorkspace");
sortPeaks->setProperty("InputWorkspace", tws2);
sortPeaks->setProperty("ColumnNameToSortBy", "DSpacing");
sortPeaks->setProperty("SortAscending", true);
sortPeaks->executeAsChildAlg();
IPeaksWorkspace_sptr tmp2 = sortPeaks->getProperty("OutputWorkspace");
tws2 = std::dynamic_pointer_cast<PeaksWorkspace>(tmp2);
}
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);
std::string name = col->name();
double s1 = 0.0;
double s2 = 0.0;
if (name == "RunNumber") {
s1 = double(peak1.getRunNumber());
s2 = double(peak2.getRunNumber());
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();
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();
s1 = peak1.getRow();
s2 = peak2.getRow();
s1 = peak1.getCol();
s2 = peak2.getCol();
}
if (std::fabs(s1 - s2) > tolerance) {
g_log.debug(name);
g_log.debug() << "s1 = " << s1 << "\n"
<< "s2 = " << s2 << "\n"
<< "std::fabs(s1 - s2) = " << std::fabs(s1 - s2) << "\n"
<< "tolerance = " << tolerance << "\n";
g_log.debug() << "Data mismatch at cell (row#,col#): (" << i << "," << j
<< ")\n";
recordMismatch("Data mismatch");
return;
}
}
}
}
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
//------------------------------------------------------------------------------------------------
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 == "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 == "QLab") {
V3D q1 = ipws1->getPeak(i).getQLabFrame();
V3D q2 = ipws2->getPeak(i).getQLabFrame();
// using s1 here as the diff
for (int i = 0; i < 3; ++i) {
s1 += (q1[i] - q2[i]) * (q1[i] - q2[i]);
}
s1 = std::sqrt(s1);
} else if (name == "QSample") {
V3D q1 = ipws1->getPeak(i).getQSampleFrame();
V3D q2 = ipws2->getPeak(i).getQSampleFrame();
// using s1 here as the diff
for (int i = 0; i < 3; ++i) {
s1 += (q1[i] - q2[i]) * (q1[i] - q2[i]);
}
}
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