Skip to content
Snippets Groups Projects
CompareWorkspaces.cpp 42 KiB
Newer Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#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/TableRow.h"
#include "MantidDataObjects/TableWorkspace.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidGeometry/Crystal/IPeak.h"

namespace Mantid {
namespace Algorithms {

using namespace Mantid::API;
using namespace Mantid::Kernel;
using namespace Mantid::DataObjects;
using namespace Mantid::Geometry;

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

//----------------------------------------------------------------------------------------------
/** Constructor
 */
CompareWorkspaces::CompareWorkspaces()
    : API::Algorithm(), m_Result(false), m_Prog(nullptr),
      m_ParallelComparison(true) {}

//----------------------------------------------------------------------------------------------
/** Destructor
 */
CompareWorkspaces::~CompareWorkspaces() {}

//----------------------------------------------------------------------------------------------
/// Algorithms name for identification. @see Algorithm::name
const std::string CompareWorkspaces::name() const {
  return "CompareWorkspaces";
}

/// Algorithm's version for identification. @see Algorithm::version
int CompareWorkspaces::version() const { return 1; }

/// Algorithm's category for identification. @see Algorithm::category
const std::string CompareWorkspaces::category() const {
  return "Utility\\Workspaces";
}

/// Algorithm's summary for use in the GUI and help. @see Algorithm::summary
const std::string CompareWorkspaces::summary() const {
  return "Compares two workspaces for equality. This algorithm is mainly "
         "intended for use by the Mantid development team as part of the "
         "testing process.";
}

//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
 */
void CompareWorkspaces::init() {
  declareProperty(
      new WorkspaceProperty<Workspace>("Workspace1", "", Direction::Input),
      "The name of the first input workspace.");
  declareProperty(
      new 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. ");
  declareProperty(
      "CheckSample", false,
      "Whether to check that the sample (e.g. logs)."); // Have this one false
                                                        // by default - the logs
                                                        // are brittle
  declareProperty(
      "ToleranceRelErr", false,
      "Treat tolerance as relative error rather then the absolute error.\n"
      "This is only applicable to Matrix workspaces.");
  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.");
  // Have this one false by default - it can be a lot of printing.

  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(
      new WorkspaceProperty<ITableWorkspace>("ErrorWorkspace", "compare_errors",
                                             Direction::Output),
      "TableWorkspace containing any errors that occured during execution");
}

//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
 */
void CompareWorkspaces::exec() {
  m_Result = true;
  m_Errors = WorkspaceFactory::Instance().createTable("TableWorkspace");
  m_Errors->addColumn("str", "Error Message");

  if (g_log.is(Logger::Priority::PRIO_DEBUG))
    m_ParallelComparison = false;

  this->doComparison();

  if (!m_Result) {
    handleError("The workspaces did not match");
  }

  setProperty("Result", m_Result);
  setProperty("ErrorWorkspace", m_Errors);
}

//----------------------------------------------------------------------------------------------
/**
 * Process two groups and ensure the Result string is set properly on the final
 * algorithm.
 *
 * @return A boolean true if execution was sucessful, false otherwise
 */
bool CompareWorkspaces::processGroups() {
  m_Result = true;
  m_Errors = WorkspaceFactory::Instance().createTable("TableWorkspace");
  m_Errors->addColumn("str", "Error Message");

  // Get workspaces
  Workspace_const_sptr w1 = getProperty("Workspace1");
  Workspace_const_sptr w2 = getProperty("Workspace2");

  // Attempt to cast to WorkspaceGroups (will be nullptr on failure)
  WorkspaceGroup_const_sptr ws1 =
      boost::dynamic_pointer_cast<const WorkspaceGroup>(w1);
  WorkspaceGroup_const_sptr ws2 =
      boost::dynamic_pointer_cast<const WorkspaceGroup>(w2);

  if (ws1 && ws2) { // Both are groups
    processGroups(ws1, ws2);
  } else if (!ws1 && !ws2) { // Neither are groups (shouldn't happen)
    m_Result = false;
    throw std::runtime_error("CompareWorkspaces::processGroups - Neither "
                             "input is a WorkspaceGroup. This is a logical "
                             "error in the code.");
  } else if (!ws1 || !ws2) {
    handleError("Type mismatch. One workspace is a group, the other is not.");
  }

  setProperty("Result", m_Result);
  setProperty("ErrorWorkspace", m_Errors);

  // Store output workspace in AnalysisDataService
  setExecuted(true);
  notificationCenter().postNotification(
      new FinishedNotification(this, this->isExecuted()));
  return true;
}

//----------------------------------------------------------------------------------------------
/**
 * @brief CompareWorkspaces::processGroups
 * @param groupOne
 * @param groupTwo
 */
void CompareWorkspaces::processGroups(
    boost::shared_ptr<const API::WorkspaceGroup> groupOne,
    boost::shared_ptr<const API::WorkspaceGroup> groupTwo) {

  // Check their sizes
  const size_t totalNum = static_cast<size_t>(groupOne->getNumberOfEntries());
  if (groupOne->getNumberOfEntries() != groupTwo->getNumberOfEntries()) {
    handleError("GroupWorkspaces size mismatch.");
    return;
  }

  // See if there are any other properties that require setting
  const std::vector<Property *> &allProps = this->getProperties();
  std::vector<Property *> nonDefaultProps;
Loading
Loading full blame...