#ifndef ALGORITHMS_TEST_REFLECTOMETRYREDUCTIONONE2TEST_H_ #define ALGORITHMS_TEST_REFLECTOMETRYREDUCTIONONE2TEST_H_ #include <cxxtest/TestSuite.h> #include "MantidAlgorithms/ReflectometryReductionOne2.h" #include "MantidAPI/AlgorithmManager.h" #include "MantidAPI/Axis.h" #include "MantidAPI/FrameworkManager.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidGeometry/Instrument.h" #include "MantidGeometry/Instrument/ReferenceFrame.h" #include "MantidHistogramData/HistogramY.h" #include "MantidTestHelpers/WorkspaceCreationHelper.h" #include <algorithm> using namespace Mantid::API; using namespace Mantid::Algorithms; using namespace WorkspaceCreationHelper; class ReflectometryReductionOne2Test : public CxxTest::TestSuite { private: MatrixWorkspace_sptr m_singleDetectorWS; MatrixWorkspace_sptr m_multiDetectorWS; MatrixWorkspace_sptr m_transmissionWS; public: // This pair of boilerplate methods prevent the suite being created statically // This means the constructor isn't called when running other tests static ReflectometryReductionOne2Test *createSuite() { return new ReflectometryReductionOne2Test(); } static void destroySuite(ReflectometryReductionOne2Test *suite) { delete suite; } ReflectometryReductionOne2Test() { FrameworkManager::Instance(); // A single detector ws m_singleDetectorWS = create2DWorkspaceWithReflectometryInstrument(0); // A multi detector ws m_multiDetectorWS = create2DWorkspaceWithReflectometryInstrumentMultiDetector(0, 0.1); // A transmission ws with different spectrum numbers to the run m_transmissionWS = create2DWorkspaceWithReflectometryInstrumentMultiDetector(0, 0.1); m_transmissionWS->getSpectrum(0).setSpectrumNo(2); m_transmissionWS->getSpectrum(1).setSpectrumNo(3); m_transmissionWS->getSpectrum(2).setSpectrumNo(4); m_transmissionWS->getSpectrum(3).setSpectrumNo(5); // Set different values in each spectrum so that we can check the correct // spectra were used for the transmission correction using namespace Mantid::HistogramData; m_transmissionWS->setCounts(0, Counts(m_transmissionWS->y(0).size(), 10)); m_transmissionWS->setCounts(1, Counts(m_transmissionWS->y(1).size(), 20)); m_transmissionWS->setCounts(2, Counts(m_transmissionWS->y(2).size(), 30)); m_transmissionWS->setCounts(3, Counts(m_transmissionWS->y(3).size(), 40)); } void test_IvsLam() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT(outLam->x(0)[0] >= 1.5); TS_ASSERT(outLam->x(0)[7] <= 15.0); TS_ASSERT_DELTA(outLam->y(0)[0], 2.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 2.0000, 0.0001); } void test_IvsLam_processing_instructions_1to2() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 1+2 ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1+2"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT(outLam->x(0)[0] >= 1.5); TS_ASSERT(outLam->x(0)[7] <= 15.0); // Y counts, should be 2.0000 * 2 TS_ASSERT_DELTA(outLam->y(0)[0], 4.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 4.0000, 0.0001); } void test_IvsLam_processing_instructions_1to3() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 1-3 ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1-3"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT(outLam->x(0)[0] >= 1.5); TS_ASSERT(outLam->x(0)[7] <= 15.0); // Y counts, should be 2.0000 * 3 TS_ASSERT_DELTA(outLam->y(0)[0], 6.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 6.0000, 0.0001); } void test_IvsLam_multiple_detector_groups() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 2,1+3 (two separate groups) ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "2,1+3"); // Run the algorithm. There should be 2 output histograms, one for each // input group. Note that the group order is swapped from the input order // because they are sorted by the first spectrum number in the group, // i.e. as if the input was "1+3,2" MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 14, 2); TS_ASSERT(outLam->x(0)[0] >= 1.5); TS_ASSERT(outLam->x(0)[7] <= 15.0); TS_ASSERT(outLam->x(1)[0] >= 1.5); TS_ASSERT(outLam->x(1)[7] <= 15.0); // Y counts, should be 2.0000 * 2 for first group, 2.0000 * 1 for second. TS_ASSERT_DELTA(outLam->y(0)[0], 4.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 4.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(1)[0], 2.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(1)[7], 2.0000, 0.0001); } void test_bad_processing_instructions() { // Processing instructions : 5+6 ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "5+6"); // Must throw as spectrum 2 is not defined TS_ASSERT_THROWS_ANYTHING(alg.execute()); } void test_sum_in_lambda() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // SummationType : SumInLambda (same as default) ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1"); alg.setProperty("SummationType", "SumInLambda"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT(outLam->x(0)[0] >= 1.5); TS_ASSERT(outLam->x(0)[7] <= 15.0); TS_ASSERT_DELTA(outLam->y(0)[0], 2.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 2.0000, 0.0001); } void test_sum_in_lambda_with_bad_reduction_type() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // SummationType : SumInLambda (same as default) // ReductionType : DivergentBeam (invalid) ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1"); alg.setProperty("SummationType", "SumInLambda"); alg.setProperty("ReductionType", "DivergentBeam"); TS_ASSERT_THROWS_ANYTHING(alg.execute()); } void test_IvsLam_no_monitors() { // Test IvsLam workspace // No monitor normalization // Direct beam normalization: 2-3 // No transmission correction // Processing instructions : 1 // I0MonitorIndex: 0 // MonitorBackgroundWavelengthMin : Not given // MonitorBackgroundWavelengthMax : Not given ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1"); alg.setProperty("I0MonitorIndex", "0"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT(outLam->x(0)[0] >= 1.5); TS_ASSERT(outLam->x(0)[7] <= 15.0); // No monitors considered because MonitorBackgroundWavelengthMin // and MonitorBackgroundWavelengthMax were not set // Y counts must be 2.0000 TS_ASSERT_DELTA(outLam->y(0)[0], 2.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 2.0000, 0.0001); } void test_IvsLam_monitor_normalization() { // Test IvsLam workspace // Monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 2 // I0MonitorIndex: 0 // MonitorBackgroundWavelengthMin : 0.5 // MonitorBackgroundWavelengthMax : 3.0 // Normalize by integrated monitors : No // Modify counts in monitor (only for this test) // Modify counts only for range that will be fitted auto inputWS = m_multiDetectorWS; auto &Y = m_multiDetectorWS->mutableY(0); std::fill(Y.begin(), Y.begin() + 2, 1.0); ReflectometryReductionOne2 alg; setupAlgorithmMonitorCorrection(alg, 0.0, 15.0, "2", inputWS, false); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 10); TS_ASSERT(outLam->x(0)[0] >= 0.0); TS_ASSERT(outLam->x(0)[7] <= 15.0); // Expected values are 2.4996 = 3.15301 (detectors) / 1.26139 (monitors) TS_ASSERT_DELTA(outLam->y(0)[2], 2.4996, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[4], 2.4996, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 2.4996, 0.0001); } void test_IvsLam_integrated_monitors() { // Test IvsLam workspace // Monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 1 // I0MonitorIndex: 0 // MonitorBackgroundWavelengthMin : 0.5 // MonitorBackgroundWavelengthMax : 3.0 // Normalize by integrated monitors : Yes // Modify counts in monitor (only for this test) // Modify counts only for range that will be fitted auto inputWS = m_multiDetectorWS; auto &Y = inputWS->mutableY(0); std::fill(Y.begin(), Y.begin() + 2, 1.0); ReflectometryReductionOne2 alg; setupAlgorithmMonitorCorrection(alg, 0.0, 15.0, "1", inputWS, true); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 16); TS_ASSERT(outLam->x(0)[0] >= 0.0); TS_ASSERT(outLam->x(0)[7] <= 15.0); // Expected values are 0.1981 = 2.0000 (detectors) / (1.26139*8) (monitors) TS_ASSERT_DELTA(outLam->y(0)[0], 0.1981, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 0.1981, 0.0001); } void test_transmission_correction_run() { // Transmission run is the same as input run ReflectometryReductionOne2 alg; setupAlgorithmTransmissionCorrection(alg, 1.5, 15.0, "1", m_multiDetectorWS, false); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); // Expected values are 1 = m_wavelength / m_wavelength TS_ASSERT_DELTA(outLam->y(0)[0], 1.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 1.0000, 0.0001); } void test_transmission_correction_two_runs() { // Transmission run is the same as input run ReflectometryReductionOne2 alg; setupAlgorithmTransmissionCorrection(alg, 1.5, 15.0, "1", m_multiDetectorWS, true); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); // Expected values are 1 = m_wavelength / m_wavelength TS_ASSERT_DELTA(outLam->y(0)[0], 1.0000, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 1.0000, 0.0001); } void test_transmission_correction_with_mapped_spectra() { // Run workspace spectrum numbers are 1,2,3,4. // Transmission workspace has spectrum numbers 2,3,4,5. // Processing instructions 2-3 in the run workspace map to // spectra 3-4, which map to indices 1-2 in the transmission // workspace. ReflectometryReductionOne2 alg; setupAlgorithmTransmissionCorrection(alg, 1.5, 15.0, "2-3", m_transmissionWS, true); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT_DELTA(outLam->y(0)[0], 0.0807, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 0.0802, 0.0001); } void test_transmission_correction_with_bad_mapped_spectra() { // Run workspace spectrum numbers are 1,2,3,4. // Transmission workspace has spectrum numbers 2,3,4,5. // Processing instructions 0 in the run workspace maps to // spectrum 1, which doesn't exist in the transmission // workspace. ReflectometryReductionOne2 alg; setupAlgorithmTransmissionCorrection(alg, 1.5, 15.0, "0", m_transmissionWS, true); TS_ASSERT_THROWS_ANYTHING(alg.execute()); } void test_transmission_correction_with_different_spectra() { // Run workspace spectrum numbers are 1,2,3,4. Transmission workspace has // spectrum numbers 2,3,4,5. Processing instructions 2,3 are used in the // run and transmission workspaces without any mapping i.e. spectra 3-4 in // the run and spectra 4-5 in the transmission workspace are used. ReflectometryReductionOne2 alg; setupAlgorithmTransmissionCorrection(alg, 1.5, 15.0, "2-3", m_transmissionWS, true); alg.setProperty("StrictSpectrumChecking", "0"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT_DELTA(outLam->y(0)[0], 0.0571, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 0.0571, 0.0001); } void test_exponential_correction() { // CorrectionAlgorithm: ExponentialCorrection ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "2"); alg.setProperty("CorrectionAlgorithm", "ExponentialCorrection"); alg.setProperty("C0", 0.2); alg.setProperty("C1", 0.1); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT_DELTA(outLam->y(0)[0], 12.5113, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 23.4290, 0.0001); } void test_polynomial_correction() { // CorrectionAlgorithm: PolynomialCorrection ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "2"); alg.setProperty("CorrectionAlgorithm", "PolynomialCorrection"); alg.setProperty("Polynomial", "0.1,0.3,0.5"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg); TS_ASSERT_DELTA(outLam->y(0)[0], 0.6093, 0.0001); TS_ASSERT_DELTA(outLam->y(0)[7], 0.0514, 0.0001); } void test_IvsQ() { // Test IvsQ workspace // No monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 2 ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "2"); MatrixWorkspace_sptr outQ = runAlgorithmQ(alg); // X range in outQ TS_ASSERT_DELTA(outQ->x(0)[0], 0.3353, 0.0001); TS_ASSERT_DELTA(outQ->x(0)[7], 0.5962, 0.0001); // Y counts TS_ASSERT_DELTA(outQ->y(0)[0], 2.0000, 0.0001); TS_ASSERT_DELTA(outQ->y(0)[7], 2.0000, 0.0001); } void test_IvsQ_multiple_detector_groups() { // Test IvsQ workspace // No monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 2,1+3 (two separate groups) ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "2,1+3"); // Run the algorithm. There should be 2 output histograms, one for each // input group. Note that the group order is swapped from the input order // because they are sorted by the first spectrum number in the group, // i.e. as if the input was "1+3,2" MatrixWorkspace_sptr outQ = runAlgorithmQ(alg, 14, 2); // X range in outQ TS_ASSERT_DELTA(outQ->x(0)[0], 0.3353, 0.0001); TS_ASSERT_DELTA(outQ->x(0)[7], 0.5961, 0.0001); TS_ASSERT_DELTA(outQ->x(1)[0], 0.3353, 0.0001); TS_ASSERT_DELTA(outQ->x(1)[7], 0.5962, 0.0001); // Y counts, should be 2.0000 * 2 for first group, 2.0000 * 1 for second. TS_ASSERT_DELTA(outQ->y(0)[0], 4.0000, 0.0001); TS_ASSERT_DELTA(outQ->y(0)[7], 4.0000, 0.0001); TS_ASSERT_DELTA(outQ->y(1)[0], 2.0000, 0.0001); TS_ASSERT_DELTA(outQ->y(1)[7], 2.0000, 0.0001); } void test_sum_in_q_with_bad_reduction_type() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // SummationType : SumInQ // ReductionType : not set (invalid) ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1"); alg.setProperty("SummationType", "SumInQ"); TS_ASSERT_THROWS_ANYTHING(alg.execute()); } void test_sum_in_q_divergent_beam() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // SummationType : SumInQ // ReductionType : DivergentBeam ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1"); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 12); TS_ASSERT_DELTA(outLam->x(0)[0], 0.934991, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[3], 5.173599, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[7], 10.825076, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[0], 2.768185, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[3], 2.792649, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[7], 2.787410, 1e-6); } void test_sum_in_q_non_flat_sample() { // Test IvsLam workspace // No monitor normalization // No direct beam normalization // No transmission correction // SummationType : SumInQ // ReductionType : NonFlatSample ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "1"); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "NonFlatSample"); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 10); TS_ASSERT_DELTA(outLam->x(0)[0], 0.825488, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[3], 5.064095, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[7], 10.715573, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[0], 3.141858, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[3], 3.141885, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[7], 3.141920, 1e-6); } void test_sum_in_q_monitor_normalization() { // Test IvsLam workspace // Monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 2 // SummationType : SumInQ // ReductionType : DivergentBeam // I0MonitorIndex: 0 // MonitorBackgroundWavelengthMin : 0.5 // MonitorBackgroundWavelengthMax : 3.0 // Normalize by integrated monitors : No // Modify counts in monitor (only for this test) // Modify counts only for range that will be fitted auto inputWS = m_multiDetectorWS; auto &Y = m_multiDetectorWS->mutableY(0); std::fill(Y.begin(), Y.begin() + 2, 1.0); ReflectometryReductionOne2 alg; setupAlgorithmMonitorCorrection(alg, 0.0, 15.0, "2", inputWS, false); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 13); TS_ASSERT_DELTA(outLam->x(0)[0], -0.748671, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[5], 6.315674, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[9], 11.967151, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[0], 5.040302, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[5], 2.193649, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[9], 2.255101, 1e-6); } void test_sum_in_q_transmission_correction_run() { // Transmission run is the same as input run ReflectometryReductionOne2 alg; setupAlgorithmTransmissionCorrection(alg, 1.5, 15.0, "1", m_multiDetectorWS, false); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 12); TS_ASSERT_DELTA(outLam->x(0)[0], 0.934991, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[3], 5.173599, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[7], 10.825076, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[0], 0.631775, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[3], 0.888541, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[7], 0.886874, 1e-6); } void test_sum_in_q_exponential_correction() { // CorrectionAlgorithm: ExponentialCorrection ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "2"); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); alg.setProperty("CorrectionAlgorithm", "ExponentialCorrection"); alg.setProperty("C0", 0.2); alg.setProperty("C1", 0.1); MatrixWorkspace_sptr outLam = runAlgorithmLam(alg, 11); TS_ASSERT_DELTA(outLam->x(0)[0], 0.920496, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[3], 5.159104, 1e-6); TS_ASSERT_DELTA(outLam->x(0)[7], 10.810581, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[0], 16.351599, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[3], 23.963539, 1e-6); TS_ASSERT_DELTA(outLam->y(0)[7], 39.756738, 1e-6); } void test_sum_in_q_IvsQ() { // Test IvsQ workspace // No monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 2 ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "2"); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); MatrixWorkspace_sptr outQ = runAlgorithmQ(alg, 11); // X range in outQ TS_ASSERT_DELTA(outQ->x(0)[0], 0.292122, 1e-6); TS_ASSERT_DELTA(outQ->x(0)[3], 0.393419, 1e-6); TS_ASSERT_DELTA(outQ->x(0)[7], 0.731734, 1e-6); // Y counts TS_ASSERT_DELTA(outQ->y(0)[0], 2.852088, 1e-6); TS_ASSERT_DELTA(outQ->y(0)[3], 2.833380, 1e-6); TS_ASSERT_DELTA(outQ->y(0)[7], 2.841288, 1e-6); } void test_sum_in_q_IvsQ_point_detector() { // Test IvsQ workspace for a point detector // No monitor normalization // No direct beam normalization // No transmission correction // Processing instructions : 0 ReflectometryReductionOne2 alg; setupAlgorithm(alg, 1.5, 15.0, "0"); alg.setProperty("InputWorkspace", m_singleDetectorWS); alg.setProperty("SummationType", "SumInQ"); alg.setProperty("ReductionType", "DivergentBeam"); alg.setProperty("ThetaIn", 25.0); MatrixWorkspace_sptr outQ = runAlgorithmQ(alg, 28); // X range in outQ TS_ASSERT_DELTA(outQ->x(0)[0], 0.279882, 1e-6); TS_ASSERT_DELTA(outQ->x(0)[3], 0.310524, 1e-6); TS_ASSERT_DELTA(outQ->x(0)[7], 0.363599, 1e-6); // Y counts TS_ASSERT_DELTA(outQ->y(0)[0], 2.900305, 1e-6); TS_ASSERT_DELTA(outQ->y(0)[3], 2.886947, 1e-6); TS_ASSERT_DELTA(outQ->y(0)[7], 2.607359, 1e-6); } void test_angle_correction() { ReflectometryReductionOne2 alg; auto inputWS = MatrixWorkspace_sptr(m_multiDetectorWS->clone()); setYValuesToWorkspace(*inputWS); alg.setChild(true); alg.initialize(); alg.setProperty("InputWorkspace", inputWS); alg.setProperty("WavelengthMin", 1.5); alg.setProperty("WavelengthMax", 15.0); alg.setPropertyValue("ProcessingInstructions", "1+2"); alg.setPropertyValue("OutputWorkspace", "IvsQ"); alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam"); double const theta = 22.0; alg.setProperty("ThetaIn", theta); alg.execute(); MatrixWorkspace_sptr outLam = alg.getProperty("OutputWorkspaceWavelength"); MatrixWorkspace_sptr outQ = alg.getProperty("OutputWorkspace"); auto const &qX = outQ->x(0); auto const &lamX = outLam->x(0); std::vector<double> lamXinv(lamX.size() + 3); std::reverse_copy(lamX.begin(), lamX.end(), lamXinv.begin()); auto factor = 4.0 * M_PI * sin(theta * M_PI / 180.0); for (size_t i = 0; i < qX.size(); ++i) { TS_ASSERT_DELTA(qX[i], factor / lamXinv[i], 1e-14); } auto const &lamY = outLam->y(0); TS_ASSERT_DELTA(lamY[0], 19, 1e-2); TS_ASSERT_DELTA(lamY[6], 49, 1e-2); TS_ASSERT_DELTA(lamY[13], 84, 1e-2); auto const &qY = outQ->y(0); TS_ASSERT_DELTA(qY[0], 84, 1e-2); TS_ASSERT_DELTA(qY[6], 54, 1e-2); TS_ASSERT_DELTA(qY[13], 19, 1e-2); } void test_no_angle_correction() { ReflectometryReductionOne2 alg; auto inputWS = MatrixWorkspace_sptr(m_multiDetectorWS->clone()); setYValuesToWorkspace(*inputWS); alg.setChild(true); alg.initialize(); alg.setProperty("InputWorkspace", inputWS); alg.setProperty("WavelengthMin", 1.5); alg.setProperty("WavelengthMax", 15.0); alg.setPropertyValue("ProcessingInstructions", "2"); alg.setPropertyValue("OutputWorkspace", "IvsQ"); alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam"); alg.setProperty("ThetaIn", 22.0); alg.execute(); MatrixWorkspace_sptr outLam = alg.getProperty("OutputWorkspaceWavelength"); MatrixWorkspace_sptr outQ = alg.getProperty("OutputWorkspace"); auto const &qX = outQ->x(0); auto const &lamX = outLam->x(0); std::vector<double> lamXinv(lamX.size() + 3); std::reverse_copy(lamX.begin(), lamX.end(), lamXinv.begin()); auto factor = 4.0 * M_PI * sin(22.5 * M_PI / 180.0); for (size_t i = 0; i < qX.size(); ++i) { TS_ASSERT_DELTA(qX[i], factor / lamXinv[i], 1e-14); } auto const &lamY = outLam->y(0); TS_ASSERT_DELTA(lamY[0], 11, 1e-2); TS_ASSERT_DELTA(lamY[6], 29, 1e-2); TS_ASSERT_DELTA(lamY[13], 50, 1e-2); auto const &qY = outQ->y(0); TS_ASSERT_DELTA(qY[0], 50, 1e-2); TS_ASSERT_DELTA(qY[6], 32, 1e-2); TS_ASSERT_DELTA(qY[13], 11, 1e-2); } void test_angle_correction_multi_group() { ReflectometryReductionOne2 alg; alg.setChild(true); alg.setRethrows(true); alg.initialize(); alg.setProperty("InputWorkspace", m_multiDetectorWS); alg.setProperty("WavelengthMin", 1.5); alg.setProperty("WavelengthMax", 15.0); alg.setPropertyValue("ProcessingInstructions", "1+2, 3"); alg.setPropertyValue("OutputWorkspace", "IvsQ"); alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam"); alg.setProperty("ThetaIn", 22.0); TS_ASSERT_THROWS(alg.execute(), std::invalid_argument); } private: // Do standard algorithm setup void setupAlgorithm(ReflectometryReductionOne2 &alg, const double wavelengthMin, const double wavelengthMax, const std::string &procInstr) { alg.setChild(true); alg.initialize(); alg.setProperty("InputWorkspace", m_multiDetectorWS); alg.setProperty("WavelengthMin", wavelengthMin); alg.setProperty("WavelengthMax", wavelengthMax); alg.setPropertyValue("ProcessingInstructions", procInstr); alg.setPropertyValue("OutputWorkspace", "IvsQ"); alg.setPropertyValue("OutputWorkspaceWavelength", "IvsLam"); } // Do standard algorithm setup for transmission correction void setupAlgorithmTransmissionCorrection(ReflectometryReductionOne2 &alg, const double wavelengthMin, const double wavelengthMax, const std::string &procInstr, MatrixWorkspace_sptr transWS, const bool multiple_runs) { setupAlgorithm(alg, wavelengthMin, wavelengthMax, procInstr); alg.setProperty("FirstTransmissionRun", transWS); if (multiple_runs) { alg.setProperty("SecondTransmissionRun", transWS); alg.setProperty("StartOverlap", 2.5); alg.setProperty("EndOverlap", 3.0); alg.setProperty("Params", "0.1"); } } // Do standard algorithm setup for monitor correction void setupAlgorithmMonitorCorrection(ReflectometryReductionOne2 &alg, const double wavelengthMin, const double wavelengthMax, const std::string &procInstr, MatrixWorkspace_sptr inputWS, const bool integrate) { setupAlgorithm(alg, wavelengthMin, wavelengthMax, procInstr); alg.setProperty("InputWorkspace", inputWS); alg.setProperty("I0MonitorIndex", "0"); alg.setProperty("MonitorBackgroundWavelengthMin", 0.5); alg.setProperty("MonitorBackgroundWavelengthMax", 3.0); if (integrate) { alg.setProperty("NormalizeByIntegratedMonitors", "1"); alg.setProperty("MonitorIntegrationWavelengthMin", 1.5); alg.setProperty("MonitorIntegrationWavelengthMax", 15.0); } else { alg.setProperty("NormalizeByIntegratedMonitors", "0"); } } // Do standard algorithm execution and checks and return IvsLam MatrixWorkspace_sptr runAlgorithmLam(ReflectometryReductionOne2 &alg, const size_t blocksize = 14, const size_t nHist = 1) { alg.execute(); MatrixWorkspace_sptr outLam = alg.getProperty("OutputWorkspaceWavelength"); TS_ASSERT(outLam); TS_ASSERT_EQUALS(outLam->getNumberHistograms(), nHist); TS_ASSERT_EQUALS(outLam->blocksize(), blocksize); return outLam; } // Do standard algorithm execution and checks and return IvsQ MatrixWorkspace_sptr runAlgorithmQ(ReflectometryReductionOne2 &alg, const size_t blocksize = 14, const size_t nHist = 1) { alg.execute(); MatrixWorkspace_sptr outQ = alg.getProperty("OutputWorkspace"); TS_ASSERT(outQ); TS_ASSERT_EQUALS(outQ->getNumberHistograms(), nHist); TS_ASSERT_EQUALS(outQ->blocksize(), blocksize); return outQ; } void setYValuesToWorkspace(MatrixWorkspace &ws) { for (size_t i = 0; i < ws.getNumberHistograms(); ++i) { auto &y = ws.mutableY(i); for (size_t j = 0; j < y.size(); ++j) { y[j] += double(j + 1) * double(i + 1); } } } }; #endif /* ALGORITHMS_TEST_REFLECTOMETRYREDUCTIONONE2TEST_H_ */