Skip to content

Commit

Permalink
refs #7351 Extracted Common part of the SofQ codes into separate class
Browse files Browse the repository at this point in the history
  • Loading branch information
abuts committed Jul 15, 2013
1 parent 7686062 commit c73febe
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 234 deletions.
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/Algorithms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ set ( SRC_FILES
src/SignalOverError.cpp
src/SmoothData.cpp
src/SmoothNeighbours.cpp
src/SofQCommon.cpp
src/SofQW.cpp
src/SofQW2.cpp
src/SofQW3.cpp
Expand Down Expand Up @@ -410,6 +411,7 @@ set ( INC_FILES
inc/MantidAlgorithms/SignalOverError.h
inc/MantidAlgorithms/SmoothData.h
inc/MantidAlgorithms/SmoothNeighbours.h
inc/MantidAlgorithms/SofQCommon.h
inc/MantidAlgorithms/SofQW.h
inc/MantidAlgorithms/SofQW2.h
inc/MantidAlgorithms/SofQW3.h
Expand Down
35 changes: 35 additions & 0 deletions Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/SofQCommon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#ifndef MANTID_ALGORITHMS_SOFQW_COMMON_H_
#define MANTID_ALGORITHMS_SOFQW_COMMON_H_

#include "MantidAPI/Algorithm.h"
#include "MantidGeometry/IDetector.h"
// number of small routines used by all SofQW algorithms intended to provide united user interface to all SofQ algorihtms.

namespace Mantid
{
namespace Algorithms
{

struct SofQCommon
{

/// E Mode
int m_emode;
/// EFixed has been provided
bool m_efixedGiven;
/// EFixed
double m_efixed;

SofQCommon():m_emode(0), m_efixedGiven(false), m_efixed(0.0){}

void initCachedValues(API::MatrixWorkspace_const_sptr workspace, API::Algorithm *const hostAlgorithm);

/// Get the efixed value for the given detector
double getEFixed(Geometry::IDetector_const_sptr det) const;
};

}
}


#endif
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAPI/Algorithm.h"
#include "MantidAlgorithms/SofQCommon.h"

namespace Mantid
{
Expand Down Expand Up @@ -76,6 +76,8 @@ class DLLExport SofQW : public API::Algorithm
/// Execution code
void exec();

SofQCommon m_EmodeProperties;

};

} // namespace Algorithms
Expand Down
10 changes: 2 additions & 8 deletions Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/SofQW2.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidAlgorithms/SofQCommon.h"
#include "MantidAlgorithms/Rebin2D.h"
#include "MantidGeometry/Math/Quadrilateral.h"
#include "MantidGeometry/IDetector.h"
Expand Down Expand Up @@ -74,8 +75,6 @@ namespace Mantid
// /// Rebin the inputQ
// void rebinToOutput(const Geometry::Quadrilateral & inputQ, API::MatrixWorkspace_const_sptr inputWS,
// const size_t i, const size_t j, API::MatrixWorkspace_sptr outputWS);
/// Get the efixed value for the given detector
double getEFixed(Geometry::IDetector_const_sptr det) const;
/// Calculate the Q value for a direct instrument
double calculateDirectQ(const double efixed, const double deltaE, const double twoTheta, const double psi) const;
/// Calculate the Q value for an indirect instrument
Expand All @@ -88,13 +87,8 @@ namespace Mantid
/// Init the theta index
void initThetaCache(API::MatrixWorkspace_const_sptr workspace);

/// E Mode
int m_emode;
/// EFixed has been provided
bool m_efixedGiven;
/// EFixed
double m_efixed;

SofQCommon m_EmodeProperties;
//---------------------------------------------------------------------------------
/// Output Q axis
std::vector<double> m_Qout;
Expand Down
15 changes: 4 additions & 11 deletions Code/Mantid/Framework/Algorithms/inc/MantidAlgorithms/SofQW3.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "MantidGeometry/IDetector.h"
#include "MantidDataObjects/RebinnedOutput.h"
#include <list>
#include "MantidAlgorithms/SofQCommon.h"

namespace Mantid
{
Expand Down Expand Up @@ -73,10 +74,8 @@ namespace Mantid
void exec();

/// Calculate the Q value for given conditions.
double calculateQ(const double efixed, const double deltaE,
double calculateQ(const double efixed,const int emode, const double deltaE,
const double twoTheta, const double azimuthal) const;
/// Get the efixed value for the given detector
double getEFixed(Geometry::IDetector_const_sptr det) const;
/// Init variables cache base on the given workspace
void initCachedValues(API::MatrixWorkspace_const_sptr workspace);
/// Init the theta index
Expand All @@ -88,14 +87,8 @@ namespace Mantid
DataObjects::RebinnedOutput_sptr setUpOutputWorkspace(API::MatrixWorkspace_const_sptr inputWorkspace,
const std::vector<double> & binParams, std::vector<double>& newAxis);


/// E Mode
int m_emode;
/// EFixed has been provided
bool m_efixedGiven;
/// EFixed
double m_efixed;
/// Output Q axis
SofQCommon m_EmodeProperties;
/// Output Q axis
std::vector<double> m_Qout;
/// Single value theta width
double m_thetaWidth;
Expand Down
88 changes: 88 additions & 0 deletions Code/Mantid/Framework/Algorithms/src/SofQCommon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#include "MantidAlgorithms/SofQCommon.h"

namespace Mantid
{
namespace Algorithms
{
/** The procedure analyses emode and efixed properties provided to the algorithm and identify the energy analysis mode and the way the properties are defined
@param workspace :: input workspace which may or may not have incident energy property (Ei) attached to it as the run log
@param hostAlgorithm :: the pointer to SofQ algorithm hosting the base class. This algorithm expects to have EMode and EFixed properties attached to it.
*/
void SofQCommon::initCachedValues(API::MatrixWorkspace_const_sptr workspace, API::Algorithm *const hostAlgorithm)
{
// Retrieve the emode & efixed properties
const std::string emode = hostAlgorithm->getProperty("EMode");
// Convert back to an integer representation
m_emode = 0;
if (emode == "Direct") m_emode=1;
else if (emode == "Indirect") m_emode = 2;
m_efixed = hostAlgorithm->getProperty("EFixed");

// Check whether they should have supplied an EFixed value
if( m_emode == 1 ) // Direct
{
// If GetEi was run then it will have been stored in the workspace, if not the user will need to enter one
if( m_efixed == 0.0 )
{
if ( workspace->run().hasProperty("Ei") )
{
Kernel::Property *p = workspace->run().getProperty("Ei");
Kernel::PropertyWithValue<double> *eiProp = dynamic_cast<Kernel::PropertyWithValue<double>*>(p);
if( !eiProp ) throw std::runtime_error("Input workspace contains Ei but its property type is not a double.");
m_efixed = (*eiProp)();
}
else
{
throw std::invalid_argument("Input workspace does not contain an EFixed value. Please provide one or run GetEi.");
}
}
else
{
m_efixedGiven = true;
}
}
else
{
if( m_efixed != 0.0 )
{
m_efixedGiven = true;
}
}
}





/**
* Return the efixed for this detector. In Direct mode this has to be property set up earlier and in Indirect mode it may be the property of a component
if not specified globally for the instrument.
* @param det A pointer to a detector object
* @return The value of efixed
*/
double SofQCommon::getEFixed(Geometry::IDetector_const_sptr det) const
{
double efixed(0.0);
if( m_emode == 1 ) //Direct
{
efixed = m_efixed;
}
else // Indirect
{
if( m_efixedGiven ) efixed = m_efixed; // user provided a value
else
{
std::vector<double> param = det->getNumberParameter("EFixed");
if( param.empty() ) throw std::runtime_error("Cannot find EFixed parameter for component \"" + det->getName()
+ "\". This is required in indirect mode. Please check the IDF contains these values.");
efixed = param[0];
}
}
return efixed;
}


}
}
67 changes: 15 additions & 52 deletions Code/Mantid/Framework/Algorithms/src/SofQW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,40 +108,8 @@ void SofQW::exec()
MatrixWorkspace_sptr outputWorkspace = setUpOutputWorkspace(inputWorkspace, getProperty("QAxisBinning"), verticalAxis);
setProperty("OutputWorkspace",outputWorkspace);

// Retrieve the emode & efixed properties
const std::string emodeStr = getProperty("EMode");
// Convert back to an integer representation
int emode = 0;
if (emodeStr == "Direct") emode=1;
else if (emodeStr == "Indirect") emode=2;
// Retrieve the emode & efixed properties

// Check whether they should have supplied an EFixed value
if(emode == 1 ) // Direct
{

// If GetEi was run then it will have been stored in the workspace, if not the user will need to enter one
if ( inputWorkspace->run().hasProperty("Ei") )
{
Kernel::Property *p = inputWorkspace->run().getProperty("Ei");
Kernel::PropertyWithValue<double> *eiProp = dynamic_cast<Kernel::PropertyWithValue<double>*>(p);
if( !eiProp )
{
throw std::runtime_error("Input workspace contains Ei but its property type is not a double.");
}
efixed = (*eiProp)();
}
else
{
efixed = getProperty("EFixed");
if (efixed == 0)
{
throw std::invalid_argument("Input workspace does not contain an EFixed value. Please provide one or run GetEi.");
}
}

}

m_EmodeProperties.initCachedValues(inputWorkspace,this);
int emode = m_EmodeProperties.m_emode;

// Get a pointer to the instrument contained in the workspace
Instrument_const_sptr instrument = inputWorkspace->getInstrument();
Expand Down Expand Up @@ -175,26 +143,13 @@ void SofQW::exec()
Progress prog(this,0.0,1.0,numHists);
for (int64_t i = 0; i < int64_t(numHists); ++i)
{
try {
try
{
// Now get the detector object for this histogram
IDetector_const_sptr spectrumDet = inputWorkspace->getDetector(i);
if( spectrumDet->isMonitor() ) continue;
// If an indirect instrument, try getting Efixed from the geometry
if (emode==2)
{
efixed = getProperty("EFixed");
try {
Parameter_sptr par = pmap.get(spectrumDet.get(),"EFixed");
if (par)
{
efixed = par->value<double>();
}
else if( efixed == 0.0 )
{
continue;
}
} catch (std::runtime_error&) { /* Throws if a DetectorGroup, use single provided value */ }
}

const double efixed = m_EmodeProperties.getEFixed(spectrumDet);

// For inelastic scattering the simple relationship q=4*pi*sinTheta/lambda does not hold. In order to
// be completely general we must calculate the momentum transfer by calculating the incident and final
Expand Down Expand Up @@ -233,7 +188,7 @@ void SofQW::exec()
ef = efixed - deltaE;
if (ef<0)
{
std::string mess = "Energy transfer requested in Indirect mode exceeds incident energy.\n Found for det ID: "+boost::lexical_cast<std::string>(idet)+
std::string mess = "Energy transfer requested in Direct mode exceeds incident energy.\n Found for det ID: "+boost::lexical_cast<std::string>(idet)+
" bin No "+boost::lexical_cast<std::string>(j)+" with Ei="+boost::lexical_cast<std::string>(efixed)+" and energy transfer: "+
boost::lexical_cast<std::string>(deltaE);
throw std::runtime_error(mess);
Expand All @@ -243,6 +198,14 @@ void SofQW::exec()
{
ei = efixed + deltaE;
ef = efixed;
if (ef<0)
{
std::string mess = "Incident energy of a neutron is negative. Are you trying to process Direct data in Indirect mode?\n Found for det ID: "+boost::lexical_cast<std::string>(idet)+
" bin No "+boost::lexical_cast<std::string>(j)+" with efied="+boost::lexical_cast<std::string>(efixed)+" and energy transfer: "+
boost::lexical_cast<std::string>(deltaE);
throw std::runtime_error(mess);
}

}
const V3D ki = beamDir*sqrt(energyToK*ei);
const V3D kf = scatterDir*(sqrt(energyToK*(ef)));
Expand Down

0 comments on commit c73febe

Please sign in to comment.