diff --git a/Framework/Algorithms/inc/MantidAlgorithms/PDCalibration.h b/Framework/Algorithms/inc/MantidAlgorithms/PDCalibration.h index 6118c04412e14b10b7edaa34ea445a5d8faee5fb..f88dcfb91b289524a8390c62bac07983e489e09c 100644 --- a/Framework/Algorithms/inc/MantidAlgorithms/PDCalibration.h +++ b/Framework/Algorithms/inc/MantidAlgorithms/PDCalibration.h @@ -48,6 +48,7 @@ private: class FittedPeaks; // forward declare of private inner class void init() override; + std::map<std::string, std::string> validateInputs() override; void exec() override; API::MatrixWorkspace_sptr loadAndBin(); API::MatrixWorkspace_sptr rebin(API::MatrixWorkspace_sptr wksp); @@ -69,9 +70,13 @@ private: std::vector<double> m_peaksInDspacing; std::string calParams; std::map<detid_t, size_t> m_detidToRow; - double m_tofMin; - double m_tofMax; - bool m_hasDasIds; + double m_tofMin{0.}; + double m_tofMax{0.}; + double m_tzeroMin{0.}; + double m_tzeroMax{0.}; + double m_difaMin{0.}; + double m_difaMax{0.}; + bool m_hasDasIds{false}; }; } // namespace Algorithms diff --git a/Framework/Algorithms/src/PDCalibration.cpp b/Framework/Algorithms/src/PDCalibration.cpp index 22c16709e077d05d02039bc6c638d025c3af4a48..8bbcac1ecdd4154770147dd7bc345b91f705d0f5 100644 --- a/Framework/Algorithms/src/PDCalibration.cpp +++ b/Framework/Algorithms/src/PDCalibration.cpp @@ -12,11 +12,13 @@ #include "MantidKernel/ArrayProperty.h" #include "MantidKernel/BoundedValidator.h" #include "MantidKernel/CompositeValidator.h" +#include "MantidKernel/Diffraction.h" #include "MantidKernel/ListValidator.h" #include "MantidKernel/MandatoryValidator.h" #include "MantidKernel/RebinParamsValidator.h" #include "MantidKernel/make_unique.h" #include <cassert> +#include <limits> namespace Mantid { namespace Algorithms { @@ -43,6 +45,7 @@ DECLARE_ALGORITHM(PDCalibration) namespace { // anonymous const auto isNonZero = [](const double value) { return value != 0.; }; +const double CHISQ_BAD = 1.e9; // hopefully much worse than possible } /// private inner class @@ -115,7 +118,7 @@ public: //---------------------------------------------------------------------------------------------- /** Constructor */ -PDCalibration::PDCalibration() : m_tofMin(0), m_tofMax(0), m_hasDasIds(false) {} +PDCalibration::PDCalibration() {} //---------------------------------------------------------------------------------------------- /** Destructor @@ -234,6 +237,12 @@ void PDCalibration::init() { boost::make_shared<StringListValidator>(modes), "Select calibration parameters to fit."); + declareProperty( + Kernel::make_unique<ArrayProperty<double>>("TZEROrange"), + "Range for allowable TZERO from calibration (default is all)"); + declareProperty(Kernel::make_unique<ArrayProperty<double>>("DIFArange"), + "Range for allowable DIFA from calibration (default is all)"); + declareProperty(Kernel::make_unique<WorkspaceProperty<API::ITableWorkspace>>( "OutputCalibrationTable", "", Direction::Output), "An output workspace containing the Calibration Table"); @@ -264,6 +273,30 @@ void PDCalibration::init() { setPropertyGroup("StartFromObservedPeakCentre", findPeaksGroup); } +std::map<std::string, std::string> PDCalibration::validateInputs() { + std::map<std::string, std::string> messages; + + vector<double> tzeroRange = getProperty("TZEROrange"); + if (!tzeroRange.empty()) { + if (tzeroRange.size() != 2) { + messages["TZEROrange"] = "Require two values [min,max]"; + } else if (tzeroRange[0] >= tzeroRange[1]) { + messages["TZEROrange"] = "min must be less than max"; + } + } + + vector<double> difaRange = getProperty("DIFArange"); + if (!difaRange.empty()) { + if (difaRange.size() != 2) { + messages["DIFArange"] = "Require two values [min,max]"; + } else if (difaRange[0] >= difaRange[1]) { + messages["DIFArange"] = "min must be less than max"; + } + } + + return messages; +} + //---------------------------------------------------------------------------------------------- /** Execute the algorithm. */ @@ -272,6 +305,38 @@ void PDCalibration::exec() { m_tofMin = tofBinningParams.front(); m_tofMax = tofBinningParams.back(); + vector<double> tzeroRange = getProperty("TZEROrange"); + if (tzeroRange.size() == 2) { + m_tzeroMin = tzeroRange[0]; + m_tzeroMax = tzeroRange[1]; + + std::stringstream msg; + msg << "Using tzero range of " << m_tzeroMin << " <= " + << "TZERO <= " << m_tzeroMax; + g_log.information(msg.str()); + } else { + g_log.information("Using all TZERO values"); + + m_tzeroMin = std::numeric_limits<double>::lowest(); + m_tzeroMax = std::numeric_limits<double>::max(); + } + + vector<double> difaRange = getProperty("DIFArange"); + if (difaRange.size() == 2) { + m_difaMin = difaRange[0]; + m_difaMax = difaRange[1]; + + std::stringstream msg; + msg << "Using difa range of " << m_difaMin << " <= " + << "DIFA <= " << m_difaMax; + g_log.information(msg.str()); + } else { + g_log.information("Using all DIFA values"); + + m_difaMin = std::numeric_limits<double>::lowest(); + m_difaMax = std::numeric_limits<double>::max(); + } + m_peaksInDspacing = getProperty("PeakPositions"); // Sort peak positions, requried for correct peak window calculations std::sort(m_peaksInDspacing.begin(), m_peaksInDspacing.end()); @@ -433,17 +498,16 @@ struct d_to_tof { void PDCalibration::fitDIFCtZeroDIFA(const std::vector<double> &d, const std::vector<double> &tof, double &difc, double &t0, double &difa) { - double sum = 0; - double sumX = 0; - double sumY = 0; - double sumX2 = 0; - double sumXY = 0; - double sumX2Y = 0; - double sumX3 = 0; - double sumX4 = 0; + double num_peaks = static_cast<double>(d.size()); + double sumX = 0.; + double sumY = 0.; + double sumX2 = 0.; + double sumXY = 0.; + double sumX2Y = 0.; + double sumX3 = 0.; + double sumX4 = 0.; for (size_t i = 0; i < d.size(); ++i) { - sum++; sumX2 += d[i] * d[i]; sumXY += d[i] * tof[i]; } @@ -451,7 +515,7 @@ void PDCalibration::fitDIFCtZeroDIFA(const std::vector<double> &d, // DIFC only double difc0 = sumXY / sumX2; // Get out early if only DIFC is needed. - if (calParams == "DIFC" || sum < 3) { + if (calParams == "DIFC" || num_peaks < 3) { difc = difc0; return; } @@ -464,10 +528,10 @@ void PDCalibration::fitDIFCtZeroDIFA(const std::vector<double> &d, double difc1 = 0; double tZero1 = 0; - double determinant = sum * sumX2 - sumX * sumX; + double determinant = num_peaks * sumX2 - sumX * sumX; if (determinant != 0) { - difc1 = (sum * sumXY - sumX * sumY) / determinant; - tZero1 = sumY / sum - difc1 * sumX / sum; + difc1 = (num_peaks * sumXY - sumX * sumY) / determinant; + tZero1 = sumY / num_peaks - difc1 * sumX / num_peaks; } // calculated chi squared for each fit @@ -482,13 +546,24 @@ void PDCalibration::fitDIFCtZeroDIFA(const std::vector<double> &d, temp = tZero1 + difc1 * d[i] - tof[i]; chisq1 += (temp * temp); } + // Get reduced chi-squared - chisq0 = chisq0 / (sum - 1); - chisq1 = chisq1 / (sum - 2); + chisq0 = chisq0 / (num_peaks - 1); + chisq1 = chisq1 / (num_peaks - 2); + + // check that the value is reasonable, only need to check minimum + // side since difa is not in play - shift to a higher minimum + // means something went wrong + if (m_tofMin < Kernel::Diffraction::calcTofMin(difc1, 0., tZero1, m_tofMin) || + difc1 <= 0. || tZero1 < m_tzeroMin || tZero1 > m_tzeroMax) { + difc1 = 0; + tZero1 = 0; + chisq1 = CHISQ_BAD; + } // Select difc, t0 depending on CalibrationParameters chosen and // number of peaks fitted. - if (calParams == "DIFC+TZERO" || sum == 3) { + if (calParams == "DIFC+TZERO" || num_peaks == 3) { // choose best one according to chi-squared if (chisq0 < chisq1) { difc = difc0; @@ -509,22 +584,22 @@ void PDCalibration::fitDIFCtZeroDIFA(const std::vector<double> &d, double tZero2 = 0; double difc2 = 0; double difa2 = 0; - determinant = sum * sumX2 * sumX4 + sumX * sumX3 * sumX2 + + determinant = num_peaks * sumX2 * sumX4 + sumX * sumX3 * sumX2 + sumX2 * sumX * sumX3 - sumX2 * sumX2 * sumX2 - - sumX * sumX * sumX4 - sum * sumX3 * sumX3; + sumX * sumX * sumX4 - num_peaks * sumX3 * sumX3; if (determinant != 0) { tZero2 = (sumY * sumX2 * sumX4 + sumX * sumX3 * sumX2Y + sumX2 * sumXY * sumX3 - sumX2 * sumX2 * sumX2Y - sumX * sumXY * sumX4 - sumY * sumX3 * sumX3) / determinant; - difc2 = - (sum * sumXY * sumX4 + sumY * sumX3 * sumX2 + sumX2 * sumX * sumX2Y - - sumX2 * sumXY * sumX2 - sumY * sumX * sumX4 - sum * sumX3 * sumX2Y) / - determinant; - difa2 = - (sum * sumX2 * sumX2Y + sumX * sumXY * sumX2 + sumY * sumX * sumX3 - - sumY * sumX2 * sumX2 - sumX * sumX * sumX2Y - sum * sumXY * sumX3) / - determinant; + difc2 = (num_peaks * sumXY * sumX4 + sumY * sumX3 * sumX2 + + sumX2 * sumX * sumX2Y - sumX2 * sumXY * sumX2 - + sumY * sumX * sumX4 - num_peaks * sumX3 * sumX2Y) / + determinant; + difa2 = (num_peaks * sumX2 * sumX2Y + sumX * sumXY * sumX2 + + sumY * sumX * sumX3 - sumY * sumX2 * sumX2 - sumX * sumX * sumX2Y - + num_peaks * sumXY * sumX3) / + determinant; } // calculated reduced chi squared for each fit @@ -533,15 +608,33 @@ void PDCalibration::fitDIFCtZeroDIFA(const std::vector<double> &d, double temp = tZero2 + difc2 * d[i] + difa2 * d[i] * d[i] - tof[i]; chisq2 += (temp * temp); } - chisq2 = chisq2 / (sum - 3); + chisq2 = chisq2 / (num_peaks - 3); + + // check that the value is reasonable, only need to check minimum + // side since difa is not in play - shift to a higher minimum + // or a lower maximum means something went wrong + if (m_tofMin < + Kernel::Diffraction::calcTofMin(difc2, difa2, tZero2, m_tofMin) || + m_tofMax < + Kernel::Diffraction::calcTofMax(difc2, difa2, tZero2, m_tofMax) || + difc2 <= 0. || tZero2 < m_tzeroMin || tZero2 > m_tzeroMax || + difa2 < m_difaMin || difa2 > m_difaMax) { + tZero2 = 0; + difc2 = 0; + difa2 = 0; + chisq2 = CHISQ_BAD; + } // Select difc, t0 and difa depending on CalibrationParameters chosen and // number of peaks fitted. if ((chisq0 < chisq1) && (chisq0 < chisq2)) { difc = difc0; + t0 = 0.; + difa = 0.; } else if ((chisq1 < chisq0) && (chisq1 < chisq2)) { difc = difc1; t0 = tZero1; + difa = 0.; } else { difc = difc2; t0 = tZero2; @@ -620,19 +713,10 @@ void PDCalibration::setCalibrationValues(const detid_t detid, const double difc, vector<double> PDCalibration::getTOFminmax(const double difc, const double difa, const double tzero) { vector<double> tofminmax(2); - if (difa == 0) { - tofminmax[0] = 0.; - tofminmax[1] = DBL_MAX; - } else { - double tofExtrema = tzero - difc * difc / (4 * difa); - if (difa < 0) { - tofminmax[0] = 0.; - tofminmax[1] = tofExtrema; - } else { - tofminmax[0] = std::max(0., tofExtrema); - tofminmax[1] = DBL_MAX; - } - } + + tofminmax[0] = Kernel::Diffraction::calcTofMin(difc, difa, tzero, m_tofMin); + tofminmax[1] = Kernel::Diffraction::calcTofMax(difc, difa, tzero, m_tofMax); + return tofminmax; } MatrixWorkspace_sptr PDCalibration::load(const std::string filename) { diff --git a/Framework/DataHandling/src/LoadDiffCal.cpp b/Framework/DataHandling/src/LoadDiffCal.cpp index b4791560c59fffa19caa3a80717c57aff0979276..1ad33c13f55cce2d3d5948b2dd76f27cd3258066 100644 --- a/Framework/DataHandling/src/LoadDiffCal.cpp +++ b/Framework/DataHandling/src/LoadDiffCal.cpp @@ -11,6 +11,7 @@ #include "MantidDataObjects/MaskWorkspace.h" #include "MantidDataObjects/TableWorkspace.h" #include "MantidDataObjects/Workspace2D.h" +#include "MantidKernel/Diffraction.h" #include <cmath> #include <H5Cpp.h> @@ -230,37 +231,6 @@ void LoadDiffCal::makeMaskWorkspace(const std::vector<int32_t> &detids, setMaskWSProperty(this, m_workspaceName, wksp); } -namespace { // anonymous namespace - -double calcTofMin(const double difc, const double difa, const double tzero, - const double tofmin) { - if (difa == 0.) { - if (tzero != 0.) { - // check for negative d-spacing - return std::max<double>(-1. * tzero, tofmin); - } - } else if (difa > 0) { - // check for imaginary part in quadratic equation - return std::max<double>(tzero - .25 * difc * difc / difa, tofmin); - } - - // everything else is fine so just return supplied tofmin - return tofmin; -} - -double calcTofMax(const double difc, const double difa, const double tzero, - const double tofmax) { - if (difa < 0.) { - // check for imaginary part in quadratic equation - return std::min<double>(tzero - .25 * difc * difc / difa, tofmax); - } - - // everything else is fine so just return supplied tofmax - return tofmax; -} - -} // end of anonymous namespace - void LoadDiffCal::makeCalWorkspace(const std::vector<int32_t> &detids, const std::vector<double> &difc, const std::vector<double> &difa, @@ -315,14 +285,16 @@ void LoadDiffCal::makeCalWorkspace(const std::vector<int32_t> &detids, newrow << offsets[i]; // calculate tof range for information - const double tofMinRow = calcTofMin(difc[i], difa[i], tzero[i], tofMin); + const double tofMinRow = + Kernel::Diffraction::calcTofMin(difc[i], difa[i], tzero[i], tofMin); std::stringstream msg; if (tofMinRow != tofMin) { msg << "TofMin shifted from " << tofMin << " to " << tofMinRow << " "; } newrow << tofMinRow; if (useTofMax) { - const double tofMaxRow = calcTofMax(difc[i], difa[i], tzero[i], tofMax); + const double tofMaxRow = + Kernel::Diffraction::calcTofMax(difc[i], difa[i], tzero[i], tofMax); newrow << tofMaxRow; if (tofMaxRow != tofMax) { diff --git a/Framework/Kernel/CMakeLists.txt b/Framework/Kernel/CMakeLists.txt index 780e0a0a8b6a917f8c0c8eadc01468045fdebe32..23b9ee22f5006e6f3807a18ac2f84d51bf2c1247 100644 --- a/Framework/Kernel/CMakeLists.txt +++ b/Framework/Kernel/CMakeLists.txt @@ -2,7 +2,7 @@ set ( SRC_FILES src/ANN_complete.cpp src/ArrayBoundedValidator.cpp src/ArrayLengthValidator.cpp - src/ArrayOrderedPairsValidator.cpp + src/ArrayOrderedPairsValidator.cpp src/ArrayProperty.cpp src/Atom.cpp src/BinFinder.cpp @@ -18,6 +18,7 @@ set ( SRC_FILES src/DateTimeValidator.cpp src/DateValidator.cpp src/DeltaEMode.cpp + src/Diffraction.cpp src/DirectoryValidator.cpp src/DiskBuffer.cpp src/DllOpen.cpp @@ -84,8 +85,8 @@ set ( SRC_FILES src/PropertyManager.cpp src/PropertyManagerDataService.cpp src/PropertyManagerOwner.cpp - src/PropertyManagerProperty.cpp - src/PropertyNexus.cpp + src/PropertyManagerProperty.cpp + src/PropertyNexus.cpp src/PropertyWithValue.cpp src/ProxyInfo.cpp src/PseudoRandomNumberGenerator.cpp @@ -166,6 +167,7 @@ set ( INC_FILES inc/MantidKernel/DateTimeValidator.h inc/MantidKernel/DateValidator.h inc/MantidKernel/DeltaEMode.h + inc/MantidKernel/Diffraction.h inc/MantidKernel/DirectoryValidator.h inc/MantidKernel/DiskBuffer.h inc/MantidKernel/DllConfig.h @@ -334,6 +336,7 @@ set ( TEST_FILES DateTimeValidatorTest.h DateValidatorTest.h DeltaEModeTest.h + DiffractionTest.h DirectoryValidatorTest.h DiskBufferISaveableTest.h DiskBufferTest.h diff --git a/Framework/Kernel/inc/MantidKernel/Diffraction.h b/Framework/Kernel/inc/MantidKernel/Diffraction.h new file mode 100644 index 0000000000000000000000000000000000000000..1189b518adbc95b824b14f72642ae34105db05ba --- /dev/null +++ b/Framework/Kernel/inc/MantidKernel/Diffraction.h @@ -0,0 +1,44 @@ +#ifndef MANTID_KERNEL_DIFFRACTION_H_ +#define MANTID_KERNEL_DIFFRACTION_H_ + +#include "MantidKernel/DllConfig.h" + +namespace Mantid { +namespace Kernel { +namespace Diffraction { + +/** Diffraction : Collection of functions useful in diffraction scattering + + Copyright © 2017 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge + National Laboratory & European Spallation Source + + 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://github.com/mantidproject/mantid> + Code Documentation is available at: <http://doxygen.mantidproject.org> +*/ + +MANTID_KERNEL_DLL double calcTofMin(const double difc, const double difa, + const double tzero, + const double tofmin = 0.); + +MANTID_KERNEL_DLL double calcTofMax(const double difc, const double difa, + const double tzero, const double tofmax); +} // Diffraction +} // namespace Kernel +} // namespace Mantid + +#endif /* MANTID_KERNEL_DIFFRACTION_H_ */ diff --git a/Framework/Kernel/src/Diffraction.cpp b/Framework/Kernel/src/Diffraction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..db586c6c7c3a9f533fc26fa6df313e344c7e0303 --- /dev/null +++ b/Framework/Kernel/src/Diffraction.cpp @@ -0,0 +1,46 @@ +#include "MantidKernel/Diffraction.h" +#include <algorithm> + +namespace Mantid { +namespace Kernel { +namespace Diffraction { + +double calcTofMin(const double difc, const double difa, const double tzero, + const double tofmin) { + if (difa == 0.) { + if (tzero != 0.) { + // check for negative d-spacing + return std::max<double>(tzero, tofmin); + } + } else if (difa > 0.) { + // check for imaginary part in quadratic equation + return std::max<double>(tzero - .25 * difc * difc / difa, tofmin); + } + + // everything else is fine so just return supplied tofmin + return tofmin; +} + +/** + * Returns the maximum TOF that can be used or tofmax. Whichever is smaller. In + * the case when this is a negative number, just return 0. + */ +double calcTofMax(const double difc, const double difa, const double tzero, + const double tofmax) { + if (difa < 0.) { + // check for imaginary part in quadratic equation + if (tzero > 0.) { + // rather than calling abs multiply difa by -1 + return std::min<double>(tzero + .25 * difc * difc / difa, tofmax); + } else { + return 0.; + } + } + + // everything else is fine so just return supplied tofmax + return tofmax; +} + +} // namespace Diffraction +} // namespace Kernel +} // namespace Mantid diff --git a/Framework/Kernel/test/DiffractionTest.h b/Framework/Kernel/test/DiffractionTest.h new file mode 100644 index 0000000000000000000000000000000000000000..85b9e7c9673cbd7cf59ea1e4eeaf93d3d45024f2 --- /dev/null +++ b/Framework/Kernel/test/DiffractionTest.h @@ -0,0 +1,76 @@ +#ifndef MANTID_KERNEL_DIFFRACTIONTEST_H_ +#define MANTID_KERNEL_DIFFRACTIONTEST_H_ + +#include <cxxtest/TestSuite.h> +#include <limits> + +#include "MantidKernel/Diffraction.h" + +using Mantid::Kernel::Diffraction::calcTofMin; +using Mantid::Kernel::Diffraction::calcTofMax; + +namespace { // anonymous +const double DIFC = 2100.; // sensible value +const double TZERO = 10.; +// intentionally goofy - reduces tzero by 1 +const double DIFA1 = .25 * DIFC * DIFC; +// intentionally goofy - reduces tzero by .01 +const double DIFA2 = 25 * DIFC * DIFC; +// intentionally goofy +const double DIFA3 = -.25 * DIFC * DIFC; +} + +class DiffractionTest : 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 DiffractionTest *createSuite() { return new DiffractionTest(); } + static void destroySuite(DiffractionTest *suite) { delete suite; } + + void test_calcTofMin() { + const double TMIN = 300.; + + // just difc + TS_ASSERT_EQUALS(calcTofMin(DIFC, 0., 0.), 0.); + TS_ASSERT_EQUALS(calcTofMin(DIFC, 0., 0., TMIN), TMIN); + // difc + tzero + TS_ASSERT_EQUALS(calcTofMin(DIFC, 0., TZERO, 0.), TZERO); + TS_ASSERT_EQUALS(calcTofMin(DIFC, 0., TZERO, TMIN), TMIN); + + // difc + difa + tzero + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA1, 0., 0.), 0.); + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA1, 0., TMIN), TMIN); + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA1, TZERO, 0.), TZERO - 1.); + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA1, TZERO, TMIN), TMIN); + + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA2, 0., 0.), 0.); + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA2, 0., TMIN), TMIN); + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA2, TZERO, 0.), TZERO - .01); + TS_ASSERT_EQUALS(calcTofMin(DIFC, DIFA2, TZERO, TMIN), TMIN); + } + + void test_calcTofMax() { + const double TMAX = 16666.7; + const double TSUPERMAX = std::numeric_limits<double>::max(); + + // just difc + TS_ASSERT_EQUALS(calcTofMax(DIFC, 0., 0., TMAX), TMAX); + TS_ASSERT_EQUALS(calcTofMax(DIFC, 0., 0., TSUPERMAX), TSUPERMAX); + // difc + tzero + TS_ASSERT_EQUALS(calcTofMax(DIFC, 0., TZERO, TMAX), TMAX); + TS_ASSERT_EQUALS(calcTofMax(DIFC, 0., TZERO, TSUPERMAX), TSUPERMAX); + + // difc + difa + tzero + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA1, 0., TMAX), TMAX); + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA1, 0., TSUPERMAX), TSUPERMAX); + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA1, TZERO, TMAX), TMAX); + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA1, TZERO, TSUPERMAX), TSUPERMAX); + + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA3, 0., TMAX), 0.); + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA3, 0., TSUPERMAX), 0.); + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA3, TZERO, TMAX), TZERO - 1.); + TS_ASSERT_EQUALS(calcTofMax(DIFC, DIFA3, TZERO, TSUPERMAX), TZERO - 1.); + } +}; + +#endif /* MANTID_KERNEL_DIFFRACTIONTEST_H_ */ diff --git a/docs/source/release/v3.10.0/diffraction.rst b/docs/source/release/v3.10.0/diffraction.rst index a5405a1079f88d5662a516ab77b9bbe5819753f0..3b718959d2b34d0b0b0aae0ba5c3ca5cce39d5b4 100644 --- a/docs/source/release/v3.10.0/diffraction.rst +++ b/docs/source/release/v3.10.0/diffraction.rst @@ -21,6 +21,7 @@ Powder Diffraction - Bugfix in :ref:`SNAPReduce <algm-SNAPReduce>` with loading previous normalizations - :ref:`SNSPowderReduction <algm-SNSPowderReduction>` now supports splitters in format of ``MatrixWorkspace`` and general ``TableWorkspace``. - A new NOMAD instrument definition file with corrected values. +- :ref:`algm-PDCalibration <algm-PDCalibration>` is better at giving out physically meaningful results. It will no longer create calibrations that will convert time-of-flight to negative or imaginary d-spacing. Single Crystal Diffraction --------------------------