/** Initialize the algorithm's properties.
  */
 void UnaryOperationMD::init()
 {
   declareProperty(new WorkspaceProperty<IMDWorkspace>(inputPropName(),"",Direction::Input),
       "A MDEventWorkspace or MDHistoWorkspace on which to apply the operation.");
   declareProperty(new WorkspaceProperty<IMDWorkspace>(outputPropName(),"",Direction::Output),
       "Name of the output MDEventWorkspace or MDHistoWorkspace.");
   this->initExtraProperties();
 }
/** Initialize the algorithm's properties.
 */
void BinaryOperationMD::init() {
  declareProperty(new WorkspaceProperty<IMDWorkspace>(inputPropName1(), "",
                                                      Direction::Input),
                  "An MDEventWorkspace, MDHistoWorkspace or "
                  "WorkspaceSingleValue as the left-hand side of the "
                  "operation.");
  declareProperty(new WorkspaceProperty<IMDWorkspace>(inputPropName2(), "",
                                                      Direction::Input),
                  "An MDEventWorkspace, MDHistoWorkspace or "
                  "WorkspaceSingleValue as the right-hand side of the "
                  "operation.");
  declareProperty(new WorkspaceProperty<IMDWorkspace>(outputPropName(), "",
                                                      Direction::Output),
                  "Name of the output MDEventWorkspace or MDHistoWorkspace.");
  this->initExtraProperties();
}
/** Execute the algorithm.
 */
void BinaryOperationMD::exec() {
  // Get the properties
  m_lhs = getProperty(inputPropName1());
  m_rhs = getProperty(inputPropName2());
  m_out = getProperty(outputPropName());

  // Flip LHS and RHS if commutative and :
  //  1. A = B + A -> becomes -> A += B
  //  1. C = 1 + A -> becomes -> C = A + 1   (number is always on RHS if
  //  possible)
  if (this->commutative() &&
      ((m_out == m_rhs) ||
       boost::dynamic_pointer_cast<WorkspaceSingleValue>(m_lhs))) {
    // So we flip RHS/LHS
    Mantid::API::IMDWorkspace_sptr temp = m_lhs;
    m_lhs = m_rhs;
    m_rhs = temp;
  }

  // Do not compare conventions if one is single value
  if (!boost::dynamic_pointer_cast<WorkspaceSingleValue>(m_rhs)) {
    if (m_lhs->getConvention() != m_rhs->getConvention()) {
      throw std::runtime_error(
          "Workspaces have different conventions for Q. "
          "Use algorithm ChangeQConvention on one workspace. ");
    }
  }

  // Can't do A = 1 / B
  if (boost::dynamic_pointer_cast<MatrixWorkspace>(m_lhs))
    throw std::invalid_argument("BinaryOperationMD: can't have a "
                                "MatrixWorkspace (e.g. WorkspaceSingleValue) "
                                "as the LHS argument of " +
                                this->name() + ".");

  // Check the inputs. First cast to everything
  m_lhs_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_lhs);
  m_lhs_histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(m_lhs);
  m_lhs_scalar = boost::dynamic_pointer_cast<WorkspaceSingleValue>(m_lhs);
  m_rhs_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_rhs);
  m_rhs_histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(m_rhs);
  m_rhs_scalar = boost::dynamic_pointer_cast<WorkspaceSingleValue>(m_rhs);

  // MDEventWorkspaces only:
  // If you have to clone any WS, and the operation is commutative, and is NOT
  // in-place, then clone the one that is file-backed.
  if (this->commutative() && (m_lhs_event && m_rhs_event) && (m_out != m_lhs)) {
    if (m_rhs_event->isFileBacked() && !m_lhs_event->isFileBacked()) {
      // So we flip RHS/LHS
      Mantid::API::IMDWorkspace_sptr temp = m_lhs;
      m_lhs = m_rhs;
      m_rhs = temp;
      m_lhs_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_lhs);
      m_rhs_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_rhs);
    }
  }

  this->checkInputs();

  if (m_out == m_lhs) {
    // A = A * B. -> we will do A *= B
  } else {
    // C = A + B. -> So first we clone A (lhs) into C
    IAlgorithm_sptr clone =
        this->createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true);
    clone->setProperty("InputWorkspace", m_lhs);
    clone->executeAsChildAlg();
    m_out = clone->getProperty("OutputWorkspace");
  }

  // Okay, at this point we are ready to do, e.g.,
  //  "m_out /= m_rhs"
  if (!m_out)
    throw std::runtime_error("Error creating the output workspace");
  if (!m_rhs)
    throw std::runtime_error("No RHS workspace specified!");

  m_operand_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_rhs);
  m_operand_histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(m_rhs);
  m_operand_scalar = boost::dynamic_pointer_cast<WorkspaceSingleValue>(m_rhs);

  m_out_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_out);
  m_out_histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(m_out);

  if (m_out_event) {
    // Call the templated virtual function for this type of MDEventWorkspace
    this->execEvent();
  } else if (m_out_histo) {
    // MDHistoWorkspace as the output
    if (m_operand_histo) {
      if (m_out_histo->getNumDims() != m_operand_histo->getNumDims())
        throw std::invalid_argument(
            "Cannot perform " + this->name() +
            " on MDHistoWorkspace's with a different number of dimensions.");
      if (m_out_histo->getNPoints() != m_operand_histo->getNPoints())
        throw std::invalid_argument(
            "Cannot perform " + this->name() +
            " on MDHistoWorkspace's with a different number of points.");

      // Check that the dimensions span the same size, warn if they don't
      for (size_t d = 0; d < m_out_histo->getNumDims(); d++) {
        IMDDimension_const_sptr dimA = m_out_histo->getDimension(0);
        IMDDimension_const_sptr dimB = m_operand_histo->getDimension(0);
        if (dimA->getMinimum() != dimB->getMinimum() ||
            dimA->getMaximum() != dimB->getMaximum())
          g_log.warning() << "Dimension " << d << " (" << dimA->getName()
                          << ") has different extents in the two "
                             "MDHistoWorkspaces. The operation may not make "
                             "sense!" << std::endl;
      }
      this->execHistoHisto(m_out_histo, m_operand_histo);
    } else if (m_operand_scalar)
      this->execHistoScalar(m_out_histo, m_operand_scalar);
    else
      throw std::runtime_error(
          "Unexpected operand workspace type. Expected MDHistoWorkspace or "
          "WorkspaceSingleValue, got " +
          m_rhs->id());

    // When operating on MDHistoWorkspaces, add a simple flag
    // that will be checked in BinMD to avoid binning a modified workspace
    if (m_out_histo->getNumExperimentInfo() == 0) // Create a run if needed
      m_out_histo->addExperimentInfo(ExperimentInfo_sptr(new ExperimentInfo()));
    m_out_histo->getExperimentInfo(0)->mutableRun().addProperty(
        new PropertyWithValue<std::string>("mdhisto_was_modified", "1"), true);
  } else {
    throw std::runtime_error(
        "Unexpected output workspace type. Expected MDEventWorkspace or "
        "MDHistoWorkspace, got " +
        m_out->id());
  }

  // Give the output
  setProperty("OutputWorkspace", m_out);
}
Exemple #4
0
/** Execute the algorithm.
 */
void UnaryOperationMD::exec() {
  // Get the properties
  m_in = getProperty(inputPropName());
  m_out = getProperty(outputPropName());

  // For MatrixWorkspace's ...
  if (boost::dynamic_pointer_cast<MatrixWorkspace>(m_in)) {
    // Pass-through to the same function without "MD"
    std::string matrixAlg = this->name();
    matrixAlg = matrixAlg.substr(0, matrixAlg.size() - 2);
    IAlgorithm_sptr alg = this->createChildAlgorithm(matrixAlg);
    // Copy all properties from THIS to the non-MD version
    std::vector<Property *> props = this->getProperties();
    for (auto prop : props) {
      alg->setPropertyValue(prop->name(), prop->value());
    }
    alg->execute();
    // Copy the output too
    MatrixWorkspace_sptr outMW = alg->getProperty("OutputWorkspace");
    IMDWorkspace_sptr out = boost::dynamic_pointer_cast<IMDWorkspace>(outMW);
    setProperty("OutputWorkspace", out);
    return;
  }

  // Check for validity
  m_in_event = boost::dynamic_pointer_cast<IMDEventWorkspace>(m_in);
  m_in_histo = boost::dynamic_pointer_cast<MDHistoWorkspace>(m_in);
  this->checkInputs();

  if (m_out != m_in) {
    // B = f(A) -> So first we clone A (lhs) into B
    IAlgorithm_sptr clone =
        this->createChildAlgorithm("CloneMDWorkspace", 0.0, 0.5, true);
    clone->setProperty("InputWorkspace", m_in);
    clone->executeAsChildAlg();
    m_out = clone->getProperty("OutputWorkspace");
  }

  // Okay, at this point we are ready to do, e.g.,
  //  "log(m_out)"
  if (!m_out)
    throw std::runtime_error("Error creating the output workspace");

  IMDEventWorkspace_sptr m_out_event =
      boost::dynamic_pointer_cast<IMDEventWorkspace>(m_out);
  MDHistoWorkspace_sptr m_out_histo =
      boost::dynamic_pointer_cast<MDHistoWorkspace>(m_out);

  // Call the appropriate sub-function
  if (m_out_event)
    this->execEvent(m_out_event);
  else if (m_out_histo)
    this->execHisto(m_out_histo);
  else {
    throw std::runtime_error(
        "Unexpected output workspace type. Expected MDEventWorkspace or "
        "MDHistoWorkspace, got " +
        m_out->id());
  }

  // Give the output
  setProperty("OutputWorkspace", m_out);
}