From 3518e0919c3f0d108367c8868564620a5cc3faa0 Mon Sep 17 00:00:00 2001 From: Gemma Guest <gemma.guest@stfc.ac.uk> Date: Wed, 25 Mar 2020 19:28:40 +0000 Subject: [PATCH] Add unit tests for background subtraction in gui Also do some minor tidying of existing tests and add a missing polarization correction test. Re #27826 --- .../REFL_Parameters_Experiment.xml | 12 ++ .../REFL_Parameters_Subtraction_Invalid.xml | 20 +++ .../GUI/Batch/RowProcessingAlgorithm.cpp | 16 +-- .../TestHelpers/ModelCreationHelper.cpp | 2 +- .../TestHelpers/ModelCreationHelper.h | 4 +- .../Batch/RowProcessingAlgorithmTest.h | 29 +++- .../Common/CoderCommonTester.h | 8 ++ .../ISISReflectometry/Common/DecoderTest.h | 8 ++ .../Experiment/ExperimentOptionDefaultsTest.h | 25 ++++ .../Experiment/ExperimentPresenterTest.h | 135 ++++++++++++++++-- 10 files changed, 238 insertions(+), 21 deletions(-) create mode 100644 instrument/unit_testing/REFL_Parameters_Subtraction_Invalid.xml diff --git a/instrument/unit_testing/REFL_Parameters_Experiment.xml b/instrument/unit_testing/REFL_Parameters_Experiment.xml index e729bace714..133a18dbfb4 100644 --- a/instrument/unit_testing/REFL_Parameters_Experiment.xml +++ b/instrument/unit_testing/REFL_Parameters_Experiment.xml @@ -33,6 +33,18 @@ <!-- Corrections --> + <parameter name="BackgroundCalculationMethod" type="string"> + <value val="Polynomial"/> + </parameter> + + <parameter name="DegreeOfPolynomial"> + <value val="2"/> + </parameter> + + <parameter name="CostFunction" type="string"> + <value val="Unweighted least squares"/> + </parameter> + <parameter name="PolarizationAnalysis" type="string"> <value val="ParameterFile"/> </parameter> diff --git a/instrument/unit_testing/REFL_Parameters_Subtraction_Invalid.xml b/instrument/unit_testing/REFL_Parameters_Subtraction_Invalid.xml new file mode 100644 index 00000000000..6d81cd1869d --- /dev/null +++ b/instrument/unit_testing/REFL_Parameters_Subtraction_Invalid.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<parameter-file instrument="REFL" valid-from="forever"> + +<component-link name="REFL" > + + <parameter name="BackgroundCalculationMethod" type="string"> + <value val="badSubtractionMethod"/> + </parameter> + + <parameter name="DegreeOfPolynomial" type="string"> + <value val="badPolynomialType"/> + </parameter> + + <parameter name="CostFunction" type="string"> + <value val="badCostFunction"/> + </parameter> + +</component-link> + +</parameter-file> diff --git a/qt/scientific_interfaces/ISISReflectometry/GUI/Batch/RowProcessingAlgorithm.cpp b/qt/scientific_interfaces/ISISReflectometry/GUI/Batch/RowProcessingAlgorithm.cpp index 11bc903ad78..c383a441d39 100644 --- a/qt/scientific_interfaces/ISISReflectometry/GUI/Batch/RowProcessingAlgorithm.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/GUI/Batch/RowProcessingAlgorithm.cpp @@ -84,19 +84,17 @@ void updateTransmissionStitchProperties( void updateBackgroundSubtractionProperties( AlgorithmRuntimeProps &properties, BackgroundSubtraction const &subtraction) { - AlgorithmProperties::update("SubtractBackground", subtraction.subtractBackground(), properties); + AlgorithmProperties::update("SubtractBackground", + subtraction.subtractBackground(), properties); AlgorithmProperties::update( "BackgroundCalculationMethod", backgroundSubtractionTypeToString(subtraction.subtractionType()), properties); - - if (subtraction.subtractionType() == BackgroundSubtractionType::Polynomial) { - AlgorithmProperties::update("DegreeOfPolynomial", - subtraction.degreeOfPolynomial(), properties); - AlgorithmProperties::update( - "CostFunction", costFunctionTypeToString(subtraction.costFunction()), - properties); - } + AlgorithmProperties::update("DegreeOfPolynomial", + subtraction.degreeOfPolynomial(), properties); + AlgorithmProperties::update( + "CostFunction", costFunctionTypeToString(subtraction.costFunction()), + properties); } void updatePolarizationCorrectionProperties( diff --git a/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.cpp b/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.cpp index 8867a721a2a..add99b50fa1 100644 --- a/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.cpp +++ b/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.cpp @@ -350,7 +350,7 @@ std::map<std::string, std::string> makeEmptyStitchOptions() { } BackgroundSubtraction makeBackgroundSubtraction() { - return BackgroundSubtraction(true, BackgroundSubtractionType::Polynomial, 2, + return BackgroundSubtraction(true, BackgroundSubtractionType::Polynomial, 3, CostFunctionType::UnweightedLeastSquares); } diff --git a/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.h b/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.h index 2f90d38d95e..889ef446fb4 100644 --- a/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.h +++ b/qt/scientific_interfaces/ISISReflectometry/TestHelpers/ModelCreationHelper.h @@ -89,6 +89,8 @@ makePolarizationCorrections(); MANTIDQT_ISISREFLECTOMETRY_DLL PolarizationCorrections makeEmptyPolarizationCorrections(); MANTIDQT_ISISREFLECTOMETRY_DLL FloodCorrections makeFloodCorrections(); +MANTIDQT_ISISREFLECTOMETRY_DLL TransmissionStitchOptions +makeTransmissionStitchOptions(); MANTIDQT_ISISREFLECTOMETRY_DLL RangeInLambda makeTransmissionRunRange(); MANTIDQT_ISISREFLECTOMETRY_DLL TransmissionStitchOptions makeEmptyTransmissionStitchOptions(); @@ -106,4 +108,4 @@ MANTIDQT_ISISREFLECTOMETRY_DLL Instrument makeEmptyInstrument(); } // namespace ModelCreationHelper } // namespace ISISReflectometry } // namespace CustomInterfaces -} // namespace MantidQt \ No newline at end of file +} // namespace MantidQt diff --git a/qt/scientific_interfaces/test/ISISReflectometry/Batch/RowProcessingAlgorithmTest.h b/qt/scientific_interfaces/test/ISISReflectometry/Batch/RowProcessingAlgorithmTest.h index de8e6c1f2c5..dd7b8d936e4 100644 --- a/qt/scientific_interfaces/test/ISISReflectometry/Batch/RowProcessingAlgorithmTest.h +++ b/qt/scientific_interfaces/test/ISISReflectometry/Batch/RowProcessingAlgorithmTest.h @@ -39,6 +39,10 @@ public: TS_ASSERT_EQUALS(result["SummationType"], "SumInQ"); TS_ASSERT_EQUALS(result["IncludePartialBins"], "1"); TS_ASSERT_EQUALS(result["Debug"], "1"); + TS_ASSERT_EQUALS(result["SubtractBackground"], "1"); + TS_ASSERT_EQUALS(result["BackgroundCalculationMethod"], "Polynomial"); + TS_ASSERT_EQUALS(result["DegreeOfPolynomial"], "3"); + TS_ASSERT_EQUALS(result["CostFunction"], "Unweighted least squares"); TS_ASSERT_EQUALS(result["PolarizationAnalysis"], "1"); TS_ASSERT_EQUALS(result["FloodCorrection"], "Workspace"); TS_ASSERT_EQUALS(result["FloodWorkspace"], "test_workspace"); @@ -57,6 +61,10 @@ public: TS_ASSERT_EQUALS(result["SummationType"], "SumInQ"); TS_ASSERT_EQUALS(result["IncludePartialBins"], "1"); TS_ASSERT_EQUALS(result["Debug"], "1"); + TS_ASSERT_EQUALS(result["SubtractBackground"], "1"); + TS_ASSERT_EQUALS(result["BackgroundCalculationMethod"], "Polynomial"); + TS_ASSERT_EQUALS(result["DegreeOfPolynomial"], "3"); + TS_ASSERT_EQUALS(result["CostFunction"], "Unweighted least squares"); TS_ASSERT_EQUALS(result["PolarizationAnalysis"], "1"); TS_ASSERT_EQUALS(result["FloodCorrection"], "Workspace"); TS_ASSERT_EQUALS(result["FloodWorkspace"], "test_workspace"); @@ -218,6 +226,25 @@ public: TS_ASSERT_EQUALS(result["WavelengthMin"], "3.3"); } + void testOptionsCellOverridesSubtractBackgroundAndStillPicksUpSettings() { + auto experiment = Experiment( + AnalysisMode::MultiDetector, ReductionType::NonFlatSample, + SummationType::SumInQ, true, true, + BackgroundSubtraction(false, BackgroundSubtractionType::AveragePixelFit, + 3, CostFunctionType::UnweightedLeastSquares), + makePolarizationCorrections(), makeFloodCorrections(), + makeTransmissionStitchOptions(), makeStitchOptions(), + makePerThetaDefaultsWithTwoAnglesAndWildcard()); + auto model = Batch(experiment, m_instrument, m_runsTable, m_slicing); + auto row = makeRowWithOptionsCellFilled( + 2.3, ReductionOptionsMap{{"SubtractBackground", "1"}}); + auto result = createAlgorithmRuntimeProps(model, row); + TS_ASSERT_EQUALS(result["SubtractBackground"], "1"); + TS_ASSERT_EQUALS(result["BackgroundCalculationMethod"], "AveragePixelFit"); + TS_ASSERT_EQUALS(result["DegreeOfPolynomial"], "3"); + TS_ASSERT_EQUALS(result["CostFunction"], "Unweighted least squares"); + } + private: std::vector<std::string> m_instruments; double m_thetaTolerance; @@ -225,4 +252,4 @@ private: Instrument m_instrument; RunsTable m_runsTable; Slicing m_slicing; -}; \ No newline at end of file +}; diff --git a/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h b/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h index 93ef2330d0f..9bdfc19d2d2 100644 --- a/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h +++ b/qt/scientific_interfaces/test/ISISReflectometry/Common/CoderCommonTester.h @@ -86,6 +86,14 @@ private: map[QString("transStitchParamsEdit")].toString()) TS_ASSERT_EQUALS(gui->m_ui.transScaleRHSCheckBox->isChecked(), map[QString("transScaleRHSCheckBox")].toBool()) + TS_ASSERT_EQUALS(gui->m_ui.subtractBackgroundCheckBox->isChecked(), + map[QString("subtractBackgroundCheckBox")].toBool()) + TS_ASSERT_EQUALS(gui->m_ui.backgroundMethodComboBox->currentIndex(), + map[QString("backgroundMethodComboBox")].toInt()) + TS_ASSERT_EQUALS(gui->m_ui.polynomialDegreeSpinBox->value(), + map[QString("polynomialDegreeSpinBox")].toInt()) + TS_ASSERT_EQUALS(gui->m_ui.costFunctionComboBox->currentIndex(), + map[QString("costFunctionComboBox")].toInt()) TS_ASSERT_EQUALS(gui->m_ui.polCorrCheckBox->isChecked(), map[QString("polCorrCheckBox")].toBool()) TS_ASSERT_EQUALS(gui->m_ui.floodCorComboBox->currentIndex(), diff --git a/qt/scientific_interfaces/test/ISISReflectometry/Common/DecoderTest.h b/qt/scientific_interfaces/test/ISISReflectometry/Common/DecoderTest.h index 4bacea8c547..fe24aeabf53 100644 --- a/qt/scientific_interfaces/test/ISISReflectometry/Common/DecoderTest.h +++ b/qt/scientific_interfaces/test/ISISReflectometry/Common/DecoderTest.h @@ -35,6 +35,8 @@ const static QString BATCH_JSON_STRING{ " }," " \"experimentView\": {" " \"analysisModeComboBox\": 1," + " \"backgroundMethodComboBox\": 1," + " \"costFunctionComboBox\": 1," " \"debugCheckbox\": true," " \"endOverlapEdit\": 13," " \"floodCorComboBox\": 1," @@ -59,9 +61,11 @@ const static QString BATCH_JSON_STRING{ " \"rowsNum\": 1" " }," " \"polCorrCheckBox\": false," + " \"polynomialDegreeSpinBox\": 3," " \"reductionTypeComboBox\": 2," " \"startOverlapEdit\": 8," " \"stitchEdit\": \"Params=0.015\"," + " \"subtractBackgroundCheckBox\": true," " \"summationTypeComboBox\": 1," " \"transScaleRHSCheckBox\": false," " \"transStitchParamsEdit\": \"0.03\"" @@ -321,6 +325,8 @@ const static QString EMPTY_BATCH_JSON_STRING{ " }," " \"experimentView\": {" " \"analysisModeComboBox\": 0," + " \"backgroundMethodComboBox\": 0," + " \"costFunctionComboBox\": 0," " \"debugCheckbox\": false," " \"endOverlapEdit\": 12," " \"floodCorComboBox\": 0," @@ -345,9 +351,11 @@ const static QString EMPTY_BATCH_JSON_STRING{ " \"rowsNum\": 1" " }," " \"polCorrCheckBox\": false," + " \"polynomialDegreeSpinBox\": 3," " \"reductionTypeComboBox\": 0," " \"startOverlapEdit\": 10," " \"stitchEdit\": \"\"," + " \"subtractBackgroundCheckBox\": false," " \"summationTypeComboBox\": 0," " \"transScaleRHSCheckBox\": true," " \"transStitchParamsEdit\": \"\"" diff --git a/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentOptionDefaultsTest.h b/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentOptionDefaultsTest.h index d3b9ed34b3a..0f597d01f08 100644 --- a/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentOptionDefaultsTest.h +++ b/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentOptionDefaultsTest.h @@ -120,6 +120,31 @@ public: getDefaultsFromParamsFileThrows("TransmissionRunRange_Invalid"); } + void testDefaultSubtractionOptions() { + auto result = getDefaults(); + TS_ASSERT_EQUALS(result.backgroundSubtraction().subtractBackground(), + false); + TS_ASSERT_EQUALS(result.backgroundSubtraction().subtractionType(), + BackgroundSubtractionType::PerDetectorAverage); + TS_ASSERT_EQUALS(result.backgroundSubtraction().degreeOfPolynomial(), 0); + TS_ASSERT_EQUALS(result.backgroundSubtraction().costFunction(), + CostFunctionType::LeastSquares); + } + + void testValidSubtractionOptionsFromParamsFile() { + auto result = getDefaultsFromParamsFile("Experiment"); + TS_ASSERT_EQUALS(result.backgroundSubtraction().subtractBackground(), true); + TS_ASSERT_EQUALS(result.backgroundSubtraction().subtractionType(), + BackgroundSubtractionType::Polynomial); + TS_ASSERT_EQUALS(result.backgroundSubtraction().degreeOfPolynomial(), 2); + TS_ASSERT_EQUALS(result.backgroundSubtraction().costFunction(), + CostFunctionType::UnweightedLeastSquares); + } + + void testInvalidSubtractionOptionsFromParamsFile() { + getDefaultsFromParamsFileThrows("Subtraction_Invalid"); + } + void testDefaultCorrectionOptions() { auto result = getDefaults(); TS_ASSERT_EQUALS(result.polarizationCorrections().correctionType(), diff --git a/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentPresenterTest.h b/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentPresenterTest.h index 330e22d78f9..b1e9b6369ad 100644 --- a/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentPresenterTest.h +++ b/qt/scientific_interfaces/test/ISISReflectometry/Experiment/ExperimentPresenterTest.h @@ -161,6 +161,68 @@ public: verifyAndClear(); } + void testSetBackgroundSubtractionUpdatesModel() { + auto presenter = makePresenter(); + expectSubtractBackground(); + presenter.notifySettingsChanged(); + assertBackgroundSubtractionOptionsSet(presenter); + verifyAndClear(); + } + + void + testBackgroundSubtractionMethodIsEnabledWhenSubtractBackgroundIsChecked() { + auto presenter = makePresenter(); + expectSubtractBackground(true); + EXPECT_CALL(m_view, enableBackgroundSubtractionMethod()).Times(1); + presenter.notifySettingsChanged(); + verifyAndClear(); + } + + void testPolynomialInputsEnabledWhenSubtractingPolynomialBackground() { + auto presenter = makePresenter(); + expectSubtractBackground(true, "Polynomial"); + EXPECT_CALL(m_view, enablePolynomialDegree()).Times(1); + EXPECT_CALL(m_view, enableCostFunction()).Times(1); + presenter.notifySettingsChanged(); + verifyAndClear(); + } + + void testPolynomialInputsDisabledWhenSubtractingPerDetectorAverage() { + auto presenter = makePresenter(); + expectSubtractBackground(true, "PerDetectorAverage"); + EXPECT_CALL(m_view, disablePolynomialDegree()).Times(1); + EXPECT_CALL(m_view, disableCostFunction()).Times(1); + presenter.notifySettingsChanged(); + verifyAndClear(); + } + + void testPolynomialInputsDisabledWhenSubtractingAveragePixelFit() { + auto presenter = makePresenter(); + expectSubtractBackground(true, "AveragePixelFit"); + EXPECT_CALL(m_view, disablePolynomialDegree()).Times(1); + EXPECT_CALL(m_view, disableCostFunction()).Times(1); + presenter.notifySettingsChanged(); + verifyAndClear(); + } + + void testBackgroundSubtractionInputsDisabledWhenOptionTurnedOff() { + auto presenter = makePresenter(); + expectSubtractBackground(false); + EXPECT_CALL(m_view, disableBackgroundSubtractionMethod()).Times(1); + EXPECT_CALL(m_view, disablePolynomialDegree()).Times(1); + EXPECT_CALL(m_view, disableCostFunction()).Times(1); + presenter.notifySettingsChanged(); + verifyAndClear(); + } + + void testTogglePolarizationCorrectionOptionUpdatesModel() { + auto presenter = makePresenter(); + expectPolarizationAnalysisOn(); + presenter.notifySettingsChanged(); + assertPolarizationAnalysisOn(presenter); + verifyAndClear(); + } + void testSetFloodCorrectionsUpdatesModel() { auto presenter = makePresenter(); FloodCorrections floodCorr(FloodCorrectionType::Workspace, @@ -616,8 +678,7 @@ public: auto model = makeModelWithCorrections( PolarizationCorrections(PolarizationCorrectionType::ParameterFile), FloodCorrections(FloodCorrectionType::ParameterFile), - BackgroundSubtraction(true, BackgroundSubtractionType::Polynomial, 3, - CostFunctionType::UnweightedLeastSquares)); + makeBackgroundSubtraction()); auto defaultOptions = expectDefaults(model); auto presenter = makePresenter(std::move(defaultOptions)); EXPECT_CALL(m_view, setPolarizationCorrectionOption(true)).Times(1); @@ -634,16 +695,13 @@ public: auto model = makeModelWithCorrections( PolarizationCorrections(PolarizationCorrectionType::ParameterFile), FloodCorrections(FloodCorrectionType::ParameterFile), - BackgroundSubtraction(true, BackgroundSubtractionType::Polynomial, 3, - CostFunctionType::UnweightedLeastSquares)); + makeBackgroundSubtraction()); auto defaultOptions = expectDefaults(model); auto presenter = makePresenter(std::move(defaultOptions)); presenter.notifyInstrumentChanged("POLREF"); - TS_ASSERT_EQUALS( - presenter.experiment().polarizationCorrections().correctionType(), - PolarizationCorrectionType::ParameterFile); - TS_ASSERT_EQUALS(presenter.experiment().floodCorrections().correctionType(), - FloodCorrectionType::ParameterFile); + assertBackgroundSubtractionOptionsSet(presenter); + assertPolarizationAnalysisOn(presenter); + assertFloodCorrectionUsesParameterFile(presenter); verifyAndClear(); } @@ -786,6 +844,65 @@ private: .WillOnce(Return(std::string("DivergentBeam"))); } + void expectSubtractBackground( + bool subtractBackground = true, + std::string const &subtractionType = std::string("Polynomial"), + int degreeOfPolynomial = 3, + std::string const &costFunction = + std::string("Unweighted least squares")) { + EXPECT_CALL(m_view, getSubtractBackground()) + .Times(AtLeast(1)) + .WillRepeatedly(Return(subtractBackground)); + EXPECT_CALL(m_view, getBackgroundSubtractionMethod()) + .Times(AtLeast(1)) + .WillRepeatedly(Return(subtractionType)); + EXPECT_CALL(m_view, getPolynomialDegree()) + .Times(1) + .WillRepeatedly(Return(degreeOfPolynomial)); + EXPECT_CALL(m_view, getCostFunction()) + .Times(1) + .WillRepeatedly(Return(costFunction)); + } + + void assertBackgroundSubtractionOptionsSet( + ExperimentPresenter const &presenter, bool subtractBackground = true, + BackgroundSubtractionType subtractionType = + BackgroundSubtractionType::Polynomial, + int degreeOfPolynomial = 3, + CostFunctionType costFunction = + CostFunctionType::UnweightedLeastSquares) { + TS_ASSERT_EQUALS( + presenter.experiment().backgroundSubtraction().subtractBackground(), + subtractBackground); + TS_ASSERT_EQUALS( + presenter.experiment().backgroundSubtraction().subtractionType(), + subtractionType); + TS_ASSERT_EQUALS( + presenter.experiment().backgroundSubtraction().degreeOfPolynomial(), + degreeOfPolynomial); + TS_ASSERT_EQUALS( + presenter.experiment().backgroundSubtraction().costFunction(), + costFunction); + } + + void expectPolarizationAnalysisOn() { + EXPECT_CALL(m_view, getPolarizationCorrectionOption()) + .Times(AtLeast(1)) + .WillRepeatedly(Return(true)); + } + + void assertPolarizationAnalysisOn(ExperimentPresenter const &presenter) { + TS_ASSERT_EQUALS( + presenter.experiment().polarizationCorrections().correctionType(), + PolarizationCorrectionType::ParameterFile); + } + + void + assertFloodCorrectionUsesParameterFile(ExperimentPresenter const &presenter) { + TS_ASSERT_EQUALS(presenter.experiment().floodCorrections().correctionType(), + FloodCorrectionType::ParameterFile); + } + std::unique_ptr<MockExperimentOptionDefaults> expectDefaults(Experiment const &model) { // Create a defaults object, set expectations on it, and return it so -- GitLab