Skip to content
Snippets Groups Projects
CreateLogTimeCorrection.cpp 5.84 KiB
Newer Older
#include "MantidAlgorithms/CreateLogTimeCorrection.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/InstrumentValidator.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidAPI/Run.h"
#include "MantidAPI/TableRow.h"
#include "MantidAPI/WorkspaceProperty.h"
#include "MantidGeometry/Instrument/DetectorInfo.h"
#include <fstream>

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

using namespace std;

namespace Mantid {
namespace Algorithms {

DECLARE_ALGORITHM(CreateLogTimeCorrection)

//----------------------------------------------------------------------------------------------
/** Declare properties
 */
void CreateLogTimeCorrection::init() {
  declareProperty(Kernel::make_unique<WorkspaceProperty<MatrixWorkspace>>(
                      "InputWorkspace", "", Direction::Input,
                      boost::make_shared<InstrumentValidator>()),
                  "Name of the input workspace to generate log correct from.");

  declareProperty(Kernel::make_unique<WorkspaceProperty<TableWorkspace>>(
                      "OutputWorkspace", "", Direction::Output),
                  "Name of the output workspace containing the corrections.");

  declareProperty(Kernel::make_unique<FileProperty>("OutputFilename", "",
                                                    FileProperty::OptionalSave),
                  "Name of the output time correction file.");
}

//----------------------------------------------------------------------------------------------
/** Main execution body
  */
void CreateLogTimeCorrection::exec() {
  // 1. Process input
  MatrixWorkspace_sptr dataWS = getProperty("InputWorkspace");

  //   Check whether the output workspace name is same as input
  string outwsname = getPropertyValue("OutputWorkspace");
  if (outwsname == dataWS->getName()) {
    stringstream errmsg;
    errmsg << "It is not allowed to use the same name by both input matrix "
              "workspace and output table workspace.";
    g_log.error(errmsg.str());
    throw runtime_error(errmsg.str());
  const auto &detectorInfo = dataWS->detectorInfo();

  // 2. Log some information
  logGeometryInformation(detectorInfo);
  // 3. Calculate log time correction
  auto corrections = calculateCorrections(detectorInfo);
  // 4. Output
  TableWorkspace_sptr outWS =
      generateCorrectionTable(detectorInfo, corrections);
  setProperty("OutputWorkspace", outWS);
  string filename = getProperty("OutputFilename");
  g_log.information() << "Output file name is " << filename << ".\n";
    writeCorrectionToFile(filename, detectorInfo, corrections);
  }
}

//----------------------------------------------------------------------------------------------
/** Get instrument geometry setup including L2 for each detector and L1
  */
void CreateLogTimeCorrection::logGeometryInformation(
    const Geometry::DetectorInfo &detectorInfo) const {
  g_log.information() << "Sample position = " << detectorInfo.samplePosition()
                      << "Source position = " << detectorInfo.sourcePosition()
                      << ", L1 = " << detectorInfo.l1() << "; "
                      << "Number of detector/pixels = " << detectorInfo.size()
                      << ".\n";
}

//----------------------------------------------------------------------------------------------
/** Calculate the log time correction for each pixel, i.e., correcton from event
 * time at detector
  * to time at sample
  */
std::vector<double> CreateLogTimeCorrection::calculateCorrections(
    const Geometry::DetectorInfo &detectorInfo) const {

  std::vector<double> corrections(detectorInfo.size());
  const double l1 = detectorInfo.l1();
  for (size_t detectorIndex = 0; detectorIndex < detectorInfo.size();
       ++detectorIndex) {

    double corrfactor = l1 / (l1 + detectorInfo.l2(detectorIndex));
    corrections[detectorIndex] = corrfactor;
  return corrections;
}

//----------------------------------------------------------------------------------------------
/** Write L2 map and correction map to a TableWorkspace
  */
TableWorkspace_sptr CreateLogTimeCorrection::generateCorrectionTable(
    const Geometry::DetectorInfo &detectorInfo,
    const std::vector<double> &corrections) const {
  auto tablews = boost::make_shared<TableWorkspace>();
  tablews->addColumn("int", "DetectorID");
  tablews->addColumn("double", "Correction");
  tablews->addColumn("double", "L2");
  const auto &detectorIds = detectorInfo.detectorIDs();
  for (size_t detectorIndex = 0; detectorIndex < detectorInfo.size();
       ++detectorIndex) {
    if (!detectorInfo.isMonitor(detectorIndex)) {
      const detid_t detid = detectorIds[detectorIndex];
      const double correction = corrections[detectorIndex];
      const double l2 = detectorInfo.l2(detectorIndex);
      TableRow newrow = tablews->appendRow();
      newrow << detid << correction << l2;
    }
  return tablews;
}
//----------------------------------------------------------------------------------------------
/** Write correction map to a text file
  */
void CreateLogTimeCorrection::writeCorrectionToFile(
    const string filename, const Geometry::DetectorInfo &detectorInfo,
    const std::vector<double> &corrections) const {
  ofstream ofile;
  ofile.open(filename.c_str());
  if (ofile.is_open()) {

    const auto &detectorIds = detectorInfo.detectorIDs();
    for (size_t detectorIndex = 0; detectorIndex < corrections.size();
         ++detectorIndex) {
      if (!detectorInfo.isMonitor(detectorIndex)) {
        ofile << detectorIds[detectorIndex] << "\t" << setw(20)
              << setprecision(5) << corrections[detectorIndex] << "\n";
      }
    ofile.close();
  } else {
    g_log.error() << "Unable to open file " << filename << " to write!\n";
} // namespace Algorithms
} // namespace Mantid