/** 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); }
/** 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); }