Skip to content
Snippets Groups Projects
CompareWorkspaces.cpp 45.4 KiB
Newer Older
// Mantid Repository : https://github.com/mantidproject/mantid
//
// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
//     NScD Oak Ridge National Laboratory, European Spallation Source
//     & Institut Laue - Langevin
// SPDX - License - Identifier: GPL - 3.0 +
#include "MantidAlgorithms/CompareWorkspaces.h"

#include "MantidAPI/IMDEventWorkspace.h"
#include "MantidAPI/IMDHistoWorkspace.h"
#include "MantidAPI/IMDWorkspace.h"
#include "MantidAPI/IPeaksWorkspace.h"
#include "MantidAPI/NumericAxis.h"
#include "MantidAPI/Run.h"
#include "MantidAPI/Sample.h"
#include "MantidAPI/TableRow.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidDataObjects/EventWorkspace.h"
Samuel Jackson's avatar
Samuel Jackson committed
#include "MantidDataObjects/PeaksWorkspace.h"
#include "MantidDataObjects/TableWorkspace.h"
#include "MantidGeometry/Crystal/IPeak.h"
Samuel Jackson's avatar
Samuel Jackson committed
#include "MantidGeometry/Instrument/DetectorInfo.h"
#include "MantidKernel/Unit.h"
#include "MantidParallel/Communicator.h"

namespace Mantid {
namespace Algorithms {

using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace Mantid::DataObjects;
using namespace Mantid::Geometry;
using Types::Event::TofEvent;

// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(CompareWorkspaces)

namespace {

template <class ET> const std::vector<ET> &getEventVector(const EventList &el);

template <>
const std::vector<Types::Event::TofEvent> &getEventVector(const EventList &el) {
  return el.getEvents();
}

template <>
const std::vector<DataObjects::WeightedEvent> &
getEventVector(const EventList &el) {
  return el.getWeightedEvents();
}

template <>
const std::vector<DataObjects::WeightedEventNoTime> &
getEventVector(const EventList &el) {
  return el.getWeightedEventsNoTime();
}

template <class ET>
int compareEventLists(Kernel::Logger &logger, 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) {

  // Initialize
  numdiffpulse = 0;
  numdifftof = 0;
  numdiffboth = 0;
  numdiffweight = 0;

  // Compare event by event including all events
  const auto &events1 = getEventVector<ET>(el1);
  const auto &events2 = getEventVector<ET>(el2);

  int returnint = 0;
  size_t numevents = events1.size();
  for (size_t i = 0; i < numevents; ++i) {
    // Compare 2 individual events
    const auto &e1 = events1[i];
    const auto &e2 = events2[i];

    bool diffpulse = false;
    bool difftof = false;
    bool diffweight = false;
    if (std::abs(e1.pulseTime().totalNanoseconds() -
                 e2.pulseTime().totalNanoseconds()) > tolPulse) {
      diffpulse = true;
      ++numdiffpulse;
    }
    if (fabs(e1.tof() - e2.tof()) > tolTof) {
      difftof = true;
      ++numdifftof;
    }
    if (diffpulse && difftof)
      ++numdiffboth;
    if (fabs(e1.weight() - e2.weight()) > tolWeight) {
      diffweight = true;
      ++numdiffweight;
    }

    bool same = (!diffpulse) && (!difftof) && (!diffweight);
    if (!same) {
      returnint += 1;
      if (printdetails) {
        std::stringstream outss;
        outss << "Spectrum ? Event " << i << ": ";
        if (diffpulse)
          outss << "Diff-Pulse: " << e1.pulseTime() << " vs. " << e2.pulseTime()
                << "; ";
        if (difftof)
          outss << "Diff-TOF: " << e1.tof() << " vs. " << e2.tof() << ";";
        if (diffweight)
          outss << "Diff-Weight: " << e1.weight() << " vs. " << e2.weight()
                << ";";

        logger.information(outss.str());
      }
    }
  } // End of loop on all events

  // Anything that gets this far is equal within tolerances
  return returnint;
}
} // namespace

/** Initialize the algorithm's properties.
 */
void CompareWorkspaces::init() {
Sam Jenkins's avatar
Sam Jenkins committed
  declareProperty(std::make_unique<WorkspaceProperty<Workspace>>(
                      "Workspace1", "", Direction::Input),
                  "The name of the first input workspace.");
Sam Jenkins's avatar
Sam Jenkins committed
  declareProperty(std::make_unique<WorkspaceProperty<Workspace>>(
                      "Workspace2", "", Direction::Input),
                  "The name of the second input workspace.");

  declareProperty(
      "Tolerance", 0.0,
      "The maximum amount by which values may differ between the workspaces.");

  declareProperty("CheckType", true,
                  "Whether to check that the data types "
                  "(Workspace2D vs EventWorkspace) match.");
  declareProperty("CheckAxes", true, "Whether to check that the axes match.");
  declareProperty("CheckSpectraMap", true,
                  "Whether to check that the spectra-detector maps match. ");
  declareProperty("CheckInstrument", true,
                  "Whether to check that the instruments match. ");
  declareProperty("CheckMasking", true,
                  "Whether to check that the bin masking matches. ");

  // Have this one false by default - the logs are brittle
  declareProperty("CheckSample", false,
                  "Whether to check that the sample (e.g. logs).");

  declareProperty(
      "ToleranceRelErr", false,
      "Treat tolerance as relative error rather then the absolute error.\n"
      "This is only applicable to Matrix workspaces.");

  // Have this one false by default - it can be a lot of printing.
  declareProperty("CheckAllData", false,
                  "Usually checking data ends when first mismatch occurs. This "
                  "forces algorithm to check all data and print mismatch to "
                  "the debug log.\n"
                  "Very often such logs are huge so making it true should be "
                  "the last option.");

  declareProperty("NumberMismatchedSpectraToPrint", 1,
                  "Number of mismatched spectra from lowest to be listed. ");

  declareProperty("DetailedPrintIndex", EMPTY_INT(),
                  "Mismatched spectra that will be printed out in details. ");

  declareProperty("Result", false, Direction::Output);
  declareProperty(
      std::make_unique<WorkspaceProperty<ITableWorkspace>>(
          "Messages", "compare_msgs", Direction::Output),
      "TableWorkspace containing messages about any mismatches detected");
  m_messages = boost::make_shared<TableWorkspace>();
  m_messages->addColumn("str", "Message");
  m_messages->addColumn("str", "Workspace 1");
  m_messages->addColumn("str", "Workspace 2");
}

/** Execute the algorithm.
 */
void CompareWorkspaces::exec() {
  m_result = true;
  m_messages->setRowCount(0); // Clear table

  if (g_log.is(Logger::Priority::PRIO_DEBUG))
    m_parallelComparison = false;
  if (!m_result) {
    std::string message = m_messages->cell<std::string>(0, 0);
    g_log.notice() << "The workspaces did not match: " << message << '\n';
Loading
Loading full blame...