-
Notifications
You must be signed in to change notification settings - Fork 122
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a simple UnitConversion class. Refs #5624
Allows conversion between units using a single call.
- Loading branch information
1 parent
d982703
commit 078cb1f
Showing
4 changed files
with
283 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
Code/Mantid/Framework/Kernel/inc/MantidKernel/UnitConversion.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#ifndef MANTID_KERNEL_UNITCONVERSION_H_ | ||
#define MANTID_KERNEL_UNITCONVERSION_H_ | ||
/** | ||
Copyright © 2012 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> | ||
*/ | ||
#include "MantidKernel/DeltaEMode.h" | ||
#include "MantidKernel/DllConfig.h" | ||
#include <string> | ||
|
||
namespace Mantid | ||
{ | ||
namespace Kernel | ||
{ | ||
//------------------------------------------------------------------------- | ||
// Forward declations | ||
//------------------------------------------------------------------------- | ||
class Unit; | ||
|
||
/** | ||
* A set of static helper methods to perform conversions between units | ||
*/ | ||
class MANTID_KERNEL_DLL UnitConversion | ||
{ | ||
public: | ||
/// Convert a single value between the given units (as strings) | ||
static double 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); | ||
/// Convert a single value between the given units | ||
static double 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); | ||
|
||
private: | ||
/// Perform a quick conversion | ||
static double convertQuickly(const double srcValue, const double factor, const double power); | ||
/// Convert through TOF | ||
static double 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); | ||
}; | ||
|
||
|
||
} // namespace Kernel | ||
} // namespace Mantid | ||
|
||
#endif /* MANTID_KERNEL_UNITCONVERSION_H_ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
#ifndef MANTID_KERNEL_UNITCONVERTERTEST_H_ | ||
#define MANTID_KERNEL_UNITCONVERTERTEST_H_ | ||
|
||
#include <cxxtest/TestSuite.h> | ||
#include "MantidKernel/UnitConversion.h" | ||
#include "MantidKernel/Exception.h" | ||
#include "MantidKernel/PhysicalConstants.h" | ||
|
||
#include <iomanip> | ||
|
||
using Mantid::Kernel::UnitConversion; | ||
|
||
class UnitConversionTest : public CxxTest::TestSuite | ||
{ | ||
public: | ||
// This pair of boilerplate methods prevent the suite being created statically | ||
// This means the constructor isn't called when running other tests | ||
static UnitConversionTest *createSuite() { return new UnitConversionTest(); } | ||
static void destroySuite( UnitConversionTest *suite ) { delete suite; } | ||
|
||
void test_Run_Throws_When_Src_Unit_Is_Unknown() | ||
{ | ||
using namespace Mantid::Kernel::Exception; | ||
using Mantid::Kernel::DeltaEMode; | ||
TS_ASSERT_THROWS(UnitConversion::run("zxzxz", "Wavelength", 0.0,0.0,0.0,0.0,DeltaEMode::Elastic,0.0), NotFoundError); | ||
} | ||
|
||
void test_Run_Throws_When_Dest_Unit_Is_Unknown() | ||
{ | ||
using namespace Mantid::Kernel::Exception; | ||
using Mantid::Kernel::DeltaEMode; | ||
TS_ASSERT_THROWS(UnitConversion::run("Wavelength", "xszfsdf", 0.0,0.0,0.0,0.0,DeltaEMode::Elastic,0.0), NotFoundError); | ||
} | ||
|
||
void test_Run_Gives_Throws_With_Unknown_EMode_When_Applicable() | ||
{ | ||
// Important to test as if another mode is added but this class is not updated to deal with it | ||
using namespace Mantid::Kernel::Exception; | ||
using Mantid::Kernel::DeltaEMode; | ||
const unsigned int mode = 1000; | ||
TS_ASSERT_THROWS(UnitConversion::run("Wavelength", "MomentumTransfer", 0.0,0.0,0.0,0.0,(DeltaEMode::Type)mode,0.0), std::invalid_argument); | ||
} | ||
|
||
void test_Run_Gives_Correct_Value_For_Units_That_Can_Be_Converted_By_Simply_Factor_And_Geometry_Is_Ignored() | ||
{ | ||
using Mantid::Kernel::DeltaEMode; | ||
|
||
const std::string & srcUnit = "Wavelength"; | ||
const double srcValue(1.5); // In angstroms | ||
|
||
const std::string & destUnit = "Momentum"; | ||
const double dummy(0.0); | ||
const DeltaEMode::Type dummyMode(DeltaEMode::Indirect); | ||
const double expected(2.0*M_PI/srcValue); | ||
|
||
double result(-1.0); | ||
TS_ASSERT_THROWS_NOTHING(result = UnitConversion::run(srcUnit, destUnit, srcValue, dummy, dummy, dummy, dummyMode,dummy)); | ||
TS_ASSERT_DELTA(result, expected, 1e-12); | ||
} | ||
|
||
void test_Run_Gives_Correct_Value_For_Units_That_Go_Through_TOF() | ||
{ | ||
using Mantid::Kernel::DeltaEMode; | ||
|
||
const std::string & srcUnit = "Wavelength"; | ||
const double srcValue(1.5); // In angstroms | ||
const std::string & destUnit = "MomentumTransfer"; | ||
|
||
const double l1(10.0), l2(1.1), twoTheta(10.0*M_PI/180.0), efixed(12.0); | ||
const DeltaEMode::Type emode = DeltaEMode::Direct; | ||
|
||
const double expected(0.437943919458); | ||
double result(-1.0); | ||
TS_ASSERT_THROWS_NOTHING(result = UnitConversion::run(srcUnit, destUnit, srcValue, l1, l2, twoTheta, emode,efixed)); | ||
TS_ASSERT_DELTA(result, expected, 1e-12); | ||
} | ||
}; | ||
|
||
|
||
#endif /* MANTID_KERNEL_UNITCONVERTERTEST_H_ */ |