@@ -57,7 +57,7 @@ void MDWSDescription::buildFromMatrixWS(const API::MatrixWorkspace_const_sptr &p
{
inWS = pWS;
// fill additional dimensions values, defined by workspace properties;
this ->fillAddProperties (pWS ,dimProperyNames,AddCoord);
this ->fillAddProperties (inWS ,dimProperyNames,AddCoord);
this ->AlgID = QMode;
@@ -102,71 +102,19 @@ void MDWSDescription::buildFromMatrixWS(const API::MatrixWorkspace_const_sptr &p
}
}
// get input energy
this ->Ei = getEi (inWS);
// in direct or indirect mode input ws has to have input energy
if (emode==ConvertToMD::Direct||emode==ConvertToMD::Indir){
if (isNaN (Ei ))throw (std::invalid_argument (" Input neutron's energy has to be defined in inelastic mode " ));
if (isNaN (getEi (inWS) ))throw (std::invalid_argument (" Input neutron's energy has to be defined in inelastic mode " ));
}
// try to get the WS oriented lattice
if (pWS->sample ().hasOrientedLattice ()){
this ->pLatt = std::auto_ptr<Geometry::OrientedLattice>(new Geometry::OrientedLattice (pWS->sample ().getOrientedLattice ()));
}else {
this ->pLatt .reset ();
}
// Set up goniometer. Empty ws's goniometer returns unit transformation matrix
this ->GoniomMatr = inWS->run ().getGoniometer ().getR ();
// check if the detector information is still present in MD workspace
detInfoLost = false ;
API::NumericAxis *pYAxis = dynamic_cast <API::NumericAxis *>(inWS->getAxis (1 ));
if (pYAxis){
// if this is numeric axis, then the detector's information has been lost:
detInfoLost=true ;
}
}
/* *checks if workspace has to be processed in powder mode.
* A ws has to be processed in powder mode if it does not have oriented lattice defined */
bool MDWSDescription::isPowder ()const
{
if (pLatt.get ()==NULL )return true ;
return false ;
}
/* * function extracts the coordinates from additional workspace porperties and places them to proper position within
* the vector of MD coodinates for the particular workspace.
*
* @param dimProperyNames -- names of properties which should be treated as dimensions
*
* @returns AddCoord -- vector of additional coordinates (derived from WS properties) for current multidimensional event
*/
void MDWSDescription::fillAddProperties (Mantid::API::MatrixWorkspace_const_sptr inWS2D,const std::vector<std::string> &dimProperyNames,std::vector<coord_t > &AddCoord)const
{
size_t nDimPropNames = dimProperyNames.size ();
if (AddCoord.size ()!=nDimPropNames)AddCoord.resize (nDimPropNames);
for (size_t i=0 ;i<nDimPropNames;i++){
// HACK: A METHOD, Which converts TSP into value, correspondent to time scale of matrix workspace has to be developed and deployed!
Kernel::Property *pProperty = (inWS2D->run ().getProperty (dimProperyNames[i]));
Kernel::TimeSeriesProperty<double > *run_property = dynamic_cast <Kernel::TimeSeriesProperty<double > *>(pProperty);
if (run_property){
AddCoord[i]=coord_t (run_property->firstValue ());
}else {
// e.g Ei can be a property and dimenson
Kernel::PropertyWithValue<double > *proc_property = dynamic_cast <Kernel::PropertyWithValue<double > *>(pProperty);
if (!proc_property){
std::string ERR = " Can not interpret property, used as dimension.\n Property: " +dimProperyNames[i]+
" is neither a time series (run) property nor a property with value<double>" ;
throw (std::invalid_argument (ERR));
}
AddCoord[i] = coord_t (*(proc_property));
}
}
}
/* * the function builds MD event WS description from existing workspace.
* Primary used to obtain existing ws parameters
@@ -202,17 +150,36 @@ void MDWSDescription::buildFromMDWS(const API::IMDEventWorkspace_const_sptr &pWS
// }
}
/* * When the workspace has been build from existing MDWrokspace, some target worskpace parameters can not be defined.
examples are emode or input energy, which is actually source workspace parameters, or some other parameters
defined by the transformation algorithm
*/
void MDWSDescription::setUpMissingParameters (const MDEvents::MDWSDescription &SourceMatrWS)
{
this ->inWS = SourceMatrWS.inWS ;
this ->emode = SourceMatrWS.emode ;
this ->AlgID = SourceMatrWS.AlgID ;
this ->AddCoord .assign (SourceMatrWS.AddCoord .begin (),SourceMatrWS.AddCoord .end ());
this ->GoniomMatr = SourceMatrWS.GoniomMatr ;
}
/* *function compares old workspace description with the new workspace description, defined by the algorithm properties and
* selects/changes the properties which can be changed through input parameters given that target MD workspace exist
*
* This situation occurs if the base description has been obtained from MD workspace, and one is building a description from
* other matrix workspace to add new data to the existing workspace. The workspaces have to copmarible
*
* @param NewMDWorkspaceD -- MD workspace description, obtained from algorithm parameters
*
* @returns NewMDWorkspaceD -- modified md workspace description, which is compartible with existing MD workspace
*
*/
void MDWSDescription::compareDescriptions (MDEvents::MDWSDescription &NewMDWorkspaceD)
void MDWSDescription::checkWSCorresponsMDWorkspace (MDEvents::MDWSDescription &NewMDWorkspaceD)
{
if (this ->nDims != NewMDWorkspaceD.nDims )
{
@@ -224,69 +191,18 @@ void MDWSDescription::compareDescriptions(MDEvents::MDWSDescription &NewMDWorks
{
throw (std::invalid_argument (" Workspace description has not been correctly defined, as emode has not been defined" ));
}
if (this ->emode ==ConvertToMD::Direct||this ->emode ==ConvertToMD::Indir)
{
volatile double Ei = this ->Ei ;
if (this ->Ei !=Ei){
std::string ERR = " Workspace description has not been correctly defined, as emode " +boost::lexical_cast<std::string>(this ->emode )+" request input energy to be defined" ;
throw (std::invalid_argument (ERR));
}
}
// TODO: More thorough checks may be nesessary to prevent adding different kind of workspaces e.g 4D |Q|-dE-T-P workspace to Q3d+dE ws
}
/* * When the workspace has been build from existing MDWrokspace, some target worskpace parameters can not be defined.
examples are emode or input energy, which is actually source workspace parameters
*/
void MDWSDescription::setUpMissingParameters (const MDEvents::MDWSDescription &SourceMDWSDescr)
{
this ->inWS = SourceMDWSDescr.inWS ;
this ->emode = SourceMDWSDescr.emode ;
this ->Ei = SourceMDWSDescr.Ei ;
this ->AlgID = SourceMDWSDescr.AlgID ;
this ->emode = SourceMDWSDescr.emode ;
this ->AddCoord .assign (SourceMDWSDescr.AddCoord .begin (),SourceMDWSDescr.AddCoord .end ());
if (SourceMDWSDescr.pLatt .get ()){
this ->pLatt = std::auto_ptr<Geometry::OrientedLattice>(new Geometry::OrientedLattice (*(SourceMDWSDescr.pLatt )));
}
this ->GoniomMatr = SourceMDWSDescr.GoniomMatr ;
}
/* * function verifies the consistency of the min and max dimsnsions values checking if all necessary
* values vere defined and min values are smaller then mav values */
void MDWSDescription::checkMinMaxNdimConsistent ()const
{
if (this ->dimMin .size ()!=this ->dimMax .size ())
{
std::string ERR = " number of specified min dimension values: " +boost::lexical_cast<std::string>(dimMin.size ())+
" , number of max values: " +boost::lexical_cast<std::string>(dimMax.size ())+
" and total number of target dimensions: " +boost::lexical_cast<std::string>(nDims)+" are not consistent\n " ;
throw (std::invalid_argument (ERR));
}
for (size_t i=0 ; i<this ->dimMin .size ();i++)
{
if (this ->dimMax [i]<=this ->dimMin [i])
{
std::string ERR = " min value " +boost::lexical_cast<std::string>(dimMin[i])+
" not less then max value" +boost::lexical_cast<std::string>(dimMax[i])+" in direction: " +
boost::lexical_cast<std::string>(i)+" \n " ;
throw (std::invalid_argument (ERR));
}
}
}
// / empty constructor
MDWSDescription::MDWSDescription (unsigned int nDimensions):
emode (ConvertToMD::Undef),
Ei (std::numeric_limits<double >::quiet_NaN()),
rotMatrix (9 ,0 ), // set transformation matrix to 0 to certainly see rubbish if error later
Wtransf (3 ,3 ,true ),
GoniomMatr (3 ,3 ,true ),
detInfoLost (true )
GoniomMatr (3 ,3 ,true )
{
this ->resizeDimDescriptions (nDimensions);
@@ -310,59 +226,35 @@ void MDWSDescription::resizeDimDescriptions(unsigned int nDimensions, size_t nBi
}
}
/* *function sets up min-max values to the dimensions, described by the class
*@param minVal -- vector of minimal dimension's values
*@param maxVal -- vector of maximal dimension's values
*
*/
void MDWSDescription::setMinMax (const std::vector<double > &minVal,const std::vector<double > &maxVal)
{
dimMin.assign (minVal.begin (),minVal.end ());
dimMax.assign (maxVal.begin (),maxVal.end ());
this ->checkMinMaxNdimConsistent ();
this ->checkMinMaxNdimConsistent (dimMin,dimMax );
}
MDWSDescription & MDWSDescription::operator =(const MDWSDescription &rhs)
{
this ->nDims = rhs.nDims ;
this ->emode = rhs.emode ;
this ->Ei = rhs.Ei ;
// prepare all arrays:
this ->dimMin = rhs.dimMin ;
this ->dimMax = rhs.dimMax ;
this ->dimNames =rhs.dimNames ;
this ->dimIDs =rhs.dimIDs ;
this ->dimUnits =rhs.dimUnits ;
this ->nBins =rhs.nBins ;
this ->rotMatrix = rhs.rotMatrix ;
this ->AlgID = rhs.AlgID ;
this ->detInfoLost = rhs.detInfoLost ;
this ->pDetLocations = rhs.pDetLocations ;
if (rhs.pLatt .get ()){
this ->pLatt = std::auto_ptr<Geometry::OrientedLattice>(new Geometry::OrientedLattice (*(rhs.pLatt )));
}
this ->Wtransf = rhs.Wtransf ;
this ->GoniomMatr = rhs.GoniomMatr ;
return *this ;
}
/* *get vector of minimal and maximal values from the class */
void MDWSDescription::getMinMax (std::vector<double > &min,std::vector<double > &max)const
{
min.assign (this ->dimMin .begin (),this ->dimMin .end ());
max.assign (this ->dimMax .begin (),this ->dimMax .end ());
}
// ******************************************************************************************************************************************
// ************* STATIC HELPER FUNCTIONS
// ******************************************************************************************************************************************
/* * Helper function to obtain the energy of incident neutrons from the input workspaec
*
*@param pHost the pointer to the algorithm to work with
*
*@returns the incident energy of the neutrons or quet NaN if can not retrieve one
*/
double MDWSDescription::getEi (API::MatrixWorkspace_const_sptr inWS2D)const
double MDWSDescription::getEi (API::MatrixWorkspace_const_sptr inWS2D)
{
if (!inWS2D.get ()){
throw (std::invalid_argument (" getEi: invoked on empty input workspace " ));
@@ -373,13 +265,86 @@ double MDWSDescription::getEi(API::MatrixWorkspace_const_sptr inWS2D)const
}catch (...){
}
if (!pProp){
// convert_log.error()<<"getEi: can not obtain incident energy of neutrons\n";
// throw(std::logic_error(" should not call this function when incident energy is undefined"));
return std::numeric_limits<double >::quiet_NaN ();
}
return (*pProp);
}
/* * function extracts the coordinates from additional workspace porperties and places them to proper position within
* the vector of MD coodinates for the particular workspace.
*
* @param dimProperyNames -- names of properties which should be treated as dimensions
*
* @returns AddCoord -- vector of additional coordinates (derived from WS properties) for current multidimensional event
*/
void MDWSDescription::fillAddProperties (Mantid::API::MatrixWorkspace_const_sptr inWS2D,const std::vector<std::string> &dimProperyNames,std::vector<coord_t > &AddCoord)
{
size_t nDimPropNames = dimProperyNames.size ();
if (AddCoord.size ()!=nDimPropNames)AddCoord.resize (nDimPropNames);
for (size_t i=0 ;i<nDimPropNames;i++){
// HACK: A METHOD, Which converts TSP into value, correspondent to time scale of matrix workspace has to be developed and deployed!
Kernel::Property *pProperty = (inWS2D->run ().getProperty (dimProperyNames[i]));
Kernel::TimeSeriesProperty<double > *run_property = dynamic_cast <Kernel::TimeSeriesProperty<double > *>(pProperty);
if (run_property){
AddCoord[i]=coord_t (run_property->firstValue ());
}else {
// e.g Ei can be a property and dimenson
Kernel::PropertyWithValue<double > *proc_property = dynamic_cast <Kernel::PropertyWithValue<double > *>(pProperty);
if (!proc_property){
std::string ERR = " Can not interpret property, used as dimension.\n Property: " +dimProperyNames[i]+
" is neither a time series (run) property nor a property with value<double>" ;
throw (std::invalid_argument (ERR));
}
AddCoord[i] = coord_t (*(proc_property));
}
}
}
/* * function verifies the consistency of the min and max dimsnsions values checking if all necessary
* values vere defined and min values are smaller then mav values */
void MDWSDescription::checkMinMaxNdimConsistent (const std::vector<double > &minVal,const std::vector<double > &maxVal)
{
if (minVal.size ()!=maxVal.size ())
{
std::string ERR = " number of specified min dimension values: " +boost::lexical_cast<std::string>(minVal.size ())+
" and number of max values: " +boost::lexical_cast<std::string>(maxVal.size ())+
" are not consistent\n " ;
throw (std::invalid_argument (ERR));
}
for (size_t i=0 ; i<minVal.size ();i++)
{
if (maxVal[i]<=minVal[i])
{
std::string ERR = " min value " +boost::lexical_cast<std::string>(minVal[i])+
" not less then max value" +boost::lexical_cast<std::string>(maxVal[i])+" in direction: " +
boost::lexical_cast<std::string>(i)+" \n " ;
throw (std::invalid_argument (ERR));
}
}
}
// / function checks if source workspace still has information about detectors. Some ws (like rebinned one) do not have this information any more.
bool MDWSDescription::isDetInfoLost (Mantid::API::MatrixWorkspace_const_sptr inWS2D)
{
API::NumericAxis *pYAxis = dynamic_cast <API::NumericAxis *>(inWS2D->getAxis (1 ));
if (pYAxis){
// if this is numeric axis, then the detector's information has been lost:
return true ;
}
return false ;
}
/* * function retrieves copy of the oriented lattice from the workspace */
boost::shared_ptr<Geometry::OrientedLattice> MDWSDescription::getOrientedLattice (Mantid::API::MatrixWorkspace_const_sptr inWS2D)
{
// try to get the WS oriented lattice
boost::shared_ptr<Geometry::OrientedLattice> orl;
if (inWS2D->sample ().hasOrientedLattice ()){
orl = boost::shared_ptr<Geometry::OrientedLattice>(new Geometry::OrientedLattice (inWS2D->sample ().getOrientedLattice ()));
}
return orl;
}
}
}