def test_list_one_valid(self): """Tests that a list returns a function which itself returns 1 cube that matches the constraints provided.""" obj = create_constrained_inputcubelist_converter( ['wind_speed', 'nonsense']) result = obj(self.wind_speed_cube) self.assertEqual(result, [self.wind_speed_cube])
def test_list_no_match(self): """Tests that providing no valid constraints raises a ConstraintMismatchError.""" func = create_constrained_inputcubelist_converter( "airspeed_velocity_of_unladen_swallow", ) with self.assertRaisesRegex(ConstraintMismatchError, "^Got 0 cubes"): func(self.wind_cubes)
def test_two_valid_cubes(self): """Tests that providing 2 valid constraints raises a ConstraintMismatchError.""" func = create_constrained_inputcubelist_converter( lambda cube: cube.name() in ["wind_speed", "wind_from_direction"], ) with self.assertRaisesRegex(ConstraintMismatchError, "^Got 2 cubes"): func(self.wind_cubes)
def test_list_two_valid(self): """Tests that providing two valid constraints raises a ValueError.""" obj = create_constrained_inputcubelist_converter( ['wind_speed', 'wind_from_direction']) msg = 'Incorrect number of valid inputs available' with self.assertRaisesRegex(ValueError, msg): obj(self.wind_cubes)
def test_basic(self, m): """Tests that it returns a function which itself returns 2 cubes""" result = create_constrained_inputcubelist_converter( 'wind_speed', 'wind_from_direction') result("foo") m.assert_any_call(load_cube, "foo", constraints='wind_speed') m.assert_any_call(load_cube, "foo", constraints='wind_from_direction') self.assertEqual(m.call_count, 2)
def test_extracting_two_cubes(self): """Tests a creation of with two cube names""" func = create_constrained_inputcubelist_converter( "wind_speed", "wind_from_direction") result = func(self.wind_cubes) self.assertEqual(self.wind_speed_cube, result[0]) self.assertEqual(self.wind_dir_cube, result[1]) self.assertEqual(2, len(result))
def test_basic(self): """Tests a basic creation of create_constrained_inputcubelist_converter""" func = create_constrained_inputcubelist_converter( lambda cube: cube.name( ) in ["wind_speed", "airspeed_velocity_of_unladen_swallow"]) result = func(self.wind_cubes) self.assertEqual(self.wind_speed_cube, result[0]) self.assertEqual(1, len(result))
def test_basic_given_str(self, mocked_maybe_coerce): """Tests that a str is given to maybe_coerce_with which would return a CubeList.""" func = create_constrained_inputcubelist_converter( "wind_speed", "wind_from_direction") result = func(self.wind_cubes) self.assertEqual(self.wind_speed_cube, result[0]) self.assertEqual(self.wind_dir_cube, result[1]) self.assertEqual(2, len(result)) mocked_maybe_coerce.assert_called_once()
def test_list_two_valid(self): """Tests that one cube is loaded from each list.""" func = create_constrained_inputcubelist_converter( lambda cube: cube.name() in ["airspeed_velocity_of_unladen_swallow", "wind_speed"], lambda cube: cube.name() in ["direction_of_swallow", "wind_from_direction"], ) result = func(self.wind_cubes) self.assertEqual(self.wind_speed_cube, result[0]) self.assertEqual(self.wind_dir_cube, result[1]) self.assertEqual(2, len(result))
def test_list_two_diff_shapes(self): """Tests that one cube is loaded from each list when the two lists are different sizes. """ func = create_constrained_inputcubelist_converter( "wind_speed", lambda cube: cube.name() in ["direction_of_swallow", "wind_from_direction"], ) result = func(self.wind_cubes) self.assertEqual(self.wind_speed_cube, result[0]) self.assertEqual(self.wind_dir_cube, result[1]) self.assertEqual(2, len(result))
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Script to extrapolate input data given advection velocity fields.""" from improver import cli # Creates the value_converter that clize needs. inputadvection = cli.create_constrained_inputcubelist_converter( lambda cube: cube.name( ) in ["precipitation_advection_x_velocity", "grid_eastward_wind"], lambda cube: cube.name() in ["precipitation_advection_y_velocity", "grid_northward_wind"], ) @cli.clizefy @cli.with_output def process( cube: cli.inputcube, advection_velocity: inputadvection, orographic_enhancement: cli.inputcube = None, *, attributes_config: cli.inputjson = None, max_lead_time: int = 360, lead_time_interval: int = 15, ):
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Script to extrapolate input data given advection velocity fields.""" from improver import cli # Creates the value_converter that clize needs. inputadvection = cli.create_constrained_inputcubelist_converter( ['precipitation_advection_x_velocity', 'grid_eastward_wind'], ['precipitation_advection_y_velocity', 'grid_northward_wind']) @cli.clizefy @cli.with_output def process(cube: cli.inputcube, advection_velocity: inputadvection, orographic_enhancement: cli.inputcube = None, *, attributes_config: cli.inputjson = None, max_lead_time: int = 360, lead_time_interval: int = 15): """Module to extrapolate input cubes given advection velocity fields. Args: cube (iris.cube.Cube):
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Script to apply coefficients for Ensemble Model Output Statistics (EMOS), otherwise known as Non-homogeneous Gaussian Regression (NGR).""" from improver import cli # Creates the value_converter that clize needs. inputcoeffs = cli.create_constrained_inputcubelist_converter( "emos_coefficient_alpha", "emos_coefficient_beta", "emos_coefficient_gamma", "emos_coefficient_delta", ) @cli.clizefy @cli.with_output def process( cube: cli.inputcube, coefficients: inputcoeffs = None, land_sea_mask: cli.inputcube = None, *, realizations_count: int = None, randomise=False, random_seed: int = None, ignore_ecc_bounds=False,
def test_list_mismatching_lengths(self): """Tests that a list returns a function which itself returns 2 cubes""" obj = create_constrained_inputcubelist_converter( ['wind_speed', 'nonsense'], ['wind_from_direction']) result = obj(self.wind_cubes) self.assertEqual(result, self.wind_cubes)
def test_list_one_optional_constraint(self): """Tests that a list returns a function which itself returns 2 cubes""" obj = create_constrained_inputcubelist_converter( ['wind_speed', 'nonsense'], 'wind_from_direction') result = obj(self.wind_cubes) self.assertEqual(result, self.wind_cubes)
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Script to accumulate input data given advection velocity fields.""" from improver import cli # The accumulation frequency in minutes. ACCUMULATION_FIDELITY = 1 # Creates the value_converter that clize needs. inputadvection = cli.create_constrained_inputcubelist_converter( 'precipitation_advection_x_velocity', 'precipitation_advection_y_velocity') @cli.clizefy @cli.with_output def process(cube: cli.inputcube, advection_velocity: inputadvection, orographic_enhancement: cli.inputcube, *, attributes_config: cli.inputjson = None, max_lead_time=360, lead_time_interval=15, accumulation_period=15, accumulation_units='m'): """Module to extrapolate and accumulate the weather with 1 min fidelity.
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Module to apply a recursive filter to neighbourhooded data.""" from improver import cli input_smoothing_coefficients = cli.create_constrained_inputcubelist_converter( "smoothing_coefficient_x", "smoothing_coefficient_y", ) @cli.clizefy @cli.with_output def process( cube: cli.inputcube, smoothing_coefficients: input_smoothing_coefficients, mask: cli.inputcube = None, *, iterations: int = 1, remask=False, ): """Module to apply a recursive filter to neighbourhooded data.
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Module to apply a recursive filter to neighbourhooded data.""" from improver import cli input_smoothing_coefficients = cli.create_constrained_inputcubelist_converter( 'smoothing_coefficient_x', 'smoothing_coefficient_y') @cli.clizefy @cli.with_output def process(cube: cli.inputcube, smoothing_coefficients: input_smoothing_coefficients, mask: cli.inputcube = None, *, iterations: int = 1, remask=False): """Module to apply a recursive filter to neighbourhooded data. Run a recursive filter to convert a square neighbourhood into a Gaussian-like kernel or smooth over short distances. The filter uses a smoothing_coefficient (between 0 and 1) to control what proportion of the
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Script to calculate optical flow components as perturbations from model steering flow""" from improver import cli # Creates the value_converter that clize needs. inputflow = cli.create_constrained_inputcubelist_converter( "grid_eastward_wind", "grid_northward_wind", ) @cli.clizefy @cli.with_output def process( steering_flow: inputflow, orographic_enhancement: cli.inputcube, *cubes: cli.inputcube, ): """Calculate optical flow components as perturbations from the model steering flow. Advects the older of the two input radar observations to the validity time of the newer observation, then calculates the velocity required to adjust this forecast to match the observation. Sums the steering flow and perturbation values to give advection components for
will also have its data realised by the callable. """ def constraint(cube): ret = False if cube.name() in names: ret = True cube.data return ret return constraint # Creates the value_converter that clize needs. inputadvection = cli.create_constrained_inputcubelist_converter( name_constraint( ["precipitation_advection_x_velocity", "grid_eastward_wind"]), name_constraint( ["precipitation_advection_y_velocity", "grid_northward_wind"]), ) @cli.clizefy @cli.with_output def process( cube: cli.inputcube_nolazy, advection_velocity: inputadvection, orographic_enhancement: cli.inputcube_nolazy, *, attributes_config: cli.inputjson = None, max_lead_time=360, lead_time_interval=15, accumulation_period=15,
def test_list_no_match(self): """Tests that providing no valid constraints raises a ValueError.""" obj = create_constrained_inputcubelist_converter(['nonsense']) msg = 'Incorrect number of valid inputs available' with self.assertRaisesRegex(ValueError, msg): obj(self.wind_cubes)
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """Module to apply a recursive filter to neighbourhooded data.""" from improver import cli inputalphas = cli.create_constrained_inputcubelist_converter( 'alpha_x', 'alpha_y') @cli.clizefy @cli.with_output def process(cube: cli.inputcube, alphas: inputalphas, mask: cli.inputcube = None, *, iterations: int = 1, remask=False): """Module to apply a recursive filter to neighbourhooded data. Run a recursive filter to convert a square neighbourhood into a Gaussian-like kernel or smooth over short distances. The filter uses an alpha parameter (0 alpha < 1) to control what proportion of the