Skip to content

Commit

Permalink
refs #4572 This fixes it
Browse files Browse the repository at this point in the history
Though ConvertToMDEvents was copying data to target ws before, some processed ws which did not have detector information attached to it were empty as no spectra-det map was present (equal to empty spectra-det map)

Solved by generating fake 1:1 spectra detector map to fake detectors (which were and are not used)

Couple more tests are needed to validate the code
  • Loading branch information
abuts committed Jan 22, 2012
1 parent d0c178e commit 6ea40c2
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ namespace MDAlgorithms
void getAddDimensionNames(API::MatrixWorkspace_const_sptr inMatrixWS,Strings &add_dim_names,Strings &add_dim_units)const;
/** function parses arguments entered by user, and identifies, which subalgorithm should be deployed on WS as function of the input artuments and the WS format */
std::string identifyMatrixAlg(API::MatrixWorkspace_const_sptr inMatrixWS,const std::string &Q_mode_req, const std::string &dE_mode_req,
Strings &out_dim_IDs,Strings &out_dim_units);
Strings &out_dim_IDs,Strings &out_dim_units, bool &is_detector_information_lost);
//>---> Parts of the identifyMatrixAlg, separated for unit testing:
// identify Q - mode
std::string parseQMode(const std::string &Q_mode_req,const Strings &ws_dim_names,const Strings &ws_dim_units,Strings &out_dim_names,Strings &out_dim_units, int &nQdims);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,23 @@ struct PreprocessedDetectors{
std::vector<size_t> detIDMap; //< stores spectra index which corresponds to a valid detector index;
std::vector<size_t> spec2detMap; //< stores detector index which corresponds to the workspace index;
//
bool is_defined(const API::MatrixWorkspace_const_sptr &inputWS)const;
bool is_defined(size_t new_size)const{return det_dir.size()==new_size;}
bool isDefined(const API::MatrixWorkspace_const_sptr &inputWS)const;
bool isDefined(size_t new_size)const{return det_dir.size()==new_size;}
size_t nDetectors()const{return TwoTheta.size();}
std::vector<double>const & getL2()const{return L2;}
std::vector<double>const & getTwoTheta()const{return TwoTheta;}
std::vector<size_t>const & getDetIDMap()const{return detIDMap;}
std::vector<size_t>const & getSpec2DetMap()const{return spec2detMap;}
std::vector<Kernel::V3D>const & getDetDir()const{return det_dir;}
// function allocates the class detectors memory
void allocDetMemory(size_t nSpectra);
};

/** helper function, does preliminary calculations of the detectors positions to convert results into k-dE space ;
and places the resutls into static cash to be used in subsequent calls to this algorithm */
void DLLExport processDetectorsPositions(const API::MatrixWorkspace_sptr inputWS,PreprocessedDetectors &det,Kernel::Logger& convert_log,API::Progress *pProg);
/** function builds fake cpectra-detector map and all other detectors position for the case when detector information has been lost */
void DLLExport buildFakeDetectorsPositions(const API::MatrixWorkspace_sptr inputWS,PreprocessedDetectors &det);
} // end MDAlgorithms
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ namespace MDAlgorithms
Histohram, // typical for Matrix workspace -- deploys central average 0.5(X[i]+X[i+1]); other types of averaging are possible if needed
Centered // typical for events
};


class DLLExport IConvertToMDEventsMethods
{
Expand All @@ -89,7 +89,7 @@ namespace MDAlgorithms
// constructor;
IConvertToMDEventsMethods();

///method which initates all main class variables (constructor in fact)
///method which initates all main class variables
virtual size_t setUPConversion(Mantid::API::MatrixWorkspace_sptr pWS2D, const PreprocessedDetectors &detLoc,const MDEvents::MDWSDescription &WSD, boost::shared_ptr<MDEvents::MDEventWSWrapper> inWSWrapper);
/// method which starts the conversion procedure
virtual void runConversion(API::Progress *)=0;
Expand Down
47 changes: 35 additions & 12 deletions Code/Mantid/Framework/MDAlgorithms/src/ConvertToMDEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ ConvertToMDEvents::init()
declareProperty("QDimensions",Q_modes[NoQ],new ListValidator(Q_modes),
"You can to transfer source workspace dimensions into target workspace directly """" (NoQ), transform into mod(Q) (1 dimension) or QhQkQl (3 dimensions) in Q space",Direction::InOut);
// this switch allows to make units expressed in HKL, hkl is currently not supported by units conversion so the resulting workspace can not be subject to unit conversion
declareProperty(new PropertyWithValue<bool>("QinHKL", false, Direction::Input),
declareProperty(new PropertyWithValue<bool>("QinHKL", true, Direction::Input),
" Setting this property to true will normalize three momentums obtained in QhQkQl mode by reciprocal lattice vectors 2pi/a,2pi/b and 2pi/c\n"
" ignored in mod|Q| and NoQ modes and if reciprocal lattice is not defined");
/// this variable describes implemented modes for energy transfer analysis
Expand All @@ -222,9 +222,10 @@ ConvertToMDEvents::init()
declareProperty(new ArrayProperty<double>("MinValues"),
"It has to be N comma separated values, where N is defined as: \n"
"a) 1+N_OtherDimensions if the first dimension (QDimensions property) is equal to |Q| or \n"
"b) 3+N_OtherDimensions if the first (3) dimensions (QDimensions property) equal QxQyQz or \n"
"b) 3+N_OtherDimensions if the first (3) dimensions (QDimensions property) equal QhQkQl or \n"
"c) (1 or 2)+N_OtherDimesnions if QDimesnins property is emtpty. \n"
" In case c) the target workspace dimensions are defined by the [[units]] of the input workspace axis.\n\n"
" In case b), the target dimensions for QhQkQl are either momentums if QinHKL is false or are momentums divided by correspondent lattice parameters if QinHKL is true\n"
" This property contains minimal values for all dimensions.\n"
" Momentum values expected to be in [A^-1] and energy transfer (if any) expressed in [meV]\n"
" All other values are in the [[units]] they are expressed in their log files\n"
Expand Down Expand Up @@ -310,7 +311,7 @@ void ConvertToMDEvents::exec()
std::string dE_mod_req = getProperty("dEAnalysisMode");
//c) other dim property;
std::vector<std::string> other_dim_names = getProperty("OtherDimensions");
//d) part of the procedure, specifying the target dimensions units. Currently only Q3D target units can be converted to hkl
//d) part of the procedure, specifying the target dimensions units. Currently only Q3D target units be converted to hkl
bool convert_to_hkl = getProperty("QinHKL");

// Identify the algorithm to deploy and identify/set the (multi)dimension's names to use
Expand All @@ -330,12 +331,21 @@ void ConvertToMDEvents::exec()
throw(Kernel::Exception::NotImplementedError("Adding to existing MD workspace not Yet Implemented"));
}

bool reuse_preprocecced_detectors = getProperty("UsePreprocessedDetectors");
if(!(reuse_preprocecced_detectors&&det_loc.is_defined(inWS2D))){

if(TWS.detInfoLost){ // in NoQ mode one can not have DetPositions any more. Neither this information is needed for anything except data conversion interface.
buildFakeDetectorsPositions(inWS2D,det_loc);
}else{
bool reuse_preprocecced_detectors = getProperty("UsePreprocessedDetectors");
if(!(reuse_preprocecced_detectors&&det_loc.isDefined(inWS2D))){
// amount of work:
const size_t nHist = inWS2D->getNumberHistograms();
pProg = std::auto_ptr<API::Progress >(new API::Progress(this,0.0,1.0,nHist));
processDetectorsPositions(inWS2D,det_loc,convert_log,pProg.get());
if(det_loc.det_id.empty()){
g_log.error()<<" no valid detectors identified associated with spectra, nothing to do\n";
throw(std::invalid_argument("no valid detectors indentified associated with any spectra"));
}
}
}

if(create_new_ws)
Expand All @@ -355,7 +365,7 @@ void ConvertToMDEvents::exec()
// Do we split more due to MinRecursionDepth?
int minDepth = this->getProperty("MinRecursionDepth");
int maxDepth = this->getProperty("MaxRecursionDepth");
if (minDepth<maxDepth) throw std::invalid_argument("MinRecursionDepth must be >= MaxRecursionDepth and ");
if (minDepth>maxDepth) throw std::invalid_argument("MinRecursionDepth must be >= MaxRecursionDepth and ");
spws->setMinRecursionDepth(size_t(minDepth));
}

Expand Down Expand Up @@ -392,12 +402,13 @@ void ConvertToMDEvents::exec()
* @param inMatrixWS -- const pointer to const matrix workspace, which provides information about availible axis
* @param Q_mode_req -- what to do with Q-dimensions e.g. calculate either mod|Q| or Q3D;
* @param dE_mode_req -- desirable dE analysis mode (elastic, direct/indirect)
* @param out_dim_IDs -- the vector of strings, with each string identify the dimensions ID-s, derived from current workspace by the algorithm
* @param out_dim_units -- vector of units for target workspace, if inelastic, one of the dimension units have to be DeltaE
* @return out_dim_IDs -- the vector of strings, with each string identify the dimensions ID-s, derived from current workspace by the algorithm
* @return out_dim_units -- vector of units for target workspace, if inelastic, one of the dimension units have to be DeltaE
* @return is_det_info_lost -- if Y axis of matix workspace contains some meaningful info, the detector information is certainly lost.
*/
std::string
ConvertToMDEvents::identifyMatrixAlg(API::MatrixWorkspace_const_sptr inMatrixWS, const std::string &Q_mode_req, const std::string &dE_mode_req,
Strings &out_dim_IDs,Strings &out_dim_units)
Strings &out_dim_IDs,Strings &out_dim_units, bool &is_detector_information_lost)
{

// dimension names present in input workspace
Expand All @@ -417,11 +428,14 @@ ConvertToMDEvents::identifyMatrixAlg(API::MatrixWorkspace_const_sptr inMatrixWS,
ws_dim_units.push_back(Dim1Unit);
}
// get optional Y axis which can be used in NoQ-kind of algorithms
is_detector_information_lost= false;
API::NumericAxis *pYAxis = dynamic_cast<API::NumericAxis *>(inMatrixWS->getAxis(1));
if(pYAxis){
std::string Dim2Unit = pYAxis->unit()->unitID();
ws_dim_names.push_back(pYAxis->title());
ws_dim_units.push_back(Dim2Unit);
// if this is numeric axis, then the detector's information has been lost:
is_detector_information_lost=true;
}


Expand Down Expand Up @@ -548,7 +562,8 @@ ConvertToMDEvents::parseDEMode(const std::string &Q_MODE_ID,const std::string &d
*@param nQ_dims [out] -- number of Q or other dimensions. When converting into Q, it is 1 or 3 dimensions, if NoQ -- workspace dimensions are copied.
*/
std::string
ConvertToMDEvents::parseQMode(const std::string &Q_mode_req,const Strings &ws_dim_names,const Strings &ws_dim_units,Strings &out_dim_ID,Strings &out_dim_units, int &nQ_dims)
ConvertToMDEvents::parseQMode(const std::string &Q_mode_req,const Strings &ws_dim_names,const Strings &ws_dim_units,Strings &out_dim_ID,Strings &out_dim_units,
int &nQ_dims)
{
std::string Q_MODE_ID("Unknown");
if(is_member(Q_modes,Q_mode_req)<0){
Expand Down Expand Up @@ -635,9 +650,10 @@ ConvertToMDEvents::identifyTheAlg(API::MatrixWorkspace_const_sptr inWS,const std
Strings dim_IDs_requested,dim_units_requested;
Strings ws_dim_IDs,ws_dim_units;
std::string the_algID;
bool is_detector_info_lost;

// identify the matrix conversion part of subalgorithm as function of user input and workspace Matrix parameters (axis)
the_algID = identifyMatrixAlg(inWS, Q_mode_req, dE_mode_req,ws_dim_IDs,ws_dim_units);
the_algID = identifyMatrixAlg(inWS, Q_mode_req, dE_mode_req,ws_dim_IDs,ws_dim_units,is_detector_info_lost);
if(the_algID.find("Unknown")!=std::string::npos){
convert_log.error()<<" Input parameters indentify uncomplete algorithm ID: "<<the_algID<<std::endl;
throw(std::logic_error("can not parse input parameters propertly"));
Expand Down Expand Up @@ -673,7 +689,7 @@ ConvertToMDEvents::identifyTheAlg(API::MatrixWorkspace_const_sptr inWS,const std
convert_log.error()<<"Algorithm with ID:"<<the_algID<<" should produce at least 3 dimensions and it requested to provie just:"<<nDims<<" dims \n";
throw(std::logic_error("can not parse input parameters propertly"));
}
// we have currenlty instanciated only N input dimensions. See algorithm constructor to change that.
// we have can currenlty instanciate only N input dimensions. See the wsWrapper constructor to change that.
if(nDims>pWSWrapper->getMaxNDim()){
convert_log.error()<<"Can not currently deal with more then: "<<pWSWrapper->getMaxNDim()<< " dimesnions, but requested: "<<nDims<<std::endl;
throw(std::invalid_argument(" Too many dimensions requested "));
Expand All @@ -695,11 +711,18 @@ ConvertToMDEvents::identifyTheAlg(API::MatrixWorkspace_const_sptr inWS,const std
}
TargWSDescription.Ei = getEi(this);
}
// detector information can be currently lost in NoQ mode only, when no conversion from detectors position to Q occurs
if(is_detector_info_lost && emode!=-1){
convert_log.error()<<" Algorithm with ID: "<<the_algID<<" emode: "<<emode<<" request workspace with isntrument and full detectord information attached\n"
<<" but the detector information on input workspace has been lost\n";
throw(std::invalid_argument(" input workspace do not have full detector information attached to it"));
}


// set up the target workspace description;
TargWSDescription.n_dims = nDims;
TargWSDescription.emode = emode;
TargWSDescription.detInfoLost = is_detector_info_lost;
TargWSDescription.convert_to_hkl = convert_to_hkl;
TargWSDescription.dim_names = dim_IDs_requested;
TargWSDescription.dim_IDs = dim_IDs_requested;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,27 @@ namespace Mantid
namespace MDAlgorithms
{
bool
PreprocessedDetectors::is_defined(const API::MatrixWorkspace_const_sptr &inputWS)const
PreprocessedDetectors::isDefined(const API::MatrixWorkspace_const_sptr &inputWS)const
{
if(det_dir.empty())return false;

if(pBaseInstr !=inputWS->getInstrument()->baseInstrument())return false;
return true;
}

void
PreprocessedDetectors::allocDetMemory(size_t nHist)
{
this->det_dir.resize(nHist);
this->det_id.resize(nHist);
this->L2.resize(nHist);
this->TwoTheta.resize(nHist);
this->detIDMap.resize(nHist);
this->spec2detMap.assign(nHist,uint32_t(-1));


}

/** helper function, does preliminary calculations of the detectors positions to convert results into k-dE space ;
and places the resutls into static cash to be used in subsequent calls to this algorithm */
void DLLExport
Expand Down Expand Up @@ -46,16 +59,12 @@ processDetectorsPositions(const API::MatrixWorkspace_sptr inputWS,PreprocessedDe
//
const size_t nHist = inputWS->getNumberHistograms();

det_loc.det_dir.resize(nHist);
det_loc.det_id.resize(nHist);
det_loc.L2.resize(nHist);
det_loc.TwoTheta.resize(nHist);
det_loc.detIDMap.resize(nHist);
det_loc.spec2detMap.assign(nHist,uint32_t(-1));
size_t div=100;
det_loc.allocDetMemory(nHist);

size_t div=100;
// Loop over the spectra
size_t ic(0);
for (size_t i = 0; i < nHist; i++){
size_t ic(0);
for (size_t i = 0; i < nHist; i++){

Geometry::IDetector_const_sptr spDet;
try{
Expand Down Expand Up @@ -104,5 +113,39 @@ processDetectorsPositions(const API::MatrixWorkspace_sptr inputWS,PreprocessedDe
pProg->report();
}

void DLLExport
buildFakeDetectorsPositions(const API::MatrixWorkspace_sptr inputWS,PreprocessedDetectors &det_loc)
{

det_loc.L1 = 1;
double polar(0);
//
const size_t nHist = inputWS->getNumberHistograms();
det_loc.allocDetMemory(nHist);
// Loop over the spectra
for (size_t i = 0; i < nHist; i++){


det_loc.spec2detMap[i]= i;
det_loc.det_id[i] = (detid_t)i;
det_loc.detIDMap[i] = i;
det_loc.L2[i] = 10;


det_loc.TwoTheta[i] = polar;


double ez = 1.;
double ex = 0.;
double ey = 0.;

det_loc.det_dir[i].setX(ex);
det_loc.det_dir[i].setY(ey);
det_loc.det_dir[i].setZ(ez);

}
//
}

} // END MDAlgorithms ns
} // end Mantid ns
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class Convert2AnyTestHelper: public ConvertToMDEvents
}
std::string identifyMatrixAlg(API::MatrixWorkspace_const_sptr inMatrixWS,const std::string &Q_mode_req, const std::string &dE_mode_req,
std::vector<std::string> &outws_dim_names,std::vector<std::string> &outws_dim_units){
return ConvertToMDEvents::identifyMatrixAlg(inMatrixWS,Q_mode_req, dE_mode_req,outws_dim_names,outws_dim_units);
bool is_detInfoDefined;
return ConvertToMDEvents::identifyMatrixAlg(inMatrixWS,Q_mode_req, dE_mode_req,outws_dim_names,outws_dim_units,is_detInfoDefined);
}
//
std::string parseQMode(const std::string &Q_mode_req,const std::vector<std::string> &ws_dim_names,const std::vector<std::string> &ws_dim_units,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ namespace MDEvents
std::vector<std::string> defailt_qNames;
/// the string which describes subalgorithm, used to convert source ws to target MD ws.
std::string AlgID;
/// shows if workspace still has information about detectors. Some ws (like rebinned one) do not have this information any more.
bool detInfoLost;

};
/** function to build mslice-like axis name from the vector, which describes crystallographic direction along this axis*/
Expand Down
3 changes: 2 additions & 1 deletion Code/Mantid/Framework/MDEvents/src/MDWSDescription.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ convert_to_hkl(false),
u(1,0,0),
v(0,1,0),
is_uv_default(true),
defailt_qNames(3)
defailt_qNames(3),
detInfoLost(false)
{
for(size_t i=0;i<nDimesnions;i++){
dim_IDs[i]= dim_IDs[i]+boost::lexical_cast<std::string>(i);
Expand Down

0 comments on commit 6ea40c2

Please sign in to comment.