From 7636fb6f62bde15842098db3873fcf78b258fa07 Mon Sep 17 00:00:00 2001 From: Jasmine Beaver Date: Wed, 6 May 2026 14:37:58 +0100 Subject: [PATCH 1/2] Updating CLI and Acceptance Tests for non-default scale factors. --- improver/cli/uv_index.py | 20 ++++++++++++++++-- improver_tests/acceptance/SHA256SUMS | 1 + improver_tests/acceptance/test_uv_index.py | 24 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/improver/cli/uv_index.py b/improver/cli/uv_index.py index 257525e139..b464508b66 100755 --- a/improver/cli/uv_index.py +++ b/improver/cli/uv_index.py @@ -10,7 +10,9 @@ @cli.clizefy @cli.with_output -def process(uv_flux_down: cli.inputcube, *, model_id_attr: str = None): +def process( + uv_flux_down: cli.inputcube, *, scale_factor: float = 3.6, model_id_attr: str = None +): """Calculate the UV index using the data in the input cubes. Calculate the uv index using the radiation flux in UV downward at surface. @@ -18,6 +20,12 @@ def process(uv_flux_down: cli.inputcube, *, model_id_attr: str = None): Args: uv_flux_down (iris.cube.Cube): Cube of radiation flux in UV downwards at surface. + scale_factor: + The uv scale factor. Default is 3.6 (m2 W-1). This factor has + been empirically derived and should not be + changed except if there are scientific reasons to + do so. For more information see section 2.1.1 of the paper + referenced below. model_id_attr (str): Name of the attribute used to identify the source model for blending. @@ -25,8 +33,16 @@ def process(uv_flux_down: cli.inputcube, *, model_id_attr: str = None): Returns: iris.cube.Cube: Processed Cube. + + References: + Turner, E.C, Manners, J. Morcrette, C. J, O'Hagan, J. B, + & Smedley, A.R.D. (2017): Toward a New UV Index Diagnostic + in the Met Office's Forecast Model. Journal of Advances in + Modeling Earth Systems 9, 2654-2671. """ from improver.uv_index import calculate_uv_index - result = calculate_uv_index(uv_flux_down, model_id_attr=model_id_attr) + result = calculate_uv_index( + uv_flux_down, scale_factor=scale_factor, model_id_attr=model_id_attr + ) return result diff --git a/improver_tests/acceptance/SHA256SUMS b/improver_tests/acceptance/SHA256SUMS index 4f7414831f..b4c3dff5e0 100644 --- a/improver_tests/acceptance/SHA256SUMS +++ b/improver_tests/acceptance/SHA256SUMS @@ -1099,6 +1099,7 @@ e81c04f9f2d8dc14b8d8cd9bc9e8827ebd0da5ba016db48cf60ab738d327f968 ./train-quanti 8e2dda09c26d33fd06d68c5be17a74b93b1d75d54c60ce48f27ea3d2735bece9 ./train-quantile-regression-random-forest/without_transformation_kgo.pickle e2cfb5e19ef5ebcfd73dc1c8504b66e9a55ad76b7b18cb79318659224079f234 ./uv-index/basic/20181210T0600Z-PT0000H00M-radiation_flux_in_uv_downward_at_surface.nc e48c3b07bd14214a1a10c0bbf1e0acdf54cfedf93b2c6d766f594ce83a45c2b8 ./uv-index/basic/kgo.nc +71e9242b7d003c1d404de5f39a0e52b4a8a544784654e4c2825f83ad92217993 ./uv-index/non_default_scale_factor/non_default_scale_factor_kgo.nc 2226a5e95eb29664e21f8c0658101a53d65945a1450a60a19955563a2693d22d ./vertical-updraught/cape.nc b794823053a282e758f7eb8625867d497e55cc3757862a7be504fcbd7451bc32 ./vertical-updraught/precip_rate_max.nc 064f9d2861e6312848a7ba24893b9b8ab0271e4b99793cb0d57fdda732931292 ./vertical-updraught/with_id_attr/kgo.nc diff --git a/improver_tests/acceptance/test_uv_index.py b/improver_tests/acceptance/test_uv_index.py index 06fec3b804..871e680749 100644 --- a/improver_tests/acceptance/test_uv_index.py +++ b/improver_tests/acceptance/test_uv_index.py @@ -33,3 +33,27 @@ def test_basic(tmp_path): ] run_cli(args) acc.compare(output_path, kgo_path) + + +def test_non_default_scale_factor(tmp_path): + """Test UV index calculation with non-default scale factor""" + kgo_dir = acc.kgo_root() / "uv-index" + kgo_path = kgo_dir / "non_default_scale_factor/non_default_scale_factor_kgo.nc" + input_paths = [ + kgo_dir + / ( + "basic/20181210T0600Z-PT0000H00M-radiation_flux_in_uv_downward_at_surface.nc" + ) + ] + output_path = tmp_path / "output.nc" + args = [ + *input_paths, + "--output", + output_path, + "--scale-factor", + "0.1", + "--model-id-attr", + "mosg__model_configuration", + ] + run_cli(args) + acc.compare(output_path, kgo_path) From 6cc091941cddecff5471e6cc30e4b262dc270f44 Mon Sep 17 00:00:00 2001 From: Jasmine Beaver Date: Tue, 7 Jul 2026 14:10:40 +0100 Subject: [PATCH 2/2] Adding warning to plugin. --- improver/uv_index.py | 12 ++++++++++++ improver_tests/uv_index/test_uv_index.py | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/improver/uv_index.py b/improver/uv_index.py index 07ed513b08..c3a098eb01 100644 --- a/improver/uv_index.py +++ b/improver/uv_index.py @@ -5,6 +5,7 @@ """Module for calculating the uv index using radiation flux in UV downward at the surface.""" +import warnings from typing import Optional import numpy as np @@ -47,6 +48,9 @@ def calculate_uv_index( ValueError: If uv_downward contains values that are negative or not a number. + Warning: + - If scale_factor has been changed from the default 3.6 (m2 W-1). + References: Turner, E.C, Manners, J. Morcrette, C. J, O'Hagan, J. B, & Smedley, A.R.D. (2017): Toward a New UV Index Diagnostic @@ -71,6 +75,14 @@ def calculate_uv_index( ) raise ValueError(msg) + if scale_factor != 3.6: + msg = ( + f"The scale_factor is not the default 3.6 (m2 W-1) but {scale_factor}. " + "This default factor has been empirically derived and should not be " + "changed except if there are scientific reasons to do so." + ) + warnings.warn(msg) + uv_downward.convert_units("W m-2") uv_data = (uv_downward.data * scale_factor).astype(np.float32) attributes = generate_mandatory_attributes( diff --git a/improver_tests/uv_index/test_uv_index.py b/improver_tests/uv_index/test_uv_index.py index fcd3da86b6..02a6ef1fcf 100644 --- a/improver_tests/uv_index/test_uv_index.py +++ b/improver_tests/uv_index/test_uv_index.py @@ -42,7 +42,9 @@ def test_scale_factor(self): """Test the uv calculation works when changing the scale factor. Make sure the output is a cube with the expected data.""" expected = np.ones_like(self.cube_uv_down.data, dtype=np.float32) - result = calculate_uv_index(self.cube_uv_down, scale_factor=10) + msg = r"The scale_factor is not the default 3\.6 \(m2 W-1\) but 10\.*" + with self.assertWarnsRegex(UserWarning, msg): + result = calculate_uv_index(self.cube_uv_down, scale_factor=10) np.testing.assert_array_equal(result.data, expected) def test_metadata(self):