/** the method builds the MD ws description from existing matrix workspace and the requested transformation parameters. *@param pWS -- input matrix workspace to be converted into MD workspace *@param QMode -- momentum conversion mode. Any mode supported by Q conversion factory. Class just carries up the name of Q-mode, * to the place where factory call to the solver is made , so no code modification is needed when new modes are added * to the factory *@param dEMode -- energy analysis mode (string representation). Should correspond to energy analysis modes, supported by selected Q-mode *@param dimPropertyNames -- the vector of names for additional ws properties, which will be used as dimensions. */ void MDWSDescription::buildFromMatrixWS( const API::MatrixWorkspace_sptr &pWS, const std::string &QMode, const std::string dEMode, const std::vector<std::string> &dimPropertyNames) { m_InWS = pWS; // fill additional dimensions values, defined by workspace properties; this->fillAddProperties(m_InWS, dimPropertyNames, m_AddCoord); this->AlgID = QMode; // check and get energy conversion mode; m_Emode = Kernel::DeltaEMode::fromString(dEMode); // get raw pointer to Q-transformation (do not delete this pointer, its held // by MDTransfFactory!) MDTransfInterface *pQtransf = MDTransfFactory::Instance().create(QMode).get(); // get number of dimensions this Q transformation generates from the // workspace. unsigned int nMatrixDim = pQtransf->getNMatrixDimensions(m_Emode, m_InWS); // number of MD ws dimensions is the sum of n-matrix dimensions and dimensions // coming from additional coordinates m_NDims = nMatrixDim + static_cast<unsigned int>(m_AddCoord.size()); this->resizeDimDescriptions(m_NDims); // check if all MD dimensions descriptors are set properly if (m_NDims != m_DimNames.size() || m_NDims != m_DimMin.size()) { if (m_buildingNewWorkspace) { throw(std::invalid_argument(" dimension limits vectors and dimension " "description vectors inconsistent as have " "different length")); } else { throw(std::invalid_argument( " dimension limits vectors and dimension description vectors " "inconsistent as have different length\n" " Are you trying to add to existing workspace with convertToMD, " "which generates workspace with different number of dimensions?")); } } //*********** fill in dimension id-s, dimension units and dimension names // get default dim ID-s. TODO: it should be possibility to override it later; std::vector<std::string> MatrDimID = pQtransf->getDefaultDimID(m_Emode, m_InWS); std::vector<std::string> MatrUnitID = pQtransf->outputUnitID(m_Emode, m_InWS); for (unsigned int i = 0; i < m_NDims; i++) { if (i < nMatrixDim) { m_DimIDs[i] = MatrDimID[i]; m_DimNames[i] = MatrDimID[i]; m_DimUnits[i] = MatrUnitID[i]; } else { m_DimIDs[i] = dimPropertyNames[i - nMatrixDim]; m_DimNames[i] = dimPropertyNames[i - nMatrixDim]; m_DimUnits[i] = dimPropertyNames[i - nMatrixDim]; } } }
/** Method takes min-max values from algorithm parameters if they are present or calculates default min-max values if these values * were not supplied to the method or the supplied value is incorrect. * *@param inWS -- the shared pointer to the source workspace *@param QMode -- the string which defines algorithms Q-conversion mode *@param dEMode -- the string describes the algorithms energy conversion mode *@param QFrame -- in Q3D case this describes target coordinate system and is ignored in any other caste *@param ConvertTo -- The parameter describing Q-scaling transformations *@param otherDim -- the vector of other dimension names (if any) * Input-output values: *@param minVal -- the vector with min values for the algorithm *@param maxVal -- the vector with max values for the algorithm * * */ void ConvertToMD::findMinMax(const Mantid::API::MatrixWorkspace_sptr &inWS,const std::string &QMode, const std::string &dEMode, const std::string &QFrame,const std::string &ConvertTo,const std::vector<std::string> &otherDim, std::vector<double> &minVal,std::vector<double> &maxVal) { // get raw pointer to Q-transformation (do not delete this pointer, it hold by MDTransfFatctory!) MDTransfInterface* pQtransf = MDTransfFactory::Instance().create(QMode).get(); // get number of dimensions this Q transformation generates from the workspace. auto iEmode = Kernel::DeltaEMode().fromString(dEMode); // get total number of dimensions the workspace would have. unsigned int nMatrixDim = pQtransf->getNMatrixDimensions(iEmode,inWS); // total number of dimensions size_t nDim =nMatrixDim+otherDim.size(); // probably already have well defined min-max values, so no point of pre-calculating them bool wellDefined(true); if((nDim == minVal.size()) && (minVal.size()==maxVal.size())) { // are they indeed well defined? for(size_t i=0;i<minVal.size();i++) { if(minVal[i]>=maxVal[i]) // no it is ill defined { g_log.information()<<" Min Value: "<<minVal[i]<<" for dimension N: "<<i<<" equal or exceeds max value:"<<maxVal[i]<<std::endl; wellDefined = false; break; } } if (wellDefined)return; } // we need to identify min-max values by themselves Mantid::API::Algorithm_sptr childAlg = createChildAlgorithm("ConvertToMDMinMaxLocal"); if(!childAlg)throw(std::runtime_error("Can not create child ChildAlgorithm to found min/max values")); childAlg->setPropertyValue("InputWorkspace", inWS->getName()); childAlg->setPropertyValue("QDimensions",QMode); childAlg->setPropertyValue("dEAnalysisMode",dEMode); childAlg->setPropertyValue("Q3DFrames",QFrame); childAlg->setProperty("OtherDimensions",otherDim); childAlg->setProperty("QConversionScales",ConvertTo); childAlg->setProperty("PreprocDetectorsWS",std::string(getProperty("PreprocDetectorsWS"))); childAlg->execute(); if(!childAlg->isExecuted())throw(std::runtime_error("Can not properly execute child algorithm to find min/max workspace values")); minVal = childAlg->getProperty("MinValues"); maxVal = childAlg->getProperty("MaxValues"); // if some min-max values for dimensions produce ws with 0 width in this direction, change it to have some width; for(unsigned int i=0;i<nDim;i++) { if(minVal[i]>=maxVal[i]) { g_log.debug()<<"identified min-max values for dimension N: "<<i<<" are equal. Modifying min-max value to produce dimension with 0.2*dimValue width\n"; if(minVal[i]>0) { minVal[i]*=0.9; maxVal[i]*=1.1; } else if(minVal[i]==0) { minVal[i]=-0.1; maxVal[i]=0.1; } else { minVal[i]*=1.1; maxVal[i]*=0.9; } } else // expand min-max values a bit to avoid cutting data on the edges { if (std::fabs(minVal[i])>FLT_EPSILON) minVal[i]*=(1+2*FLT_EPSILON); else minVal[i]-=2*FLT_EPSILON; if (std::fabs(minVal[i])>FLT_EPSILON) maxVal[i]*=(1+2*FLT_EPSILON); else minVal[i]+=2*FLT_EPSILON; } } if(!wellDefined) return; // if only min or only max limits are defined and are well defined workspace, the algorithm will use these limits std::vector<double> minAlgValues = this->getProperty("MinValues"); std::vector<double> maxAlgValues = this->getProperty("MaxValues"); bool allMinDefined = (minAlgValues.size()==nDim); bool allMaxDefined = (maxAlgValues.size()==nDim); if(allMinDefined || allMaxDefined) { for(size_t i=0;i<nDim;i++) { if (allMinDefined) minVal[i] = minAlgValues[i]; if (allMaxDefined) maxVal[i] = maxAlgValues[i]; } } }