Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "MantidKernel/UnitConversion.h"
#include "MantidKernel/Unit.h"
#include "MantidKernel/UnitFactory.h"
#include <boost/lexical_cast.hpp>
#include <cmath>
namespace Mantid
{
namespace Kernel
{
/**
* Convert a single value between the given units (as strings)
* @param src :: The starting unit
* @param dest :: The destination unit
* @param srcValue :: The value to convert
* @param l1 :: The source-sample distance (in metres)
* @param l2 :: The sample-detector distance (in metres)
* @param twoTheta :: The scattering angle (in radians)
* @param emode :: The energy mode enumeration
* @param efixed :: Value of fixed energy: EI (emode=1) or EF (emode=2) (in meV)
* @return The value converted to the destination unit
*/
double UnitConversion::run(const std::string & src, const std::string & dest,
const double srcValue,
const double l1, const double l2,
const double twoTheta, const DeltaEMode::Type emode, const double efixed)
{
Unit_const_sptr srcUnit = UnitFactory::Instance().create(src);
Unit_const_sptr destUnit = UnitFactory::Instance().create(dest);
return UnitConversion::run(*srcUnit, *destUnit, srcValue, l1, l2, twoTheta, emode, efixed);
}
/**
* Convert a single value between the given units (overload for Unit objects)
* @param srcUnit :: The starting unit
* @param destUnit :: The destination unit
* @param srcValue :: The value to convert
* @param l1 :: The source-sample distance (in metres)
* @param l2 :: The sample-detector distance (in metres)
* @param twoTheta :: The scattering angle (in radians)
* @param emode :: The energy mode enumeration
* @param efixed :: Value of fixed energy: EI (emode=1) or EF (emode=2) (in meV)
* @return The value converted to the destination unit
*/
double UnitConversion::run(const Unit & srcUnit, const Unit & destUnit,
const double srcValue,
const double l1, const double l2,
const double twoTheta, const DeltaEMode::Type emode, const double efixed)
{
double factor(0.0), power(0.0);
if(srcUnit.quickConversion(destUnit, factor, power))
{
return convertQuickly(srcValue, factor, power);
}
else
{
return convertViaTOF(srcUnit, destUnit, srcValue, l1, l2, twoTheta, emode, efixed);
}
}
//---------------------------------------------------------------------------------------------
// Private methods
//---------------------------------------------------------------------------------------------
/**
* Perform a quick conversion by raising the value to a power & multiplying by the factor
* @param srcValue :: The value to convert
* @param factor :: A multiplicative constant
* @param power :: Raise the src value to this power
* @return The converted unit
*/
double UnitConversion::convertQuickly(const double srcValue, const double factor,
const double power)
{
return factor *std::pow(srcValue, power);
}
/**
* @param srcUnit :: The starting unit
* @param destUnit :: The destination unit
* @param srcValue :: The value to convert
* @param l1 :: The source-sample distance (in metres)
* @param l2 :: The sample-detector distance (in metres)
* @param twoTheta :: The scattering angle (in radians)
* @param emode :: The energy mode enumeration
* @param efixed :: Value of fixed energy: EI (emode=1) or EF (emode=2) (in meV)
* @return The value converted to the destination unit
*/
double UnitConversion::convertViaTOF(const Unit & srcUnit, const Unit & destUnit,
const double srcValue,
const double l1, const double l2,
const double twoTheta, const DeltaEMode::Type emode,
const double efixed)
{
// Translate the emode to the int formulation
int emodeAsInt(0);
switch(emode)
{
case DeltaEMode::Elastic: emodeAsInt = 0;
break;
case DeltaEMode::Direct: emodeAsInt = 1;
break;
case DeltaEMode::Indirect: emodeAsInt = 2;
break;
default: throw std::invalid_argument("UnitConversion::convertViaTOF - Unknown emode " + boost::lexical_cast<std::string>(emode));
};
const double unused(0.0);
// The unit API requires a non-const input unit but it doesn't make sense for this method to accept a non-const value
Unit & nonConstSrc = const_cast<Unit&>(srcUnit);
const double tof = nonConstSrc.convertSingleToTOF(srcValue, l1, l2, twoTheta, emodeAsInt, efixed, unused);
Unit & nonConstDest = const_cast<Unit&>(destUnit);
return nonConstDest.convertSingleFromTOF(tof, l1, l2, twoTheta, emodeAsInt, efixed, unused);
}
} // namespace Kernel
} // namespace Mantid