From 7c101e0cc233354d858a788ff423078702223ec6 Mon Sep 17 00:00:00 2001 From: lbdreyer Date: Fri, 7 Jul 2017 11:41:13 +0100 Subject: [PATCH 1/5] Remove iris.experimental.fieldsfiles module --- lib/iris/experimental/fieldsfile.py | 281 --------------- .../tests/experimental/test_fieldsfile.py | 65 ---- .../unit/experimental/fieldsfile/__init__.py | 20 -- .../fieldsfile/test__convert_collation.py | 325 ------------------ 4 files changed, 691 deletions(-) delete mode 100644 lib/iris/tests/experimental/test_fieldsfile.py delete mode 100644 lib/iris/tests/unit/experimental/fieldsfile/__init__.py delete mode 100644 lib/iris/tests/unit/experimental/fieldsfile/test__convert_collation.py diff --git a/lib/iris/experimental/fieldsfile.py b/lib/iris/experimental/fieldsfile.py index 42c99216f4..e69de29bb2 100644 --- a/lib/iris/experimental/fieldsfile.py +++ b/lib/iris/experimental/fieldsfile.py @@ -1,281 +0,0 @@ -# (C) British Crown Copyright 2014 - 2017, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -High-speed loading of structured FieldsFiles. - -.. deprecated:: 1.10 - - This module has now been *deprecated*. - Please use :mod:`iris.fileformats.um.structured_um_loading` instead. - -""" -from __future__ import (absolute_import, division, print_function) -from six.moves import (filter, input, map, range, zip) # noqa - -import os - -from iris._deprecation import warn_deprecated - -# Issue a deprecation message when the module is loaded. -warn_deprecated("The module 'iris.experimental.fieldsfile' is deprecated. " - "Please use iris.fileformats.um.structured_um_loading" - "as a replacement.") - -from iris.coords import DimCoord -from iris.cube import CubeList -from iris.exceptions import TranslationError -from iris.fileformats import FORMAT_AGENT -from iris.fileformats.um import um_to_pp -from iris.fileformats.pp import load as pp_load -from iris.fileformats.pp_rules import (_convert_time_coords, - _convert_vertical_coords, - _convert_scalar_realization_coords, - _convert_scalar_pseudo_level_coords, - _all_other_rules) -from iris.fileformats.rules import ConversionMetadata, Loader, load_cubes -from iris.fileformats.um._fast_load_structured_fields import \ - group_structured_fields - - -# Seed the preferred order of candidate dimension coordinates. -_HINT_COORDS = ['time', 'forecast_reference_time', 'model_level_number'] -_HINTS = {name: i for i, name in zip(range(len(_HINT_COORDS)), _HINT_COORDS)} - -_FF_SPEC_NAME = 'UM Fieldsfile' -_PP_SPEC_NAME = 'UM Post Processing file' - - -def _structured_loader(fname): - with open(fname, 'rb') as fh: - spec = FORMAT_AGENT.get_spec(os.path.basename(fname), fh) - if spec.name.startswith(_FF_SPEC_NAME): - result = um_to_pp - elif spec.name.startswith(_PP_SPEC_NAME): - result = pp_load - else: - emsg = 'Require {!r} to be a structured FieldsFile or a PP file.' - raise ValueError(emsg.format(fname)) - return result - - -def _collations_from_filename(filename): - loader = _structured_loader(filename) - fields = iter(loader(filename)) - return group_structured_fields(fields) - - -def load(filenames, callback=None): - """ - Load structured FieldsFiles and PP files. - - Args: - - * filenames: - One or more filenames. - - - Kwargs: - - * callback: - A modifier/filter function. Please see the module documentation - for :mod:`iris`. - - .. note:: - - Unlike the standard :func:`iris.load` operation, the callback is - applied to the final result cubes, not individual input fields. - - Returns: - An :class:`iris.cube.CubeList`. - - - This is a streamlined load operation, to be used only on fieldsfiles or PP - files whose fields repeat regularly over the same vertical levels and - times. The results aim to be equivalent to those generated by - :func:`iris.load`, but the operation is substantially faster for input that - is structured. - - The structured input files should conform to the following requirements: - - * the file must contain fields for all possible combinations of the - vertical levels and time points found in the file. - - * the fields must occur in a regular repeating order within the file. - - (For example: a sequence of fields for NV vertical levels, repeated - for NP different forecast periods, repeated for NT different forecast - times). - - * all other metadata must be identical across all fields of the same - phenomenon. - - Each group of fields with the same values of LBUSER4, LBUSER7 and LBPROC - is identified as a separate phenomenon: These groups are processed - independently and returned as separate result cubes. - - .. note:: - - Each input file is loaded independently. Thus a single result cube can - not combine data from multiple input files. - - .. note:: - - The resulting time-related coordinates ('time', 'forecast_time' and - 'forecast_period') may be mapped to shared cube dimensions and in some - cases can also be multidimensional. However, the vertical level - information *must* have a simple one-dimensional structure, independent - of the time points, otherwise an error will be raised. - - .. note:: - - Where input data does *not* have a fully regular arrangement, the - corresponding result cube will have a single anonymous extra dimension - which indexes over all the input fields. - - This can happen if, for example, some fields are missing; or have - slightly different metadata; or appear out of order in the file. - - .. warning:: - - Any non-regular metadata variation in the input should be strictly - avoided, as not all irregularities are detected, which can cause - erroneous results. - - - """ - warn_deprecated( - "The module 'iris.experimental.fieldsfile' is deprecated. " - "Please use the 'iris.fileformats.um.structured_um_loading' facility " - "as a replacement." - "\nA call to 'iris.experimental.fieldsfile.load' can be replaced with " - "'iris.load_raw', within a 'structured_um_loading' context.") - loader = Loader(_collations_from_filename, {}, _convert_collation) - return CubeList(load_cubes(filenames, callback, loader, None)) - - -def _adjust_dims(coords_and_dims, n_dims): - def adjust(dims): - if dims is not None: - dims += n_dims - return dims - return [(coord, adjust(dims)) for coord, dims in coords_and_dims] - - -def _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, - aux_coords_and_dims): - def key_func(item): - return _HINTS.get(item[0].name(), len(_HINTS)) - # Target the first DimCoord for a dimension at dim_coords, - # and target everything else at aux_coords. - for coord, dims in sorted(coords_and_dims, key=key_func): - if (isinstance(coord, DimCoord) and dims is not None and - len(dims) == 1 and dims[0] not in dim_coord_dims): - dim_coords_and_dims.append((coord, dims)) - dim_coord_dims.add(dims[0]) - else: - aux_coords_and_dims.append((coord, dims)) - - -def _convert_collation(collation): - """ - Converts a FieldCollation into the corresponding items of Cube - metadata. - - Args: - - * collation: - A FieldCollation object. - - Returns: - A :class:`iris.fileformats.rules.ConversionMetadata` object. - - """ - # For all the scalar conversions all fields in the collation will - # give the same result, so the choice is arbitrary. - field = collation.fields[0] - - # All the "other" rules. - (references, standard_name, long_name, units, attributes, cell_methods, - dim_coords_and_dims, aux_coords_and_dims) = _all_other_rules(field) - - # Adjust any dimension bindings to account for the extra leading - # dimensions added by the collation. - if collation.vector_dims_shape: - n_collation_dims = len(collation.vector_dims_shape) - dim_coords_and_dims = _adjust_dims(dim_coords_and_dims, - n_collation_dims) - aux_coords_and_dims = _adjust_dims(aux_coords_and_dims, - n_collation_dims) - - # "Normal" (non-cross-sectional) time values - vector_headers = collation.element_arrays_and_dims - # If the collation doesn't define a vector of values for a - # particular header then it must be constant over all fields in the - # collation. In which case it's safe to get the value from any field. - t1, t1_dims = vector_headers.get('t1', (field.t1, ())) - t2, t2_dims = vector_headers.get('t2', (field.t2, ())) - lbft, lbft_dims = vector_headers.get('lbft', (field.lbft, ())) - coords_and_dims = _convert_time_coords(field.lbcode, field.lbtim, - field.time_unit('hours'), - t1, t2, lbft, - t1_dims, t2_dims, lbft_dims) - dim_coord_dims = set() - _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, - aux_coords_and_dims) - - # "Normal" (non-cross-sectional) vertical levels - blev, blev_dims = vector_headers.get('blev', (field.blev, ())) - lblev, lblev_dims = vector_headers.get('lblev', (field.lblev, ())) - bhlev, bhlev_dims = vector_headers.get('bhlev', (field.bhlev, ())) - bhrlev, bhrlev_dims = vector_headers.get('bhrlev', (field.bhrlev, ())) - brsvd1, brsvd1_dims = vector_headers.get('brsvd1', (field.brsvd[0], ())) - brsvd2, brsvd2_dims = vector_headers.get('brsvd2', (field.brsvd[1], ())) - brlev, brlev_dims = vector_headers.get('brlev', (field.brlev, ())) - # Find all the non-trivial dimension values - dims = set(filter(None, [blev_dims, lblev_dims, bhlev_dims, bhrlev_dims, - brsvd1_dims, brsvd2_dims, brlev_dims])) - if len(dims) > 1: - raise TranslationError('Unsupported multiple values for vertical ' - 'dimension.') - if dims: - v_dims = dims.pop() - if len(v_dims) > 1: - raise TranslationError('Unsupported multi-dimension vertical ' - 'headers.') - else: - v_dims = () - coords_and_dims, factories = _convert_vertical_coords(field.lbcode, - field.lbvc, - blev, lblev, - field.stash, - bhlev, bhrlev, - brsvd1, brsvd2, - brlev, v_dims) - _bind_coords(coords_and_dims, dim_coord_dims, dim_coords_and_dims, - aux_coords_and_dims) - - # Realization (aka ensemble) (--> scalar coordinates) - aux_coords_and_dims.extend(_convert_scalar_realization_coords( - lbrsvd4=field.lbrsvd[3])) - - # Pseudo-level coordinate (--> scalar coordinates) - aux_coords_and_dims.extend(_convert_scalar_pseudo_level_coords( - lbuser5=field.lbuser[4])) - - return ConversionMetadata(factories, references, standard_name, long_name, - units, attributes, cell_methods, - dim_coords_and_dims, aux_coords_and_dims) diff --git a/lib/iris/tests/experimental/test_fieldsfile.py b/lib/iris/tests/experimental/test_fieldsfile.py deleted file mode 100644 index c97eb2ef94..0000000000 --- a/lib/iris/tests/experimental/test_fieldsfile.py +++ /dev/null @@ -1,65 +0,0 @@ -# (C) British Crown Copyright 2014 - 2016, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -""" -Test the fast loading of structured Fieldsfiles. - -""" - -from __future__ import (absolute_import, division, print_function) -from six.moves import (filter, input, map, range, zip) # noqa - -# import iris tests first so that some things can be initialised before -# importing anything else -import iris.tests as tests - -from iris.experimental.fieldsfile import load - - -@tests.skip_data -class TestStructuredLoadFF(tests.IrisTest): - def setUp(self): - self.fname = tests.get_data_path(('FF', 'structured', 'small')) - - def test_simple(self): - cube, = load(self.fname) - self.assertCML(cube) - - def test_simple_callback(self): - def callback(cube, field, filename): - cube.attributes['processing'] = 'fast-ff' - cube, = load(self.fname, callback=callback) - self.assertCML(cube) - - -@tests.skip_data -class TestStructuredLoadPP(tests.IrisTest): - def setUp(self): - self.fname = tests.get_data_path(('PP', 'structured', 'small.pp')) - - def test_simple(self): - [cube] = load(self.fname) - self.assertCML(cube) - - def test_simple_callback(self): - def callback(cube, field, filename): - cube.attributes['processing'] = 'fast-pp' - [cube] = load(self.fname, callback=callback) - self.assertCML(cube) - - -if __name__ == "__main__": - tests.main() diff --git a/lib/iris/tests/unit/experimental/fieldsfile/__init__.py b/lib/iris/tests/unit/experimental/fieldsfile/__init__.py deleted file mode 100644 index 8513b08fdb..0000000000 --- a/lib/iris/tests/unit/experimental/fieldsfile/__init__.py +++ /dev/null @@ -1,20 +0,0 @@ -# (C) British Crown Copyright 2014 - 2015, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for :mod:`iris.experimental.fieldsfile`.""" - -from __future__ import (absolute_import, division, print_function) -from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/experimental/fieldsfile/test__convert_collation.py b/lib/iris/tests/unit/experimental/fieldsfile/test__convert_collation.py deleted file mode 100644 index d8edbc3df7..0000000000 --- a/lib/iris/tests/unit/experimental/fieldsfile/test__convert_collation.py +++ /dev/null @@ -1,325 +0,0 @@ -# (C) British Crown Copyright 2014 - 2015, Met Office -# -# This file is part of Iris. -# -# Iris is free software: you can redistribute it and/or modify it under -# the terms of the GNU Lesser General Public License as published by the -# Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# Iris is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with Iris. If not, see . -"""Unit tests for :func:`iris.experimental.fieldsfile._convert_collation`.""" - -from __future__ import (absolute_import, division, print_function) -from six.moves import (filter, input, map, range, zip) # noqa - -# Import iris.tests first so that some things can be initialised before -# importing anything else. -import iris.tests as tests - -import cf_units -import netcdftime -import numpy as np - -from iris.experimental.fieldsfile \ - import _convert_collation as convert_collation -import iris.aux_factory -import iris.coord_systems -import iris.coords -import iris.fileformats.pp -import iris.fileformats.rules -from iris.tests import mock - - -COORD_SYSTEM = iris.coord_systems.GeogCS(6371229.0) -LATITUDE = iris.coords.DimCoord([15, 0, -15], 'latitude', units='degrees', - coord_system=COORD_SYSTEM) -LONGITUDE = iris.coords.DimCoord([0, 20, 40, 60], 'longitude', units='degrees', - coord_system=COORD_SYSTEM, circular=True) - - -class Test(tests.IrisTest): - def _field(self): - # Create PP field for X wind on a regular lat-lon grid. - header = [0] * 64 - # Define the regular lat-lon grid. - header[15] = 1 # LBCODE - header[17] = 3 # LBROW - header[18] = 4 # LBNPT - header[55] = 90 # BPLAT - header[58] = 30 # BZY - header[59] = -15 # BDY - header[60] = -20 # BZX - header[61] = 20 # BDX - # Define the STASH code m01s00i002. - header[41] = 2 # LBUSER(4) - header[44] = 1 # LBUSER(7) - field = iris.fileformats.pp.PPField3(header) - return field - - def _check_phenomenon(self, metadata, factory=None): - if factory is None: - self.assertEqual(metadata.factories, []) - else: - self.assertEqual(metadata.factories, [factory]) - self.assertEqual(metadata.references, []) - self.assertEqual(metadata.standard_name, 'x_wind') - self.assertIsNone(metadata.long_name) - self.assertEqual(metadata.units, cf_units.Unit('m s-1')) - self.assertEqual(metadata.attributes, {'STASH': (1, 0, 2)}) - self.assertEqual(metadata.cell_methods, []) - - def test_all_scalar(self): - field = self._field() - field.lbtim = 11 - field.t1 = netcdftime.datetime(1970, 1, 1, 18) - field.t2 = netcdftime.datetime(1970, 1, 1, 12) - collation = mock.Mock(fields=[field], vector_dims_shape=(), - element_arrays_and_dims={}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - coords_and_dims = [(LONGITUDE, 1), - (LATITUDE, 0)] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [ - (iris.coords.DimCoord(18, 'time', units='hours since epoch'), - None), - (iris.coords.DimCoord(12, 'forecast_reference_time', - units='hours since epoch'), None), - (iris.coords.DimCoord(6, 'forecast_period', units='hours'), None) - ] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_vector_t1(self): - field = self._field() - field.lbtim = 11 - field.t2 = netcdftime.datetime(1970, 1, 1, 12) - t1 = ([netcdftime.datetime(1970, 1, 1, 18), - netcdftime.datetime(1970, 1, 2, 0), - netcdftime.datetime(1970, 1, 2, 6)], [0]) - collation = mock.Mock(fields=[field], vector_dims_shape=(3,), - element_arrays_and_dims={'t1': t1}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - coords_and_dims = [(LONGITUDE, 2), - (LATITUDE, 1), - (iris.coords.DimCoord([18, 24, 30], 'time', - units='hours since epoch'), - (0,)) - ] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [ - (iris.coords.DimCoord(12, 'forecast_reference_time', - units='hours since epoch'), None), - (iris.coords.DimCoord([6, 12, 18], 'forecast_period', - units='hours'), (0,)) - ] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_vector_t2(self): - field = self._field() - field.lbtim = 11 - field.t1 = netcdftime.datetime(1970, 1, 1, 18) - t2 = ([netcdftime.datetime(1970, 1, 1, 12), - netcdftime.datetime(1970, 1, 1, 15), - netcdftime.datetime(1970, 1, 1, 18)], [0]) - collation = mock.Mock(fields=[field], vector_dims_shape=(3,), - element_arrays_and_dims={'t2': t2}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - coords_and_dims = [(LONGITUDE, 2), - (LATITUDE, 1), - (iris.coords.DimCoord([12, 15, 18], - 'forecast_reference_time', - units='hours since epoch'), - (0,)) - ] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [ - (iris.coords.DimCoord(18, 'time', units='hours since epoch'), - None), - (iris.coords.DimCoord([6, 3, 0.], 'forecast_period', - units='hours'), - (0,)) - ] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_vector_lbft(self): - field = self._field() - field.lbtim = 21 - field.t1 = netcdftime.datetime(1970, 1, 1, 12) - field.t2 = netcdftime.datetime(1970, 1, 1, 18) - lbft = ([18, 15, 12], [0]) - collation = mock.Mock(fields=[field], vector_dims_shape=(3,), - element_arrays_and_dims={'lbft': lbft}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - coords_and_dims = [(LONGITUDE, 2), - (LATITUDE, 1), - (iris.coords.DimCoord([0, 3, 6], - 'forecast_reference_time', - units='hours since epoch'), - (0,))] - coords_and_dims = [ - (iris.coords.DimCoord(15, 'time', units='hours since epoch', - bounds=[[12, 18]]), None), - (iris.coords.DimCoord([15, 12, 9], 'forecast_period', - units='hours', - bounds=[[12, 18], [9, 15], [6, 12]]), - (0,)) - ] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_vector_t1_and_t2(self): - field = self._field() - field.lbtim = 11 - t1 = ([netcdftime.datetime(1970, 1, 2, 6), - netcdftime.datetime(1970, 1, 2, 9), - netcdftime.datetime(1970, 1, 2, 12)], [1]) - t2 = ([netcdftime.datetime(1970, 1, 1, 12), - netcdftime.datetime(1970, 1, 2, 0)], [0]) - collation = mock.Mock(fields=[field], vector_dims_shape=(2, 3), - element_arrays_and_dims={'t1': t1, 't2': t2}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - coords_and_dims = [(LONGITUDE, 3), - (LATITUDE, 2), - (iris.coords.DimCoord([30, 33, 36], 'time', - units='hours since epoch'), - (1,)), - (iris.coords.DimCoord([12, 24], - 'forecast_reference_time', - units='hours since epoch'), - (0,))] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [ - (iris.coords.AuxCoord([[18, 21, 24], [6, 9, 12]], - 'forecast_period', units='hours'), (0, 1)) - ] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_vertical_pressure(self): - field = self._field() - field.lbvc = 8 - blev = ([1000, 850, 700], (0,)) - lblev = ([1000, 850, 700], (0,)) - collation = mock.Mock(fields=[field], vector_dims_shape=(3,), - element_arrays_and_dims={'blev': blev, - 'lblev': lblev}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - coords_and_dims = [(LONGITUDE, 2), - (LATITUDE, 1), - (iris.coords.DimCoord([1000, 850, 700], - long_name='pressure', - units='hPa'), - (0,))] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_soil_level(self): - field = self._field() - field.lbvc = 6 - points = [10, 20, 30] - lower = [0] * 3 - upper = [0] * 3 - lblev = (points, (0,)) - brsvd1 = (lower, (0,)) - brlev = (upper, (0,)) - collation = mock.Mock(fields=[field], vector_dims_shape=(3,), - element_arrays_and_dims={'lblev': lblev, - 'brsvd1': brsvd1, - 'brlev': brlev}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - level = iris.coords.DimCoord(points, - long_name='soil_model_level_number', - attributes={'positive': 'down'}) - coords_and_dims = [(LONGITUDE, 2), - (LATITUDE, 1), - (level, (0,))] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_soil_depth(self): - field = self._field() - field.lbvc = 6 - points = [10, 20, 30] - lower = [0, 15, 25] - upper = [15, 25, 35] - blev = (points, (0,)) - brsvd1 = (lower, (0,)) - brlev = (upper, (0,)) - collation = mock.Mock(fields=[field], vector_dims_shape=(3,), - element_arrays_and_dims={'blev': blev, - 'brsvd1': brsvd1, - 'brlev': brlev}) - metadata = convert_collation(collation) - self._check_phenomenon(metadata) - depth = iris.coords.DimCoord(points, standard_name='depth', - bounds=np.vstack((lower, upper)).T, - units='m', - attributes={'positive': 'down'}) - coords_and_dims = [(LONGITUDE, 2), - (LATITUDE, 1), - (depth, (0,))] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - def test_vertical_hybrid_height(self): - field = self._field() - field.lbvc = 65 - blev = ([5, 18, 38], (0,)) - lblev = ([1000, 850, 700], (0,)) - brsvd1 = ([10, 26, 50], (0,)) - brsvd2 = ([0.9989, 0.9970, 0.9944], (0,)) - brlev = ([0, 10, 26], (0,)) - bhrlev = ([1, 0.9989, 0.9970], (0,)) - lblev = ([1, 2, 3], (0,)) - bhlev = ([0.9994, 0.9979, 0.9957], (0,)) - collation = mock.Mock(fields=[field], vector_dims_shape=(3,), - element_arrays_and_dims={'blev': blev, - 'lblev': lblev, - 'brsvd1': brsvd1, - 'brsvd2': brsvd2, - 'brlev': brlev, - 'bhrlev': bhrlev, - 'lblev': lblev, - 'bhlev': bhlev}) - metadata = convert_collation(collation) - factory = iris.fileformats.rules.Factory( - iris.aux_factory.HybridHeightFactory, - [{'long_name': 'level_height'}, {'long_name': 'sigma'}, - iris.fileformats.rules.Reference('orography')]) - self._check_phenomenon(metadata, factory) - coords_and_dims = [(LONGITUDE, 2), - (LATITUDE, 1), - (iris.coords.DimCoord([1, 2, 3], - 'model_level_number', - attributes={'positive': 'up'} - ), - (0,))] - self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) - coords_and_dims = [ - (iris.coords.DimCoord([5, 18, 38], long_name='level_height', - units='m', bounds=[[0, 10], [10, 26], - [26, 50]], - attributes={'positive': 'up'}), (0,)), - (iris.coords.AuxCoord([0.9994, 0.9979, 0.9957], long_name='sigma', - bounds=[[1, 0.9989], [0.9989, 0.9970], - [0.9970, 0.9944]]), (0,)) - ] - self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) - - -if __name__ == '__main__': - tests.main() From c3d30e4b8dd2cc25bc8da26d84a44bb1a4a97f01 Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Tue, 10 Oct 2017 14:25:36 +0100 Subject: [PATCH 2/5] Review actions: keep and move existing test modules --- lib/iris/tests/integration/um/__init__.py | 20 ++ .../tests/integration/um/test_fieldsfile.py | 65 ++++ .../unit/fileformats/um/fast_load/__init__.py | 23 ++ .../um/fast_load/test__convert_collation.py | 325 ++++++++++++++++++ 4 files changed, 433 insertions(+) create mode 100644 lib/iris/tests/integration/um/__init__.py create mode 100644 lib/iris/tests/integration/um/test_fieldsfile.py create mode 100644 lib/iris/tests/unit/fileformats/um/fast_load/__init__.py create mode 100644 lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py diff --git a/lib/iris/tests/integration/um/__init__.py b/lib/iris/tests/integration/um/__init__.py new file mode 100644 index 0000000000..263abe4855 --- /dev/null +++ b/lib/iris/tests/integration/um/__init__.py @@ -0,0 +1,20 @@ +# (C) British Crown Copyright 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Integration tests for :mod:`iris.fileformats.um` fast load functions.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/integration/um/test_fieldsfile.py b/lib/iris/tests/integration/um/test_fieldsfile.py new file mode 100644 index 0000000000..6bf909881c --- /dev/null +++ b/lib/iris/tests/integration/um/test_fieldsfile.py @@ -0,0 +1,65 @@ +# (C) British Crown Copyright 2014 - 2016, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Test the fast loading of structured Fieldsfiles. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# import iris tests first so that some things can be initialised before +# importing anything else +import iris.tests as tests + +from iris.fileformats.um import load_cubes as load + + +@tests.skip_data +class TestStructuredLoadFF(tests.IrisTest): + def setUp(self): + self.fname = tests.get_data_path(('FF', 'structured', 'small')) + + def test_simple(self): + cube, = load(self.fname, None) + self.assertCML(cube) + + def test_simple_callback(self): + def callback(cube, field, filename): + cube.attributes['processing'] = 'fast-ff' + cube, = load(self.fname, callback=callback) + self.assertCML(cube) + + +@tests.skip_data +class TestStructuredLoadPP(tests.IrisTest): + def setUp(self): + self.fname = tests.get_data_path(('PP', 'structured', 'small.pp')) + + def test_simple(self): + [cube] = load(self.fname, None) + self.assertCML(cube) + + def test_simple_callback(self): + def callback(cube, field, filename): + cube.attributes['processing'] = 'fast-pp' + [cube] = load(self.fname, callback=callback) + self.assertCML(cube) + + +if __name__ == "__main__": + tests.main() diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py new file mode 100644 index 0000000000..9c26f321e4 --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py @@ -0,0 +1,23 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +""" +Unit tests for the module :mod:`iris.fileformats.um._fast_load`. + +""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py b/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py new file mode 100644 index 0000000000..3f6c9963fa --- /dev/null +++ b/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py @@ -0,0 +1,325 @@ +# (C) British Crown Copyright 2014 - 2015, Met Office +# +# This file is part of Iris. +# +# Iris is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the +# Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Iris is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Iris. If not, see . +"""Unit tests for :func:`iris.fileformats.um._fast_load._convert_collation`.""" + +from __future__ import (absolute_import, division, print_function) +from six.moves import (filter, input, map, range, zip) # noqa + +# Import iris.tests first so that some things can be initialised before +# importing anything else. +import iris.tests as tests + +import cf_units +import netcdftime +import numpy as np + +from iris.fileformats.um._fast_load \ + import _convert_collation as convert_collation +import iris.aux_factory +import iris.coord_systems +import iris.coords +import iris.fileformats.pp +import iris.fileformats.rules +from iris.tests import mock + + +COORD_SYSTEM = iris.coord_systems.GeogCS(6371229.0) +LATITUDE = iris.coords.DimCoord([15, 0, -15], 'latitude', units='degrees', + coord_system=COORD_SYSTEM) +LONGITUDE = iris.coords.DimCoord([0, 20, 40, 60], 'longitude', units='degrees', + coord_system=COORD_SYSTEM, circular=True) + + +class Test(tests.IrisTest): + def _field(self): + # Create PP field for X wind on a regular lat-lon grid. + header = [0] * 64 + # Define the regular lat-lon grid. + header[15] = 1 # LBCODE + header[17] = 3 # LBROW + header[18] = 4 # LBNPT + header[55] = 90 # BPLAT + header[58] = 30 # BZY + header[59] = -15 # BDY + header[60] = -20 # BZX + header[61] = 20 # BDX + # Define the STASH code m01s00i002. + header[41] = 2 # LBUSER(4) + header[44] = 1 # LBUSER(7) + field = iris.fileformats.pp.PPField3(header) + return field + + def _check_phenomenon(self, metadata, factory=None): + if factory is None: + self.assertEqual(metadata.factories, []) + else: + self.assertEqual(metadata.factories, [factory]) + self.assertEqual(metadata.references, []) + self.assertEqual(metadata.standard_name, 'x_wind') + self.assertIsNone(metadata.long_name) + self.assertEqual(metadata.units, cf_units.Unit('m s-1')) + self.assertEqual(metadata.attributes, {'STASH': (1, 0, 2)}) + self.assertEqual(metadata.cell_methods, []) + + def test_all_scalar(self): + field = self._field() + field.lbtim = 11 + field.t1 = netcdftime.datetime(1970, 1, 1, 18) + field.t2 = netcdftime.datetime(1970, 1, 1, 12) + collation = mock.Mock(fields=[field], vector_dims_shape=(), + element_arrays_and_dims={}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 1), + (LATITUDE, 0)] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord(18, 'time', units='hours since epoch'), + None), + (iris.coords.DimCoord(12, 'forecast_reference_time', + units='hours since epoch'), None), + (iris.coords.DimCoord(6, 'forecast_period', units='hours'), None) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_t1(self): + field = self._field() + field.lbtim = 11 + field.t2 = netcdftime.datetime(1970, 1, 1, 12) + t1 = ([netcdftime.datetime(1970, 1, 1, 18), + netcdftime.datetime(1970, 1, 2, 0), + netcdftime.datetime(1970, 1, 2, 6)], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'t1': t1}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([18, 24, 30], 'time', + units='hours since epoch'), + (0,)) + ] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord(12, 'forecast_reference_time', + units='hours since epoch'), None), + (iris.coords.DimCoord([6, 12, 18], 'forecast_period', + units='hours'), (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_t2(self): + field = self._field() + field.lbtim = 11 + field.t1 = netcdftime.datetime(1970, 1, 1, 18) + t2 = ([netcdftime.datetime(1970, 1, 1, 12), + netcdftime.datetime(1970, 1, 1, 15), + netcdftime.datetime(1970, 1, 1, 18)], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'t2': t2}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([12, 15, 18], + 'forecast_reference_time', + units='hours since epoch'), + (0,)) + ] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord(18, 'time', units='hours since epoch'), + None), + (iris.coords.DimCoord([6, 3, 0.], 'forecast_period', + units='hours'), + (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_lbft(self): + field = self._field() + field.lbtim = 21 + field.t1 = netcdftime.datetime(1970, 1, 1, 12) + field.t2 = netcdftime.datetime(1970, 1, 1, 18) + lbft = ([18, 15, 12], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'lbft': lbft}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([0, 3, 6], + 'forecast_reference_time', + units='hours since epoch'), + (0,))] + coords_and_dims = [ + (iris.coords.DimCoord(15, 'time', units='hours since epoch', + bounds=[[12, 18]]), None), + (iris.coords.DimCoord([15, 12, 9], 'forecast_period', + units='hours', + bounds=[[12, 18], [9, 15], [6, 12]]), + (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vector_t1_and_t2(self): + field = self._field() + field.lbtim = 11 + t1 = ([netcdftime.datetime(1970, 1, 2, 6), + netcdftime.datetime(1970, 1, 2, 9), + netcdftime.datetime(1970, 1, 2, 12)], [1]) + t2 = ([netcdftime.datetime(1970, 1, 1, 12), + netcdftime.datetime(1970, 1, 2, 0)], [0]) + collation = mock.Mock(fields=[field], vector_dims_shape=(2, 3), + element_arrays_and_dims={'t1': t1, 't2': t2}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 3), + (LATITUDE, 2), + (iris.coords.DimCoord([30, 33, 36], 'time', + units='hours since epoch'), + (1,)), + (iris.coords.DimCoord([12, 24], + 'forecast_reference_time', + units='hours since epoch'), + (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.AuxCoord([[18, 21, 24], [6, 9, 12]], + 'forecast_period', units='hours'), (0, 1)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vertical_pressure(self): + field = self._field() + field.lbvc = 8 + blev = ([1000, 850, 700], (0,)) + lblev = ([1000, 850, 700], (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'blev': blev, + 'lblev': lblev}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([1000, 850, 700], + long_name='pressure', + units='hPa'), + (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_soil_level(self): + field = self._field() + field.lbvc = 6 + points = [10, 20, 30] + lower = [0] * 3 + upper = [0] * 3 + lblev = (points, (0,)) + brsvd1 = (lower, (0,)) + brlev = (upper, (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'lblev': lblev, + 'brsvd1': brsvd1, + 'brlev': brlev}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + level = iris.coords.DimCoord(points, + long_name='soil_model_level_number', + attributes={'positive': 'down'}) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (level, (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_soil_depth(self): + field = self._field() + field.lbvc = 6 + points = [10, 20, 30] + lower = [0, 15, 25] + upper = [15, 25, 35] + blev = (points, (0,)) + brsvd1 = (lower, (0,)) + brlev = (upper, (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'blev': blev, + 'brsvd1': brsvd1, + 'brlev': brlev}) + metadata = convert_collation(collation) + self._check_phenomenon(metadata) + depth = iris.coords.DimCoord(points, standard_name='depth', + bounds=np.vstack((lower, upper)).T, + units='m', + attributes={'positive': 'down'}) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (depth, (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + def test_vertical_hybrid_height(self): + field = self._field() + field.lbvc = 65 + blev = ([5, 18, 38], (0,)) + lblev = ([1000, 850, 700], (0,)) + brsvd1 = ([10, 26, 50], (0,)) + brsvd2 = ([0.9989, 0.9970, 0.9944], (0,)) + brlev = ([0, 10, 26], (0,)) + bhrlev = ([1, 0.9989, 0.9970], (0,)) + lblev = ([1, 2, 3], (0,)) + bhlev = ([0.9994, 0.9979, 0.9957], (0,)) + collation = mock.Mock(fields=[field], vector_dims_shape=(3,), + element_arrays_and_dims={'blev': blev, + 'lblev': lblev, + 'brsvd1': brsvd1, + 'brsvd2': brsvd2, + 'brlev': brlev, + 'bhrlev': bhrlev, + 'lblev': lblev, + 'bhlev': bhlev}) + metadata = convert_collation(collation) + factory = iris.fileformats.rules.Factory( + iris.aux_factory.HybridHeightFactory, + [{'long_name': 'level_height'}, {'long_name': 'sigma'}, + iris.fileformats.rules.Reference('orography')]) + self._check_phenomenon(metadata, factory) + coords_and_dims = [(LONGITUDE, 2), + (LATITUDE, 1), + (iris.coords.DimCoord([1, 2, 3], + 'model_level_number', + attributes={'positive': 'up'} + ), + (0,))] + self.assertEqual(metadata.dim_coords_and_dims, coords_and_dims) + coords_and_dims = [ + (iris.coords.DimCoord([5, 18, 38], long_name='level_height', + units='m', bounds=[[0, 10], [10, 26], + [26, 50]], + attributes={'positive': 'up'}), (0,)), + (iris.coords.AuxCoord([0.9994, 0.9979, 0.9957], long_name='sigma', + bounds=[[1, 0.9989], [0.9989, 0.9970], + [0.9970, 0.9944]]), (0,)) + ] + self.assertEqual(metadata.aux_coords_and_dims, coords_and_dims) + + +if __name__ == '__main__': + tests.main() From 691a983c29e4d427bd98e2806adbfcbc14c81c71 Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Tue, 10 Oct 2017 16:31:55 +0100 Subject: [PATCH 3/5] Changes to get tests passing --- lib/iris/tests/integration/um/__init__.py | 2 +- lib/iris/tests/integration/um/test_fieldsfile.py | 10 +++++----- .../um}/fieldsfile/TestStructuredLoadFF/simple.cml | 0 .../TestStructuredLoadFF/simple_callback.cml | 0 .../um}/fieldsfile/TestStructuredLoadPP/simple.cml | 0 .../TestStructuredLoadPP/simple_callback.cml | 0 .../tests/unit/fileformats/um/fast_load/__init__.py | 2 +- .../um/fast_load/test__convert_collation.py | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) rename lib/iris/tests/results/{experimental => integration/um}/fieldsfile/TestStructuredLoadFF/simple.cml (100%) rename lib/iris/tests/results/{experimental => integration/um}/fieldsfile/TestStructuredLoadFF/simple_callback.cml (100%) rename lib/iris/tests/results/{experimental => integration/um}/fieldsfile/TestStructuredLoadPP/simple.cml (100%) rename lib/iris/tests/results/{experimental => integration/um}/fieldsfile/TestStructuredLoadPP/simple_callback.cml (100%) diff --git a/lib/iris/tests/integration/um/__init__.py b/lib/iris/tests/integration/um/__init__.py index 263abe4855..e012485f2c 100644 --- a/lib/iris/tests/integration/um/__init__.py +++ b/lib/iris/tests/integration/um/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2016, Met Office +# (C) British Crown Copyright 2016 - 2017, Met Office # # This file is part of Iris. # diff --git a/lib/iris/tests/integration/um/test_fieldsfile.py b/lib/iris/tests/integration/um/test_fieldsfile.py index 6bf909881c..8582ed62f3 100644 --- a/lib/iris/tests/integration/um/test_fieldsfile.py +++ b/lib/iris/tests/integration/um/test_fieldsfile.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014 - 2016, Met Office +# (C) British Crown Copyright 2014 - 2017, Met Office # # This file is part of Iris. # @@ -35,14 +35,14 @@ def setUp(self): self.fname = tests.get_data_path(('FF', 'structured', 'small')) def test_simple(self): - cube, = load(self.fname, None) - self.assertCML(cube) + cubes = list(load(self.fname, None)) + self.assertCML(cubes) def test_simple_callback(self): def callback(cube, field, filename): cube.attributes['processing'] = 'fast-ff' - cube, = load(self.fname, callback=callback) - self.assertCML(cube) + cubes = list(load(self.fname, callback=callback)) + self.assertCML(cubes) @tests.skip_data diff --git a/lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadFF/simple.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml similarity index 100% rename from lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadFF/simple.cml rename to lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml diff --git a/lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadFF/simple_callback.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml similarity index 100% rename from lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadFF/simple_callback.cml rename to lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml diff --git a/lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadPP/simple.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple.cml similarity index 100% rename from lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadPP/simple.cml rename to lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple.cml diff --git a/lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadPP/simple_callback.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple_callback.cml similarity index 100% rename from lib/iris/tests/results/experimental/fieldsfile/TestStructuredLoadPP/simple_callback.cml rename to lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadPP/simple_callback.cml diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py index 9c26f321e4..451e19c8d8 100644 --- a/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py +++ b/lib/iris/tests/unit/fileformats/um/fast_load/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014 - 2015, Met Office +# (C) British Crown Copyright 2014 - 2017, Met Office # # This file is part of Iris. # diff --git a/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py b/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py index 3f6c9963fa..78a9c5b8b5 100644 --- a/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py +++ b/lib/iris/tests/unit/fileformats/um/fast_load/test__convert_collation.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2014 - 2015, Met Office +# (C) British Crown Copyright 2014 - 2017, Met Office # # This file is part of Iris. # From d2daea47ee6eca6c9b580ee30a2ff9d3892db7b8 Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Wed, 11 Oct 2017 14:57:54 +0100 Subject: [PATCH 4/5] Common test result format --- lib/iris/experimental/fieldsfile.py | 0 lib/iris/tests/integration/um/test_fieldsfile.py | 15 +++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) delete mode 100644 lib/iris/experimental/fieldsfile.py diff --git a/lib/iris/experimental/fieldsfile.py b/lib/iris/experimental/fieldsfile.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/lib/iris/tests/integration/um/test_fieldsfile.py b/lib/iris/tests/integration/um/test_fieldsfile.py index 8582ed62f3..5f9a0c91c6 100644 --- a/lib/iris/tests/integration/um/test_fieldsfile.py +++ b/lib/iris/tests/integration/um/test_fieldsfile.py @@ -25,6 +25,7 @@ # import iris tests first so that some things can be initialised before # importing anything else import iris.tests as tests +from iris.cube import CubeList from iris.fileformats.um import load_cubes as load @@ -34,15 +35,21 @@ class TestStructuredLoadFF(tests.IrisTest): def setUp(self): self.fname = tests.get_data_path(('FF', 'structured', 'small')) + def _merge_cubes(self, cubes): + # Merge the 2D cubes returned by `iris.fileformats.um.load_cubes`. + return CubeList(cubes).merge_cube() + def test_simple(self): - cubes = list(load(self.fname, None)) - self.assertCML(cubes) + list_of_cubes = list(load(self.fname, None)) + cube = self._merge_cubes(list_of_cubes) + self.assertCML(cube) def test_simple_callback(self): def callback(cube, field, filename): cube.attributes['processing'] = 'fast-ff' - cubes = list(load(self.fname, callback=callback)) - self.assertCML(cubes) + list_of_cubes = list(load(self.fname, callback=callback)) + cube = self._merge_cubes(list_of_cubes) + self.assertCML(cube) @tests.skip_data From 2b1c57560afa52ead98e12d6f5bf596dff0485f9 Mon Sep 17 00:00:00 2001 From: Peter Killick Date: Thu, 12 Oct 2017 10:36:58 +0100 Subject: [PATCH 5/5] Update result files --- .../integration/um/fieldsfile/TestStructuredLoadFF/simple.cml | 2 +- .../um/fieldsfile/TestStructuredLoadFF/simple_callback.cml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml index 5cb0de933c..0c316bcfea 100644 --- a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml +++ b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple.cml @@ -54,7 +54,7 @@ - diff --git a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml index 62126aa03b..188c583b2a 100644 --- a/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml +++ b/lib/iris/tests/results/integration/um/fieldsfile/TestStructuredLoadFF/simple_callback.cml @@ -55,7 +55,7 @@ -