From dee2d90128eefe381ee70e0d1df05caf0d7304c6 Mon Sep 17 00:00:00 2001 From: marqh Date: Thu, 2 Mar 2017 20:15:35 +0000 Subject: [PATCH 1/2] Ensure tests work when installing from conda-forge channel --- conda-requirements.txt | 2 +- .../General/custom_file_loading.py | 4 +-- docs/iris/src/conf.py | 4 +-- lib/iris/coords.py | 24 +++++++++++-- lib/iris/fileformats/grib/__init__.py | 4 +-- lib/iris/tests/__init__.py | 28 +++++++-------- lib/iris/tests/idiff.py | 14 +++++++- .../tests/integration/plot/test_netcdftime.py | 18 ++++++---- .../results/analysis/rotated_pole.0.rlat.json | 1 + .../results/analysis/rotated_pole.0.rlon.json | 1 + .../results/analysis/rotated_pole.0.x.json | 1 + .../results/analysis/rotated_pole.0.y.json | 1 + .../results/analysis/rotated_pole.1.rlat.json | 1 + .../results/analysis/rotated_pole.1.rlon.json | 1 + .../results/analysis/rotated_pole.1.x.json | 1 + .../results/analysis/rotated_pole.1.y.json | 1 + .../results/analysis/weighted_mean_lat.cml | 2 +- .../results/analysis/weighted_mean_latlon.cml | 2 +- .../results/analysis/weighted_mean_lon.cml | 2 +- .../latitude_longitude_dual_stage.cml | 2 +- ...latitude_model_level_number_dual_stage.cml | 2 +- .../latitude_time_dual_stage.cml | 2 +- .../longitude_latitude_dual_stage.cml | 2 +- ...ongitude_model_level_number_dual_stage.cml | 2 +- .../longitude_time_dual_stage.cml | 2 +- ...model_level_number_latitude_dual_stage.cml | 2 +- ...odel_level_number_longitude_dual_stage.cml | 2 +- .../model_level_number_time_dual_stage.cml | 2 +- .../time_latitude_dual_stage.cml | 2 +- .../time_longitude_dual_stage.cml | 2 +- .../time_model_level_number_dual_stage.cml | 2 +- lib/iris/tests/results/imagerepo.json | 27 ++++----------- lib/iris/tests/test_analysis.py | 34 +++++++++++++------ lib/iris/tests/test_cdm.py | 10 +++++- lib/iris/tests/test_pandas.py | 28 ++++++++++----- .../test_add_categorised_coord.py | 7 +++- lib/iris/tests/unit/cube/test_Cube.py | 6 ++-- .../test_FieldCollation.py | 6 +++- minimal-conda-requirements.txt | 2 +- 39 files changed, 164 insertions(+), 92 deletions(-) create mode 100644 lib/iris/tests/results/analysis/rotated_pole.0.rlat.json create mode 100644 lib/iris/tests/results/analysis/rotated_pole.0.rlon.json create mode 100644 lib/iris/tests/results/analysis/rotated_pole.0.x.json create mode 100644 lib/iris/tests/results/analysis/rotated_pole.0.y.json create mode 100644 lib/iris/tests/results/analysis/rotated_pole.1.rlat.json create mode 100644 lib/iris/tests/results/analysis/rotated_pole.1.rlon.json create mode 100644 lib/iris/tests/results/analysis/rotated_pole.1.x.json create mode 100644 lib/iris/tests/results/analysis/rotated_pole.1.y.json diff --git a/conda-requirements.txt b/conda-requirements.txt index 3324c5fbc4..0c634d818c 100644 --- a/conda-requirements.txt +++ b/conda-requirements.txt @@ -4,7 +4,7 @@ # Mandatory dependencies biggus cartopy -matplotlib +matplotlib<1.9 netcdf4 numpy pyke diff --git a/docs/iris/example_code/General/custom_file_loading.py b/docs/iris/example_code/General/custom_file_loading.py index 27f037f06f..d6fddf8464 100644 --- a/docs/iris/example_code/General/custom_file_loading.py +++ b/docs/iris/example_code/General/custom_file_loading.py @@ -158,8 +158,8 @@ def load_NAME_III(filename): # Cast the x and y grid positions to floats and convert them to # zero based indices (the numbers are 1 based grid positions where # 0.5 represents half a grid point.) - x = float(vals[0]) - 1.5 - y = float(vals[1]) - 1.5 + x = int(float(vals[0]) - 1.5) + y = int(float(vals[1]) - 1.5) # Populate the data arrays (i.e. all columns but the leading 4). for i, data_array in enumerate(data_arrays): diff --git a/docs/iris/src/conf.py b/docs/iris/src/conf.py index 254ef464c0..b3db19d515 100644 --- a/docs/iris/src/conf.py +++ b/docs/iris/src/conf.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2016, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -56,7 +56,7 @@ # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage', - 'sphinx.ext.pngmath', + 'sphinx.ext.imgmath', 'sphinx.ext.autosummary', 'sphinx.ext.graphviz', 'sphinx.ext.intersphinx', diff --git a/lib/iris/coords.py b/lib/iris/coords.py index 20d4058b6a..e1a81533fc 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2016, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -329,7 +329,17 @@ def __common_cmp__(self, other, operator_method): me = min(self.bound) else: me = max(self.bound) - result = operator_method(me, other) + + # Hack to handle netcdftime.datetime comparison, which doesn't + # return NotImplemented on failure in some versions of the library + try: + result = operator_method(me, other) + except TypeError: + rop = {operator.lt: operator.gt, + operator.gt: operator.lt, + operator.le: operator.ge, + operator.ge: operator.le}[operator_method] + result = rop(other, me) return result @@ -492,7 +502,15 @@ def is_full_slice(s): raise IndexError('Cannot index with zero length ' 'slice.') if bounds is not None: - bounds = bounds[keys + (Ellipsis, )] + # Bounds will generally have an extra dimension compared + # to points, so add an Ellipsis at the end, unless there + # is already one, as numpy does not support double + # Ellipsis. + if (not isinstance(keys[-1], np.ndarray) and + keys[-1] == Ellipsis): + bounds = bounds[keys] + else: + bounds = bounds[keys + (Ellipsis, )] new_coord = self.copy(points=points, bounds=bounds) return new_coord diff --git a/lib/iris/fileformats/grib/__init__.py b/lib/iris/fileformats/grib/__init__.py index 3c06f62875..f31e20dd1f 100644 --- a/lib/iris/fileformats/grib/__init__.py +++ b/lib/iris/fileformats/grib/__init__.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2016, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -239,7 +239,7 @@ def __init__(self, grib_message, grib_fh=None, auto_regularise=True): # The byte offset requires to be reset back to the first byte # of this message. The file pointer offset is always at the end # of the current message due to the grib-api reading the message. - proxy = GribDataProxy(shape, np.zeros(.0).dtype, np.nan, + proxy = GribDataProxy(shape, np.zeros(0).dtype, np.nan, grib_fh.name, offset - message_length, auto_regularise) diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py index 8c730901b4..3c37c71043 100644 --- a/lib/iris/tests/__init__.py +++ b/lib/iris/tests/__init__.py @@ -295,7 +295,7 @@ def assertCMLApproxData(self, cubes, reference_filename=None, **kwargs): if fname[-1].endswith(".cml"): fname[-1] = fname[-1][:-4] fname[-1] += '.data.%d.json' % i - self.assertCubeDataAlmostEqual(cube, fname, **kwargs) + self.assertDataAlmostEqual(cube.data, fname, **kwargs) self.assertCML(cubes, reference_filename, checksum=False) def assertCDL(self, netcdf_filename, reference_filename=None, flags='-h'): @@ -407,36 +407,36 @@ def assertTextFile(self, source_filename, reference_filename, desc="text file"): diff = ''.join(difflib.unified_diff(reference_text, source_text, 'Reference', 'Test result', '', '', 0)) self.fail("%s does not match reference file: %s\n%s" % (desc, reference_filename, diff)) - def assertCubeDataAlmostEqual(self, cube, reference_filename, **kwargs): + def assertDataAlmostEqual(self, data, reference_filename, **kwargs): reference_path = self.get_result_path(reference_filename) if self._check_reference_file(reference_path): kwargs.setdefault('err_msg', 'Reference file %s' % reference_path) with open(reference_path, 'r') as reference_file: stats = json.load(reference_file) - self.assertEqual(stats.get('shape', []), list(cube.shape)) + self.assertEqual(stats.get('shape', []), list(data.shape)) self.assertEqual(stats.get('masked', False), - isinstance(cube.data, ma.MaskedArray)) + isinstance(data, ma.MaskedArray)) nstats = np.array((stats.get('mean', 0.), stats.get('std', 0.), stats.get('max', 0.), stats.get('min', 0.)), dtype=np.float_) if math.isnan(stats.get('mean', 0.)): - self.assertTrue(math.isnan(cube.data.mean())) + self.assertTrue(math.isnan(data.mean())) else: - cube_stats = np.array((cube.data.mean(), cube.data.std(), - cube.data.max(), cube.data.min()), + data_stats = np.array((data.mean(), data.std(), + data.max(), data.min()), dtype=np.float_) - self.assertArrayAllClose(nstats, cube_stats, **kwargs) + self.assertArrayAllClose(nstats, data_stats, **kwargs) else: self._ensure_folder(reference_path) logger.warning('Creating result file: %s', reference_path) masked = False - if isinstance(cube.data, ma.MaskedArray): + if isinstance(data, ma.MaskedArray): masked = True - stats = {'mean': np.float_(cube.data.mean()), - 'std': np.float_(cube.data.std()), - 'max': np.float_(cube.data.max()), - 'min': np.float_(cube.data.min()), - 'shape': cube.shape, 'masked': masked} + stats = {'mean': np.float_(data.mean()), + 'std': np.float_(data.std()), + 'max': np.float_(data.max()), + 'min': np.float_(data.min()), + 'shape': data.shape, 'masked': masked} with open(reference_path, 'w') as reference_file: reference_file.write(json.dumps(stats)) diff --git a/lib/iris/tests/idiff.py b/lib/iris/tests/idiff.py index e5b39b615e..919947196f 100755 --- a/lib/iris/tests/idiff.py +++ b/lib/iris/tests/idiff.py @@ -41,6 +41,7 @@ import matplotlib.pyplot as plt import matplotlib.image as mimg import matplotlib.testing.compare as mcompare +from matplotlib.testing.exceptions import ImageComparisonFailure import matplotlib.widgets as mwidget import numpy as np import requests @@ -236,7 +237,18 @@ def step_over_diffs(result_dir, action, display=True): # So copy the local file to the exected file to # maintain this helpfulness. shutil.copy(local_fname, expected_fname) - mcompare.compare_images(expected_fname, result_fname, tol=0) + try: + mcompare.compare_images(expected_fname, result_fname, + tol=0) + except Exception as e: + if isinstance(e, ValueError) or \ + isinstance(e, ImageComparisonFailure): + print('Could not compare {}: {}'.format(result_fname, + e.message)) + continue + else: + # Propagate the exception, keeping the stack trace + raise diff_fname = os.path.splitext(result_fname)[0] + _POSTFIX_DIFF args = expected_fname, result_fname, diff_fname if display: diff --git a/lib/iris/tests/integration/plot/test_netcdftime.py b/lib/iris/tests/integration/plot/test_netcdftime.py index ca6cf89a38..ea3cdd8d78 100644 --- a/lib/iris/tests/integration/plot/test_netcdftime.py +++ b/lib/iris/tests/integration/plot/test_netcdftime.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. # @@ -26,12 +26,15 @@ # importing anything else import iris.tests as tests +import netcdftime +import numpy as np + +from iris.coords import AuxCoord + from cf_units import Unit if tests.NC_TIME_AXIS_AVAILABLE: from nc_time_axis import CalendarDateTime -import numpy as np -from iris.coords import AuxCoord # Run tests in no graphics mode if matplotlib is not available. if tests.MPL_AVAILABLE: @@ -47,9 +50,12 @@ def test_360_day_calendar(self): calendar = '360_day' time_unit = Unit('days since 1970-01-01 00:00', calendar=calendar) time_coord = AuxCoord(np.arange(n), 'time', units=time_unit) - expected_ydata = np.array([CalendarDateTime(time_unit.num2date(point), - calendar) - for point in time_coord.points]) + times = [time_unit.num2date(point) for point in time_coord.points] + times = [netcdftime.datetime(atime.year, atime.month, atime.day, + atime.hour, atime.minute, atime.second) + for atime in times] + expected_ydata = np.array([CalendarDateTime(time, calendar) + for time in times]) line1, = iplt.plot(time_coord) result_ydata = line1.get_ydata() self.assertArrayEqual(expected_ydata, result_ydata) diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.rlat.json b/lib/iris/tests/results/analysis/rotated_pole.0.rlat.json new file mode 100644 index 0000000000..b09b1697d7 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.rlat.json @@ -0,0 +1 @@ +{"std": 3.7195861803241614, "min": -5.593200206756592, "max": 8.72130012512207, "shape": [93, 75], "masked": false, "mean": 1.6348200228305594} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.rlon.json b/lib/iris/tests/results/analysis/rotated_pole.0.rlon.json new file mode 100644 index 0000000000..cd1fe2fd52 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.rlon.json @@ -0,0 +1 @@ +{"std": 3.05635954577972, "min": 353.052490234375, "max": 365.08099365234375, "shape": [93, 75], "masked": false, "mean": 359.0960595703125} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.x.json b/lib/iris/tests/results/analysis/rotated_pole.0.x.json new file mode 100644 index 0000000000..7f09ca434f --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.x.json @@ -0,0 +1 @@ +{"std": 5.256882991869942, "min": -16.571169372070806, "max": 7.855481068868564, "shape": [93, 75], "masked": false, "mean": -4.045853791096988} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.0.y.json b/lib/iris/tests/results/analysis/rotated_pole.0.y.json new file mode 100644 index 0000000000..9f1fcef264 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.0.y.json @@ -0,0 +1 @@ +{"std": 3.711246685838892, "min": 46.42276494752364, "max": 61.22127069532664, "shape": [93, 75], "masked": false, "mean": 54.01432122690471} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.rlat.json b/lib/iris/tests/results/analysis/rotated_pole.1.rlat.json new file mode 100644 index 0000000000..612cb85e9a --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.rlat.json @@ -0,0 +1 @@ +{"std": 0.10904959181607428, "min": -1.732200026512146, "max": -1.3676999807357788, "shape": [28, 26], "masked": false, "mean": -1.5499499993664878} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.rlon.json b/lib/iris/tests/results/analysis/rotated_pole.1.rlon.json new file mode 100644 index 0000000000..18923a67f6 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.rlon.json @@ -0,0 +1 @@ +{"std": 0.10125036032780034, "min": 359.8294982910156, "max": 360.1669921875, "shape": [28, 26], "masked": false, "mean": 359.99824993426984} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.x.json b/lib/iris/tests/results/analysis/rotated_pole.1.x.json new file mode 100644 index 0000000000..c4fe081a1e --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.x.json @@ -0,0 +1 @@ +{"std": 0.16065754648082262, "min": -2.7716267023533385, "max": -2.233964274513027, "shape": [28, 26], "masked": false, "mean": -2.5027768780735946} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/rotated_pole.1.y.json b/lib/iris/tests/results/analysis/rotated_pole.1.y.json new file mode 100644 index 0000000000..501fe5e3a5 --- /dev/null +++ b/lib/iris/tests/results/analysis/rotated_pole.1.y.json @@ -0,0 +1 @@ +{"std": 0.10904936809954589, "min": 50.767481894563936, "max": 51.13229974298538, "shape": [28, 26], "masked": false, "mean": 50.94993734826177} \ No newline at end of file diff --git a/lib/iris/tests/results/analysis/weighted_mean_lat.cml b/lib/iris/tests/results/analysis/weighted_mean_lat.cml index 6c2076388e..fb8e032bc7 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_lat.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_lat.cml @@ -21,6 +21,6 @@ - + diff --git a/lib/iris/tests/results/analysis/weighted_mean_latlon.cml b/lib/iris/tests/results/analysis/weighted_mean_latlon.cml index bb2ea78521..738a622f00 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_latlon.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_latlon.cml @@ -22,6 +22,6 @@ - + diff --git a/lib/iris/tests/results/analysis/weighted_mean_lon.cml b/lib/iris/tests/results/analysis/weighted_mean_lon.cml index a45ade8bb6..8006e50759 100644 --- a/lib/iris/tests/results/analysis/weighted_mean_lon.cml +++ b/lib/iris/tests/results/analysis/weighted_mean_lon.cml @@ -21,6 +21,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml index 9a3d948c37..ca783b4563 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_longitude_dual_stage.cml @@ -93,6 +93,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml index 5e14bcc4af..ebfc3b6993 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_model_level_number_dual_stage.cml @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml index 5294b06a14..deeeb62db9 100644 --- a/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/latitude_time_dual_stage.cml @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml index 06884a3a79..4ce600dd3e 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_latitude_dual_stage.cml @@ -93,6 +93,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml index ab8593adab..07c31f985f 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_model_level_number_dual_stage.cml @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml index 346bf6a6f7..6f420545f4 100644 --- a/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/longitude_time_dual_stage.cml @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml index 4e365d3621..02fd20f6f8 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_latitude_dual_stage.cml @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml index 21d27cf04e..3db2d1acc9 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_longitude_dual_stage.cml @@ -55,6 +55,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml index 5b410d8e30..9e8fbff56f 100644 --- a/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/model_level_number_time_dual_stage.cml @@ -61,6 +61,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml index 310b74eeca..5dd1f6eb3c 100644 --- a/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_latitude_dual_stage.cml @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml index 4f440b8d9c..a92352ca43 100644 --- a/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_longitude_dual_stage.cml @@ -99,6 +99,6 @@ - + diff --git a/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml b/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml index 0d27de62e7..8c6ca19bdb 100644 --- a/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml +++ b/lib/iris/tests/results/cube_collapsed/time_model_level_number_dual_stage.cml @@ -61,6 +61,6 @@ - + diff --git a/lib/iris/tests/results/imagerepo.json b/lib/iris/tests/results/imagerepo.json index 9b95de4325..202ecbd1d0 100644 --- a/lib/iris/tests/results/imagerepo.json +++ b/lib/iris/tests/results/imagerepo.json @@ -85,12 +85,14 @@ ], "example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.0": [ "https://scitools.github.io/test-iris-imagehash/images/5fa1f298a1580c27336eb3d08d9e4c3ae563a60d931cd3d2728e7939ede4ad03.png", - "https://scitools.github.io/test-iris-imagehash/images/5fa3f298a1580c27336eb3d08d9e4c3aed61a60d931cd3d2728e7939e9e4ad03.png" + "https://scitools.github.io/test-iris-imagehash/images/5fa3f298a1580c27336eb3d08d9e4c3aed61a60d931cd3d2728e7939e9e4ad03.png", + "https://scitools.github.io/test-iris-imagehash/images/5fa17298a1580c27336eb3d08d9e4c3aed63260d931cd3d273ce7939ecc5ad03.png" ], "example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.1": [ "https://scitools.github.io/test-iris-imagehash/images/c7a196b9391c69464ec28cf1b3b55abe63db2549976d9926c9b643982e8da149.png", "https://scitools.github.io/test-iris-imagehash/images/c7a196b9391c694e4ec28cf1b1b55abe63da25499d6c9926d9b643da26c9a149.png", - "https://scitools.github.io/test-iris-imagehash/images/c7a196b9391c69464ec28cf1b3b55abe63db25499d6c9926d9b6439a26c9a149.png" + "https://scitools.github.io/test-iris-imagehash/images/c7a196b9391c69464ec28cf1b3b55abe63db25499d6c9926d9b6439a26c9a149.png", + "https://scitools.github.io/test-iris-imagehash/images/c7a1d699391c694e4ec28cf1b1b55aae69da25499f6d9926db3263da2689a149.png" ], "example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.0": [ "https://scitools.github.io/test-iris-imagehash/images/5fa8867ae985c9b5837a7881235f7c2db90c817e7ca0837edea599e4817e7880.png" @@ -123,24 +125,6 @@ "iris.tests.test_analysis.TestProject.test_cartopy_projection.0": [ "https://scitools.github.io/test-iris-imagehash/images/79984a9383a62d3f6651b9e28362b85e06df74a17c2d64bd46bf4439f92083b6.png" ], - "iris.tests.test_analysis.TestRotatedPole.test_all.0": [ - "https://scitools.github.io/test-iris-imagehash/images/8717167e79e8e181690879198671595a8ee096f61fe286f513868675e78cd957.png", - "https://scitools.github.io/test-iris-imagehash/images/8717167e79e8e181690879198671595a9ee016f61fe286e513c68675e78cd957.png" - ], - "iris.tests.test_analysis.TestRotatedPole.test_all.1": [ - "https://scitools.github.io/test-iris-imagehash/images/97a696a26959e93f6959695916e2695996a216c686a29687a9b896d769287a5d.png", - "https://scitools.github.io/test-iris-imagehash/images/97a696a26959e92f6959695916e2695996a216c686a296c6a9b8965769387b5d.png", - "https://scitools.github.io/test-iris-imagehash/images/97a696a26959e9af6959695916e2695996a216c686a296c6a9a8965769297b5d.png" - ], - "iris.tests.test_analysis.TestRotatedPole.test_all.2": [ - "https://scitools.github.io/test-iris-imagehash/images/572b0ba0a15701aaa15e01aa5ee87a055ea8fe552b80f45f2b80fe55a1bffe55.png", - "https://scitools.github.io/test-iris-imagehash/images/570f09a0e9f081aae9f007aa16aa1ebd16aa7c5d0b82fc5f2b007e05a1fffe15.png" - ], - "iris.tests.test_analysis.TestRotatedPole.test_all.3": [ - "https://scitools.github.io/test-iris-imagehash/images/577aa55aeb95a5524ba5a5525ee8a4521ee8f4560ba0f4572b007e55a13f5e15.png", - "https://scitools.github.io/test-iris-imagehash/images/577aa152eb95a5524ba5a5525ee8a4561ee8f4560ba8f4572b007e55a13f5e15.png", - "https://scitools.github.io/test-iris-imagehash/images/577aa152ab95a5524ba5a5525ee8a4561ee8f4570be8f4572b005e55a13f5e15.png" - ], "iris.tests.test_mapping.TestBasic.test_contourf.0": [ "https://scitools.github.io/test-iris-imagehash/images/175a963369b54987c99369cca1497938c38159b3679ba6737666d60c1c76a68d.png" ], @@ -728,7 +712,8 @@ "iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_not_reference_time_units.0": [ "https://scitools.github.io/test-iris-imagehash/images/415f85e9fefb91e94600bb6f07009be7effa1966ab065b273b009b663b007a04.png", "https://scitools.github.io/test-iris-imagehash/images/411d85e9fefb91e14600bb6707009be7effe1966ab06fb273b009b663f007a04.png", - "https://scitools.github.io/test-iris-imagehash/images/411f85e9fefb91e14600bb6f07009be7effe1966ab067b273b009b663b007a04.png" + "https://scitools.github.io/test-iris-imagehash/images/411f85e9fefb91e14600bb6f07009be7effe1966ab067b273b009b663b007a04.png", + "https://scitools.github.io/test-iris-imagehash/images/411f85e9fefb91e14600bb6707009be7effe1966ab06fb273b00bb263b007a04.png" ], "iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_reference_time_units.0": [ "https://scitools.github.io/test-iris-imagehash/images/417f8119feebeeff070054bb2b0014a0bb157ba6bb972b46dabf3b0419827b04.png", diff --git a/lib/iris/tests/test_analysis.py b/lib/iris/tests/test_analysis.py index c496fd5774..7b5f32dc6c 100644 --- a/lib/iris/tests/test_analysis.py +++ b/lib/iris/tests/test_analysis.py @@ -123,15 +123,25 @@ def test_weighted_mean_little(self): self.assertCML(cube, ('analysis', 'weighted_mean_source.cml')) a = cube.collapsed('lat', iris.analysis.MEAN, weights=weights) + # np.ma.average doesn't apply type promotion rules in some versions, + # and instead makes the result type float64. To ignore that case we + # fix up the dtype here if it is promotable from float32. We still want + # to catch cases where there is a loss of precision however. + if a.dtype > np.float32: + a.data = a.data.astype(np.float32) self.assertCMLApproxData(a, ('analysis', 'weighted_mean_lat.cml')) b = cube.collapsed(lon_coord, iris.analysis.MEAN, weights=weights) + if b.dtype > np.float32: + b.data = b.data.astype(np.float32) b.data = np.asarray(b.data) self.assertCMLApproxData(b, ('analysis', 'weighted_mean_lon.cml')) self.assertEqual(b.coord('dummy').shape, (1, )) # test collapsing multiple coordinates (and the fact that one of the coordinates isn't the same coordinate instance as on the cube) c = cube.collapsed([lat_coord[:], lon_coord], iris.analysis.MEAN, weights=weights) + if c.dtype > np.float32: + c.data = c.data.astype(np.float32) self.assertCMLApproxData(c, ('analysis', 'weighted_mean_latlon.cml')) self.assertEqual(c.coord('dummy').shape, (1, )) @@ -534,19 +544,23 @@ def test_weighted_rms(self): @tests.skip_data -class TestRotatedPole(tests.GraphicsTest): - @tests.skip_plot - def _check_both_conversions(self, cube): +class TestRotatedPole(tests.IrisTest): + def _check_both_conversions(self, cube, index): rlons, rlats = iris.analysis.cartography.get_xy_grids(cube) rcs = cube.coord_system('RotatedGeogCS') x, y = iris.analysis.cartography.unrotate_pole( rlons, rlats, rcs.grid_north_pole_longitude, rcs.grid_north_pole_latitude) - plt.scatter(x, y) - self.check_graphic() - - plt.scatter(rlons, rlats) - self.check_graphic() + self.assertDataAlmostEqual(x, ('analysis', + 'rotated_pole.{}.x.json'.format(index))) + self.assertDataAlmostEqual(y, ('analysis', + 'rotated_pole.{}.y.json'.format(index))) + self.assertDataAlmostEqual(rlons, + ('analysis', + 'rotated_pole.{}.rlon.json'.format(index))) + self.assertDataAlmostEqual(rlats, + ('analysis', + 'rotated_pole.{}.rlat.json'.format(index))) def test_all(self): path = tests.get_data_path(('PP', 'ukVorog', 'ukv_orog_refonly.pp')) @@ -554,11 +568,11 @@ def test_all(self): # Check overall behaviour. cube = master_cube[::10, ::10] - self._check_both_conversions(cube) + self._check_both_conversions(cube, 0) # Check numerical stability. cube = master_cube[210:238, 424:450] - self._check_both_conversions(cube) + self._check_both_conversions(cube, 1) def test_unrotate_nd(self): rlons = np.array([[350., 352.], [350., 352.]]) diff --git a/lib/iris/tests/test_cdm.py b/lib/iris/tests/test_cdm.py index 2c09cff948..4491a1838c 100644 --- a/lib/iris/tests/test_cdm.py +++ b/lib/iris/tests/test_cdm.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2010 - 2016, Met Office +# (C) British Crown Copyright 2010 - 2017, Met Office # # This file is part of Iris. # @@ -1024,9 +1024,17 @@ def collapse_test_common(self, cube, a_name, b_name, *args, **kwargs): # compare dual and single stage collapsing dual_stage = cube.collapsed(a_name, iris.analysis.MEAN) dual_stage = dual_stage.collapsed(b_name, iris.analysis.MEAN) + # np.ma.average doesn't apply type promotion rules in some versions, + # and instead makes the result type float64. To ignore that case we + # fix up the dtype here if it is promotable from cube.dtype. We still + # want to catch cases where there is a loss of precision however. + if dual_stage.dtype > cube.dtype: + dual_stage.data = dual_stage.data.astype(cube.dtype) self.assertCMLApproxData(dual_stage, ('cube_collapsed', '%s_%s_dual_stage.cml' % (a_filename, b_filename)), *args, **kwargs) single_stage = cube.collapsed([a_name, b_name], iris.analysis.MEAN) + if single_stage.dtype > cube.dtype: + single_stage.data = single_stage.data.astype(cube.dtype) self.assertCMLApproxData(single_stage, ('cube_collapsed', '%s_%s_single_stage.cml' % (a_filename, b_filename)), *args, **kwargs) # Compare the cube bits that should match diff --git a/lib/iris/tests/test_pandas.py b/lib/iris/tests/test_pandas.py index 56b2c20e53..abe680b318 100644 --- a/lib/iris/tests/test_pandas.py +++ b/lib/iris/tests/test_pandas.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2016, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -28,6 +28,7 @@ import cf_units import matplotlib.units +import netCDF4 import netcdftime import numpy as np @@ -100,11 +101,18 @@ def test_time_360(self): time_coord = DimCoord([0, 100.1, 200.2, 300.3, 400.4], long_name="time", units=time_unit) cube.add_dim_coord(time_coord, 0) - expected_index = [netcdftime.datetime(2000, 1, 1, 0, 0), - netcdftime.datetime(2000, 4, 11, 2, 24), - netcdftime.datetime(2000, 7, 21, 4, 48), - netcdftime.datetime(2000, 11, 1, 7, 12), - netcdftime.datetime(2001, 2, 11, 9, 36)] + if netCDF4.__version__ > '1.2.4': + expected_index = [netcdftime.Datetime360Day(2000, 1, 1, 0, 0), + netcdftime.Datetime360Day(2000, 4, 11, 2, 24), + netcdftime.Datetime360Day(2000, 7, 21, 4, 48), + netcdftime.Datetime360Day(2000, 11, 1, 7, 12), + netcdftime.Datetime360Day(2001, 2, 11, 9, 36)] + else: + expected_index = [netcdftime.datetime(2000, 1, 1, 0, 0), + netcdftime.datetime(2000, 4, 11, 2, 24), + netcdftime.datetime(2000, 7, 21, 4, 48), + netcdftime.datetime(2000, 11, 1, 7, 12), + netcdftime.datetime(2001, 2, 11, 9, 36)] series = iris.pandas.as_series(cube) self.assertArrayEqual(series, cube.data) self.assertArrayEqual(series.index, expected_index) @@ -236,8 +244,12 @@ def test_time_360(self): time_coord = DimCoord([100.1, 200.2], long_name="time", units=time_unit) cube.add_dim_coord(time_coord, 0) - expected_index = [netcdftime.datetime(2000, 4, 11, 2, 24), - netcdftime.datetime(2000, 7, 21, 4, 48)] + if netCDF4.__version__ > '1.2.4': + expected_index = [netcdftime.Datetime360Day(2000, 4, 11, 2, 24), + netcdftime.Datetime360Day(2000, 7, 21, 4, 48)] + else: + expected_index = [netcdftime.datetime(2000, 4, 11, 2, 24), + netcdftime.datetime(2000, 7, 21, 4, 48)] expected_columns = [0, 1, 2, 3, 4] data_frame = iris.pandas.as_data_frame(cube) self.assertArrayEqual(data_frame, cube.data) diff --git a/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py b/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py index de21b9a0eb..7f2aa1a721 100644 --- a/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py +++ b/lib/iris/tests/unit/coord_categorisation/test_add_categorised_coord.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2016, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -116,6 +116,11 @@ def make_cube(self, calendar): def test_calendars(self): for calendar in calendars: + # Skip the Julian calendar due to + # https://github.com/Unidata/netcdftime/issues/13 + # Remove this if block once the issue is resolved. + if calendar == 'julian': + continue cube = self.make_cube(calendar) add_day_of_year(cube, 'time') points = cube.coord('day_of_year').points diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py index 1b421f3c33..a1625d2a03 100644 --- a/lib/iris/tests/unit/cube/test_Cube.py +++ b/lib/iris/tests/unit/cube/test_Cube.py @@ -1,4 +1,4 @@ -# (C) British Crown Copyright 2013 - 2016, Met Office +# (C) British Crown Copyright 2013 - 2017, Met Office # # This file is part of Iris. # @@ -542,7 +542,7 @@ def test_nodimension(self): def create_cube(lon_min, lon_max, bounds=False): n_lons = max(lon_min, lon_max) - min(lon_max, lon_min) - data = np.arange(4 * 3 * n_lons, dtype='f4').reshape(4, 3, n_lons) + data = np.arange(4 * 3 * n_lons, dtype='f4').reshape(4, 3, -1) data = biggus.NumpyArrayAdapter(data) cube = Cube(data, standard_name='x_wind', units='ms-1') cube.add_dim_coord(iris.coords.DimCoord([0, 20, 40, 80], @@ -560,7 +560,7 @@ def create_cube(lon_min, lon_max, bounds=False): if bounds: cube.coord('longitude').guess_bounds() cube.add_aux_coord(iris.coords.AuxCoord( - np.arange(3 * n_lons).reshape(3, n_lons) * 10, 'surface_altitude', + np.arange(3 * n_lons).reshape(3, -1) * 10, 'surface_altitude', units='m'), [1, 2]) cube.add_aux_factory(iris.aux_factory.HybridHeightFactory( cube.coord('level_height'), cube.coord('sigma'), diff --git a/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_FieldCollation.py b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_FieldCollation.py index e2ae06292d..76b81de669 100644 --- a/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_FieldCollation.py +++ b/lib/iris/tests/unit/fileformats/um/fast_load_structured_fields/test_FieldCollation.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. # @@ -52,8 +52,12 @@ def _make_field(lbyr=None, lbyrd=None, lbft=None, header = [0] * 64 if lbyr is not None: header[0] = lbyr + header[1] = 1 + header[2] = 1 if lbyrd is not None: header[6] = lbyrd + header[7] = 1 + header[8] = 1 if lbft is not None: header[13] = lbft if blev is not None: diff --git a/minimal-conda-requirements.txt b/minimal-conda-requirements.txt index 5299e438e9..5a2b385ff4 100644 --- a/minimal-conda-requirements.txt +++ b/minimal-conda-requirements.txt @@ -4,7 +4,7 @@ # Mandatory dependencies biggus cartopy -matplotlib +matplotlib<1.9 netcdf4 numpy pyke From 5c97da0fc0aa783f784e50960e1db01bf9407d7b Mon Sep 17 00:00:00 2001 From: marqh Date: Mon, 3 Apr 2017 14:08:07 +0000 Subject: [PATCH 2/2] Update coords.py --- lib/iris/coords.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/iris/coords.py b/lib/iris/coords.py index e1a81533fc..77dab6ba3f 100644 --- a/lib/iris/coords.py +++ b/lib/iris/coords.py @@ -330,7 +330,7 @@ def __common_cmp__(self, other, operator_method): else: me = max(self.bound) - # Hack to handle netcdftime.datetime comparison, which doesn't + # Work around to handle netcdftime.datetime comparison, which doesn't # return NotImplemented on failure in some versions of the library try: result = operator_method(me, other)