/** 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];
    }
  }
}
Exemple #2
0
    /** 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];
        }

      }


    }