|
|
@@ -1,241 +1,131 @@ |
|
|
#include "MDEvents/MDTransfModQ.h" |
|
|
#include "MantidMDEvents/MDTransfModQ.h" |
|
|
|
|
|
namespace Mantid |
|
|
{ |
|
|
namespace MDAlgorithms |
|
|
namespace MDEvents |
|
|
{ |
|
|
|
|
|
|
|
|
/** Set of internal class used by ConvertToMDEvents algorithm and responsible for conversion of input workspace |
|
|
* data into proper number of output dimensions for ModQ transformation |
|
|
* |
|
|
* Currently contains Elastic and Inelastic transformations |
|
|
* |
|
|
* This particular file defines specializations of generic coordinate transformation templated to the ModQ case |
|
|
* |
|
|
* @date 11-10-2011 |
|
|
|
|
|
Copyright © 2010 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory |
|
|
|
|
|
This file is part of Mantid. |
|
|
|
|
|
Mantid is free software; you can redistribute it and/or modify |
|
|
it under the terms of the GNU General Public License as published by |
|
|
the Free Software Foundation; either version 3 of the License, or |
|
|
(at your option) any later version. |
|
|
|
|
|
Mantid is distributed in the hope that it will be useful, |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
|
GNU General Public License for more details. |
|
|
|
|
|
You should have received a copy of the GNU General Public License |
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
|
|
|
|
File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid> |
|
|
Code Documentation is available at: <http://doxygen.mantidproject.org> |
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool MDTransfModQInelastic::calcGenericVariables(std::vector<coord_t> &Coord, size_t nd) |
|
|
//********************************************************************************************************************** |
|
|
//*************************************************** ELASTIC ****************************************************** |
|
|
//********************************************************************************************************************** |
|
|
bool MDTransfModQElastic::calcGenericVariables(std::vector<coord_t> &Coord, size_t nd) |
|
|
{ |
|
|
/// 2 coordinates (|Q|, DeltaE) came from workspace, are interconnnected all additional defined by properties, |
|
|
/// here we copy these values into Coord vector |
|
|
if(!pHost->fillAddProperties(Coord,nd,2))return false; |
|
|
|
|
|
// energy |
|
|
Ei = pHost->getEi(); |
|
|
// the wave vector of incident neutrons; |
|
|
ki=sqrt(Ei/PhysicalConstants::E_mev_toNeutronWavenumberSq); |
|
|
// get transformation matrix (needed for CrystalAsPoder mode) |
|
|
rotMat = pHost->getTransfMatrix(); |
|
|
// if workspace is not in DeltaE, initiate units conversion, if not -- empty conversion should be instanciated |
|
|
const Kernel::Unit_sptr pThisUnit= pHost->getAxisUnits(); |
|
|
// CONV_UNITS_FROM.setUpConversion(*(pHost->getDetectors()),pThisUnit->unitID(),"DeltaE"); |
|
|
|
|
|
// 1 coordinate (|Q|) came from workspace, all additional defined by properties: |
|
|
if(!pHost->fillAddProperties(Coord,nd,nMatrixDim))return false; |
|
|
// get transformation matrix (needed for CrystalAsPoder mode) |
|
|
rotMat = pHost->getTransfMatrix(); |
|
|
|
|
|
// get pointer to the positions of the detectors |
|
|
std::vector<Kernel::V3D> const & DetDir = pHost->pPrepDetectors()->getDetDir(); |
|
|
pDet = &DetDir[0]; |
|
|
pHost->getMinMax(dim_min,dim_max); |
|
|
|
|
|
// dim_min/max here are momentums and they are verified on momentum squared base |
|
|
if(dim_min[0]<0)dim_min[0]=0; |
|
|
if(dim_max[0]<0)dim_max[0]=0; |
|
|
|
|
|
dim_min[0]*=dim_min[0]; |
|
|
dim_max[0]*=dim_max[0]; |
|
|
if(std::fabs(dim_min[0]-dim_max[0])<FLT_EPSILON||dim_max[0]<dim_min[0]) |
|
|
{ |
|
|
std::string ERR = "ModQ inelastic coordinate transformation: Min Q^2 value: "+boost::lexical_cast<std::string>(dim_min[0])+ |
|
|
" is more or equal then Max Q^2 value: "+boost::lexical_cast<std::string>(dim_max[0]); |
|
|
throw(std::invalid_argument(ERR)); |
|
|
} |
|
|
// |
|
|
return true; |
|
|
std::vector<Kernel::V3D> const & DetDir = pHost->pPrepDetectors()->getDetDir(); |
|
|
pDet = &DetDir[0]; // |
|
|
// |
|
|
pHost->getMinMax(dim_min,dim_max); |
|
|
// dim_min/max here are momentums and they are verified on momentum squared base |
|
|
if(dim_min[0]<0)dim_min[0]=0; |
|
|
if(dim_max[0]<0)dim_max[0]=0; |
|
|
|
|
|
// dim_min here is a momentum and it is verified on momentum squared base |
|
|
dim_min[0]*=dim_min[0]; |
|
|
dim_max[0]*=dim_max[0]; |
|
|
if(std::fabs(dim_min[0]-dim_max[0])<FLT_EPSILON||dim_max[0]<dim_min[0]) |
|
|
{ |
|
|
std::string ERR = "ModQ coordinate transformation: Min Q^2 value: "+boost::lexical_cast<std::string>(dim_min[0])+ |
|
|
" is more or equal then Max Q^2 value: "+boost::lexical_cast<std::string>(dim_max[0]); |
|
|
throw(std::invalid_argument(ERR)); |
|
|
} |
|
|
|
|
|
return true; |
|
|
} |
|
|
// |
|
|
bool MDTransfModQInelastic::calcYDepCoordinates(std::vector<coord_t> &Coord,size_t i) |
|
|
bool MDTransfModQElastic::calcYDepCoordinates(std::vector<coord_t> &Coord,size_t i) |
|
|
{ |
|
|
UNUSED_ARG(Coord); |
|
|
CONV_UNITS_FROM.updateConversion(i); |
|
|
ex = (pDet+i)->X(); |
|
|
ey = (pDet+i)->Y(); |
|
|
ez = (pDet+i)->Z(); |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool MDTransfModQInelastic::calc1MatrixCoord(const double& E_tr,std::vector<coord_t> &Coord)const |
|
|
// |
|
|
bool MDTransfModQElastic::calcMatrixCoord(const double& k0,std::vector<coord_t> &Coord)const |
|
|
{ |
|
|
if(E_tr<dim_min[1]||E_tr>=dim_max[1])return false; |
|
|
Coord[1] =(coord_t)E_tr; |
|
|
|
|
|
// get module of the wavevector for scattered neutrons |
|
|
double k_tr = k_trans<MODE>(Ei,E_tr); |
|
|
|
|
|
double qx = -ex*k_tr; |
|
|
double qy = -ey*k_tr; |
|
|
double qz = ki - ez*k_tr; |
|
|
// transformation matrix has to be here for "Crystal AS Powder conversion mode, further specialization possible if "powder" switch provided" |
|
|
double qx = -ex*k0; |
|
|
double qy = -ey*k0; |
|
|
double qz = (1 - ez)*k0; |
|
|
// transformation matrix has to be here for "Crystal AS Powder mode, further specialization possible if powder mode is defined " |
|
|
double Qx = (rotMat[0]*qx+rotMat[1]*qy+rotMat[2]*qz); |
|
|
double Qy = (rotMat[3]*qx+rotMat[4]*qy+rotMat[5]*qz); |
|
|
double Qz = (rotMat[6]*qx+rotMat[7]*qy+rotMat[8]*qz); |
|
|
|
|
|
double Qsq = Qx*Qx+Qy*Qy+Qz*Qz; |
|
|
if(Qsq < dim_min[0]||Qsq>=dim_max[0])return false; |
|
|
Coord[0] = (coord_t)sqrt(Qsq); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
// should be actually on ICoordTransformer but there is problem with template-overloaded functions |
|
|
bool MDTransfModQInelastic::calcMatrixCoord(const MantidVec& X,size_t i,size_t j,std::vector<coord_t> &Coord)const |
|
|
|
|
|
void MDTransfModQElastic::initialize(const ConvToMDEventsBase &Conv) |
|
|
{ |
|
|
UNUSED_ARG(i); |
|
|
//double X_ev = CONV_UNITS_FROM.getXConverted(X,j); |
|
|
//return calc1MatrixCoord(X_ev,Coord); |
|
|
nMatrixDim = 1; |
|
|
pHost = &Conv; |
|
|
} |
|
|
|
|
|
bool MDTransfModQInelastic::convertAndCalcMatrixCoord(const double & X,std::vector<coord_t> &Coord)const |
|
|
//********************************************************************************************************************** |
|
|
//*************************************************** INELASTIC ***************************************************** |
|
|
//********************************************************************************************************************** |
|
|
|
|
|
|
|
|
bool MDTransfModQInelastic::calcGenericVariables(std::vector<coord_t> &Coord, size_t nd) |
|
|
{ |
|
|
double X_ev = CONV_UNITS_FROM.getXConverted(X); |
|
|
return calc1MatrixCoord(X_ev,Coord); |
|
|
} |
|
|
// constructor; |
|
|
MDTransfModQInelastic::MDTransfModQInelastic():pDet(NULL),pHost(NULL){} |
|
|
void MDTransfModQInelastic::setUpTransf(IConvertToMDEventsWS *pConv){ |
|
|
pHost = pConv; |
|
|
} |
|
|
private: |
|
|
// the energy of the incident neutrons |
|
|
double Ei; |
|
|
// the wavevector of incident neutrons |
|
|
double ki; |
|
|
// directions to the detectors |
|
|
double ex,ey,ez; |
|
|
// the matrix which transforms the neutron momentums from lablratory to crystall coordinate system. |
|
|
std::vector<double> rotMat; |
|
|
// min-max values, some modified to work with squared values: |
|
|
std::vector<double> dim_min,dim_max; |
|
|
// |
|
|
Kernel::V3D const *pDet; |
|
|
// Calling Mantid algorithm |
|
|
IConvertToMDEventsWS *pHost; |
|
|
// class which would convert units |
|
|
UnitsConverter<CONV,TYPE> CONV_UNITS_FROM; |
|
|
|
|
|
}; |
|
|
|
|
|
inline bool calcGenericVariables(std::vector<coord_t> &Coord, size_t nd) |
|
|
{ |
|
|
|
|
|
// 1 coordinate (|Q|) came from workspace, all additional defined by properties: |
|
|
if(!pHost->fillAddProperties(Coord,nd,1))return false; |
|
|
// get transformation matrix (needed for CrystalAsPoder mode) |
|
|
rotMat = pHost->getTransfMatrix(); |
|
|
|
|
|
const Kernel::Unit_sptr pThisUnit= pHost->getAxisUnits(); |
|
|
CONV_UNITS_FROM.setUpConversion(*(pHost->getDetectors()),pThisUnit->unitID(),"Momentum"); |
|
|
/// 2 coordinates (|Q|, DeltaE) came from workspace, are interconnnected all additional defined by properties, |
|
|
/// here we copy these values into Coord vector |
|
|
if(!MDTransfModQElastic::calcGenericVariables(Coord, nd))return false; |
|
|
// energy |
|
|
Ei = pHost->getEi(); |
|
|
// the wave vector of incident neutrons; |
|
|
ki=sqrt(Ei/PhysicalConstants::E_mev_toNeutronWavenumberSq); |
|
|
|
|
|
// get pointer to the positions of the detectors |
|
|
std::vector<Kernel::V3D> const & DetDir = pHost->pPrepDetectors()->getDetDir(); |
|
|
pDet = &DetDir[0]; // |
|
|
// |
|
|
pHost->getMinMax(dim_min,dim_max); |
|
|
// dim_min here is a momentum and it is verified on momentum squared base |
|
|
dim_min[0]*=dim_min[0]; |
|
|
dim_max[0]*=dim_max[0]; |
|
|
return true; |
|
|
} |
|
|
// |
|
|
inline bool calcYDepCoordinates(std::vector<coord_t> &Coord,size_t i) |
|
|
{ |
|
|
UNUSED_ARG(Coord); |
|
|
CONV_UNITS_FROM.updateConversion(i); |
|
|
ex = (pDet+i)->X(); |
|
|
ey = (pDet+i)->Y(); |
|
|
ez = (pDet+i)->Z(); |
|
|
return true; |
|
|
} |
|
|
// |
|
|
inline bool calc1MatrixCoord(const double& k0,std::vector<coord_t> &Coord)const |
|
|
{ |
|
|
return true; |
|
|
} |
|
|
|
|
|
bool MDTransfModQInelastic::calcMatrixCoord(const double& E_tr,std::vector<coord_t> &Coord)const |
|
|
{ |
|
|
if(E_tr<dim_min[1]||E_tr>=dim_max[1])return false; |
|
|
Coord[1] =(coord_t)E_tr; |
|
|
double k_tr; |
|
|
// get module of the wavevector for scattered neutrons |
|
|
if(this->emode==ConvertToMD::Direct){ |
|
|
k_tr=sqrt((Ei-E_tr)/PhysicalConstants::E_mev_toNeutronWavenumberSq); |
|
|
}else{ |
|
|
k_tr=sqrt((Ei+E_tr)/PhysicalConstants::E_mev_toNeutronWavenumberSq); |
|
|
} |
|
|
|
|
|
double qx = -ex*k0; |
|
|
double qy = -ey*k0; |
|
|
double qz = (1 - ez)*k0; |
|
|
// transformation matrix has to be here for "Crystal AS Powder mode, further specialization possible if " |
|
|
double qx = -ex*k_tr; |
|
|
double qy = -ey*k_tr; |
|
|
double qz = ki - ez*k_tr; |
|
|
// transformation matrix has to be here for "Crystal AS Powder conversion mode, further specialization possible if "powder" mode defined" |
|
|
double Qx = (rotMat[0]*qx+rotMat[1]*qy+rotMat[2]*qz); |
|
|
double Qy = (rotMat[3]*qx+rotMat[4]*qy+rotMat[5]*qz); |
|
|
double Qz = (rotMat[6]*qx+rotMat[7]*qy+rotMat[8]*qz); |
|
|
|
|
|
double Qsq = Qx*Qx+Qy*Qy+Qz*Qz; |
|
|
if(Qsq < dim_min[0]||Qsq>=dim_max[0])return false; |
|
|
Coord[0] = (coord_t)sqrt(Qsq); |
|
|
|
|
|
return true; |
|
|
|
|
|
} |
|
|
|
|
|
// should be actually on ICoordTransformer |
|
|
inline bool calcMatrixCoord(const MantidVec& X,size_t i,size_t j,std::vector<coord_t> &Coord)const |
|
|
{ |
|
|
UNUSED_ARG(i); |
|
|
double X_ev = CONV_UNITS_FROM.getXConverted(X,j); |
|
|
|
|
|
return calc1MatrixCoord(X_ev,Coord); |
|
|
} |
|
|
inline bool convertAndCalcMatrixCoord(const double & X,std::vector<coord_t> &Coord)const |
|
|
{ |
|
|
double X_ev = CONV_UNITS_FROM.getXConverted(X); |
|
|
return calc1MatrixCoord(X_ev,Coord); |
|
|
} |
|
|
|
|
|
// constructor; |
|
|
CoordTransformer():pDet(NULL),pHost(NULL){} |
|
|
void setUpTransf(IConvertToMDEventsWS *pConv){ |
|
|
pHost = pConv; |
|
|
} |
|
|
private: |
|
|
// the energy of the incident neutrons |
|
|
double Ei; |
|
|
// the wavevector of incident neutrons |
|
|
double ki; |
|
|
// directions to the detectors |
|
|
double ex,ey,ez; |
|
|
// the matrix which transforms the neutron momentums from lablratory to crystall coordinate system. |
|
|
std::vector<double> rotMat; |
|
|
// min-max values, some modified to work with squared values: |
|
|
std::vector<double> dim_min,dim_max; |
|
|
// |
|
|
Kernel::V3D const * pDet; |
|
|
// Calling Mantid algorithm |
|
|
IConvertToMDEventsWS *pHost; |
|
|
// class which would convert units |
|
|
UnitsConverter<CONV,TYPE> CONV_UNITS_FROM; |
|
|
|
|
|
}; |
|
|
#endif |
|
|
} |
|
|
|
|
|
void MDTransfModQInelastic::initialize(const ConvToMDEventsBase &Conv) |
|
|
{ |
|
|
// inelastic workspace provides two variables |
|
|
nMatrixDim = 2; |
|
|
pHost = &Conv; |
|
|
emode = (ConvertToMD::EModes)pHost->getEMode(); |
|
|
} |
|
|
|
|
|
} // End MDAlgorighms namespace |
|
|
} // End Mantid namespace |