Skip to content
Snippets Groups Projects
CreateEPP.cpp 6.2 KiB
Newer Older
#include "MantidAlgorithms/CreateEPP.h"

#include "MantidAPI/ITableWorkspace.h"
#include "MantidAPI/InstrumentValidator.h"
#include "MantidAPI/Run.h"
#include "MantidAPI/SpectrumInfo.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidAPI/WorkspaceUnitValidator.h"
#include "MantidKernel/BoundedValidator.h"
#include "MantidKernel/CompositeValidator.h"
#include "MantidKernel/UnitConversion.h"

namespace Mantid {
namespace Algorithms {

using Mantid::API::WorkspaceProperty;
using Mantid::Kernel::Direction;
/** A private namespace holding the property names.
 */
namespace PropertyNames {
const static std::string INPUT_WORKSPACE("InputWorkspace");
const static std::string OUTPUT_WORKSPACE("OutputWorkspace");
const static std::string SIGMA("Sigma");
} // namespace PropertyNames

/** A private namespace holding the column names of the EPP table.
 */
namespace ColumnNames {
const static std::string WS_INDEX("WorkspaceIndex");
const static std::string PEAK_CENTRE("PeakCentre");
const static std::string PEAK_CENTRE_ERR("PeakCentreError");
const static std::string SIGMA("Sigma");
const static std::string SIGMA_ERR("SigmaError");
const static std::string HEIGHT("Height");
const static std::string HEIGHT_ERR("HeightError");
const static std::string CHI_SQUARED("chiSq");
const static std::string STATUS("FitStatus");
} // namespace ColumnNames
/** Add standard EPP table columns to the input workspace.
 *
 * @param ws The TableWorkspace to add the columns to.
 */
void addEPPColumns(API::ITableWorkspace_sptr ws) {
  ws->addColumn("int", ColumnNames::WS_INDEX);
  ws->addColumn("double", ColumnNames::PEAK_CENTRE);
  ws->addColumn("double", ColumnNames::PEAK_CENTRE_ERR);
  ws->addColumn("double", ColumnNames::SIGMA);
  ws->addColumn("double", ColumnNames::SIGMA_ERR);
  ws->addColumn("double", ColumnNames::HEIGHT);
  ws->addColumn("double", ColumnNames::HEIGHT_ERR);
  ws->addColumn("double", ColumnNames::CHI_SQUARED);
  ws->addColumn("str", ColumnNames::STATUS);
}

} // anonymous namespace

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

//----------------------------------------------------------------------------------------------

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

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

/// Algorithm's category for identification. @see Algorithm::category
Antti Soininen's avatar
Antti Soininen committed
const std::string CreateEPP::category() const { return "Utility"; }

/// Algorithm's summary for use in the GUI and help. @see Algorithm::summary
const std::string CreateEPP::summary() const {
Antti Soininen's avatar
Antti Soininen committed
  return "Creates a nominal EPP table compatible with what is returned by the "
         "FindEPP algorithm.";
}

//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
 */
void CreateEPP::init() {
  auto inputWSValidator = boost::make_shared<Kernel::CompositeValidator>();
  inputWSValidator->add(boost::make_shared<API::InstrumentValidator>());
  inputWSValidator->add(boost::make_shared<API::WorkspaceUnitValidator>("TOF"));
Antti Soininen's avatar
Antti Soininen committed
  declareProperty(Kernel::make_unique<WorkspaceProperty<API::MatrixWorkspace>>(
                      "InputWorkspace", "", Direction::Input, inputWSValidator),
                  "An input workspace.");
  declareProperty(Kernel::make_unique<WorkspaceProperty<API::ITableWorkspace>>(
                      "OutputWorkspace", "", Direction::Output),
                  "The calculated output EPP table.");
  auto mustBePositive = boost::make_shared<Kernel::BoundedValidator<double>>();
  mustBePositive->setLower(0);
Antti Soininen's avatar
Antti Soininen committed
  declareProperty(PropertyNames::SIGMA, 0.0, mustBePositive,
                  "The value to fill the Sigma column with.");
}

//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
 */
void CreateEPP::exec() {
Antti Soininen's avatar
Antti Soininen committed
  API::MatrixWorkspace_sptr inputWS =
      getProperty(PropertyNames::INPUT_WORKSPACE);
  const auto &spectrumInfo = inputWS->spectrumInfo();
Antti Soininen's avatar
Antti Soininen committed
  API::ITableWorkspace_sptr outputWS =
      API::WorkspaceFactory::Instance().createTable("TableWorkspace");
  addEPPColumns(outputWS);
  const double sigma = getProperty(PropertyNames::SIGMA);
  const size_t spectraCount = spectrumInfo.size();
  outputWS->setRowCount(spectraCount);
  const auto l1 = spectrumInfo.l1();
  const double EFixed = inputWS->run().getPropertyAsSingleValue("Ei");
  for (size_t i = 0; i < spectraCount; ++i) {
    const auto l2 = spectrumInfo.l2(i);
Antti Soininen's avatar
Antti Soininen committed
    const auto elasticTOF = Kernel::UnitConversion::run(
        "Energy", "TOF", EFixed, l1, l2, 0, Kernel::DeltaEMode::Direct, EFixed);
    outputWS->getRef<int>(ColumnNames::WS_INDEX, i) = static_cast<int>(i);
    outputWS->getRef<double>(ColumnNames::PEAK_CENTRE, i) = elasticTOF;
    outputWS->getRef<double>(ColumnNames::PEAK_CENTRE_ERR, i) = 0;
    outputWS->getRef<double>(ColumnNames::SIGMA, i) = sigma;
    outputWS->getRef<double>(ColumnNames::SIGMA_ERR, i) = 0;
    double height = 0;
    try {
      const auto elasticIndex = inputWS->binIndexOf(elasticTOF, i);
      height = inputWS->y(i)[elasticIndex];
    } catch (std::out_of_range &) {
      std::ostringstream sout;
Antti Soininen's avatar
Antti Soininen committed
      sout << "EPP out of TOF range for workspace index " << i
           << ". Peak height set to zero.";
      g_log.warning() << sout.str();
    }
    outputWS->getRef<double>(ColumnNames::HEIGHT, i) = height;
    outputWS->getRef<double>(ColumnNames::CHI_SQUARED, i) = 1;
    outputWS->getRef<std::string>(ColumnNames::STATUS, i) = "success";
  }
  setProperty(PropertyNames::OUTPUT_WORKSPACE, outputWS);
}

//----------------------------------------------------------------------------------------------
/** Validate the algorithm's properties.
 *
 * @return A map of porperty names and their issues.
 */
std::map<std::string, std::string> CreateEPP::validateInputs(void) {
  std::map<std::string, std::string> issues;
Antti Soininen's avatar
Antti Soininen committed
  API::MatrixWorkspace_sptr inputWS =
      getProperty(PropertyNames::INPUT_WORKSPACE);
  if (!inputWS->run().hasProperty("Ei")) {
Antti Soininen's avatar
Antti Soininen committed
    issues[PropertyNames::INPUT_WORKSPACE] =
        "Workspace is missing the 'Ei' sample log.";
  }
  return issues;
}

} // namespace Algorithms
} // namespace Mantid