def test_basic_realizations_predictor(self):
        """
        Test that the plugin returns a numpy float value. The ensemble
        realizations are the predictor. The result indicates the minimum value
        for the CRPS that was achieved by the minimisation.
        """
        predictor = "realizations"

        plugin = Plugin()
        result = plugin.calculate_truncated_normal_crps(
            self.initial_guess_for_realization,
            self.forecast_predictor_data_realizations, self.truth_data,
            self.forecast_variance_data, self.sqrt_pi, predictor)

        self.assertIsInstance(result, np.float64)
        self.assertAlmostEqual(result, 0.1670167)
    def test_basic_mean_predictor_bad_value(self):
        """
        Test that the plugin returns a numpy float64 value
        and that the value matches the BAD_VALUE, when the appropriate
        condition is found. The ensemble mean is the predictor. The initial
        guess is specifically set to float32 precision for the purpose for
        generating the BAD_VALUE for the unit test.
        """
        initial_guess = np.array([1e65, 1e65, 1e65, 1e65], dtype=np.float32)

        predictor = "mean"

        plugin = Plugin()
        result = plugin.calculate_truncated_normal_crps(
            initial_guess, self.forecast_predictor_data, self.truth_data,
            self.forecast_variance_data, self.sqrt_pi, predictor)

        self.assertIsInstance(result, np.float64)
        self.assertAlmostEqual(result, plugin.BAD_VALUE)
class Test_calculate_truncated_normal_crps(SetupTruncatedNormalInputs):
    """
    Test minimising the crps for a truncated normal distribution.
    Either the ensemble mean or the individual ensemble realizations are used
    as the predictors.
    """
    def setUp(self):
        """Set up plugin."""
        super().setUp()
        self.precision = 4
        self.plugin = Plugin(tolerance=1e-4)

    @ManageWarnings(
        ignored_messages=["Collapsing a non-contiguous coordinate."])
    def test_basic_mean_predictor(self):
        """
        Test that the plugin returns a numpy float value. The ensemble mean
        is the predictor. The result indicates the minimum value
        for the CRPS that was achieved by the minimisation.
        """
        predictor = "mean"

        result = self.plugin.calculate_truncated_normal_crps(
            self.initial_guess_for_mean,
            self.forecast_predictor_data,
            self.truth_data,
            self.forecast_variance_data,
            self.sqrt_pi,
            predictor,
        )

        self.assertIsInstance(result, np.float64)
        self.assertAlmostEqual(result, 0.2150, self.precision)

    @ManageWarnings(
        ignored_messages=["Collapsing a non-contiguous coordinate."])
    def test_basic_realizations_predictor(self):
        """
        Test that the plugin returns a numpy float value. The ensemble
        realizations are the predictor. The result indicates the minimum value
        for the CRPS that was achieved by the minimisation.
        """
        predictor = "realizations"

        result = self.plugin.calculate_truncated_normal_crps(
            self.initial_guess_for_realization,
            self.forecast_predictor_data_realizations,
            self.truth_data,
            self.forecast_variance_data,
            self.sqrt_pi,
            predictor,
        )

        self.assertIsInstance(result, np.float64)
        self.assertAlmostEqual(result, 0.2150, self.precision)

    @ManageWarnings(
        ignored_messages=[
            "Collapsing a non-contiguous coordinate.",
            "invalid value encountered in",
        ],
        warning_types=[UserWarning, RuntimeWarning],
    )
    def test_basic_mean_predictor_bad_value(self):
        """
        Test that the plugin returns a numpy float64 value
        and that the value matches the BAD_VALUE, when the appropriate
        condition is found. The ensemble mean is the predictor. The initial
        guess is specifically set to float32 precision for the purpose for
        generating the BAD_VALUE for the unit test.
        """
        initial_guess = np.array([1e65, 1e65, 1e65, 1e65], dtype=np.float32)

        predictor = "mean"

        result = self.plugin.calculate_truncated_normal_crps(
            initial_guess,
            self.forecast_predictor_data,
            self.truth_data,
            self.forecast_variance_data,
            self.sqrt_pi,
            predictor,
        )

        self.assertIsInstance(result, np.float64)
        self.assertAlmostEqual(result, self.plugin.BAD_VALUE, self.precision)