Skip to content
This repository was archived by the owner on Apr 27, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions agg_regrid/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) British Crown Copyright 2015 - 2018, Met Office
# (C) British Crown Copyright 2015 - 2019, Met Office
#
# This file is part of agg-regrid.
#
Expand Down Expand Up @@ -210,8 +210,14 @@ def __call__(self, src_cube):
sx_dim = src_cube.coord_dims(sx)[0]
sy_dim = src_cube.coord_dims(sy)[0]

# Manipulating masked arrays can be of the order 4-5 times slower,
# therefore use the underlying numpy array if there are no masked data
data = src_cube.data
if ma.isMA(data) and not ma.is_masked(data):
data = data.data

# Perform the regrid.
result = agg(src_cube.data, sx.points, self._sx_bounds,
result = agg(data, sx.points, self._sx_bounds,
sy.points, self._sy_bounds, sx_dim, sy_dim,
self._gx_bounds, self._gy_bounds, self.buffer_depth)

Expand Down Expand Up @@ -319,24 +325,22 @@ def agg(data, sx_points, sx_bounds, sy_points, sy_bounds,
raise ValueError(emsg.format(data.ndim))

# Account for negative indexing ...
dim = sx_dim
if sx_dim < 0:
sx_dim = ndim + sx_dim
sx_dim += ndim

if sx_dim not in dims:
emsg = 'Invalid src x-coordinate dimension, got {} expected ' \
'within range {}-{}.'
raise ValueError(emsg.format(dim, dims[0], dims[-1]))
raise ValueError(emsg.format(sx_dim, dims[0], dims[-1]))

# Account for negative indexing ...
dim = sy_dim
if sy_dim < 0:
sy_dim = ndim + sy_dim
sy_dim += ndim

if sy_dim not in dims:
emsg = 'Invalid src y-coordinate dimension, got {} expected ' \
'within range {}-{}.'
raise ValueError(emsg.format(dim, dims[0], dims[-1]))
raise ValueError(emsg.format(sy_dim, dims[0], dims[-1]))

# Determine the source data shape ...
shape = data.shape
Expand Down
11 changes: 11 additions & 0 deletions agg_regrid/tests/test_AreaWeighted.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,17 @@ def test_regridder(self):
expected = [mock.call(self.src, self.tgt, buffer_depth=self.depth)]
self.assertEqual(mocker.mock_calls, expected)

def test_regridder_with_buffer_depth(self):
depth = mock.sentinel.buffer_depth
regridder = 'agg_regrid._AreaWeightedRegridder'
with mock.patch(regridder, autospec=True,
return_value=self.regridder) as mocker:
scheme = AreaWeighted(buffer_depth=depth)
result = scheme.regridder(self.src, self.tgt)
self.assertEqual(result, self.regridder)
expected = [mock.call(self.src, self.tgt, buffer_depth=depth)]
self.assertEqual(mocker.mock_calls, expected)


if __name__ == '__main__':
unittest.main()
62 changes: 47 additions & 15 deletions agg_regrid/tests/test__AreadWeightedRegridder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) British Crown Copyright 2015 - 2018, Met Office
# (C) British Crown Copyright 2015 - 2019, Met Office
#
# This file is part of agg-regrid.
#
Expand Down Expand Up @@ -27,6 +27,7 @@
from unittest import mock
except ImportError:
import mock
import numpy.ma as ma

from agg_regrid import (_AreaWeightedRegridder as Regridder,
DEFAULT_BUFFER_DEPTH)
Expand Down Expand Up @@ -117,14 +118,12 @@ def setUp(self):
self.tgt_cube = mock.Mock(spec=iris.cube.Cube)
self.sx_dim = mock.sentinel.sx_dim
self.sy_dim = mock.sentinel.sy_dim
coord_dims = mock.Mock(side_effect=([self.sx_dim], [self.sy_dim]))
coord_dims = mock.Mock(side_effect=([self.sx_dim], [self.sy_dim],
[self.sx_dim], [self.sy_dim]))
self.metadata = dict(standard_name='air_pressure',
long_name='long_name', var_name='var_name',
units='Pa', attributes={}, cell_methods=())
self.data = mock.sentinel.data
self.cube = mock.Mock(spec=iris.cube.Cube, coord_dims=coord_dims,
metadata=self.metadata, dim_coords=(),
aux_coords=(), data=self.data)
scrs = mock.sentinel.scrs
self.sxp = mock.sentinel.sx_points
self.sxb = mock.sentinel.sx_contiguous_bounds
Expand All @@ -140,11 +139,19 @@ def setUp(self):
gx = mock.Mock(coord_system=tcrs)
gy = mock.Mock(coord_system=tcrs)
self.src_grid = (self.sx, self.sy)
tgt_grid = (gx, gy)
self.side_effect = (self.src_grid, tgt_grid)
self.tgt_grid = (gx, gy)
dim_coords = [self.sx, self.sy]
self.cube = mock.Mock(spec=iris.cube.Cube, coord_dims=coord_dims,
metadata=self.metadata, dim_coords=dim_coords,
aux_coords=(), data=self.data)
self.side_effect = (self.src_grid, self.tgt_grid)
self.gmesh = (mock.sentinel.gxx, mock.sentinel.gyy)
self.snapshot_grid = 'agg_regrid.snapshot_grid'
self.get_xy_dim_coords = 'agg_regrid.get_xy_dim_coords'
self.depth = DEFAULT_BUFFER_DEPTH
self.meshgrid = 'numpy.meshgrid'
self.agg = 'agg_regrid.agg'
self.add_dim_coord = 'iris.cube.Cube.add_dim_coord'
self.depth = mock.sentinel.buffer_depth

def test_bad_src_cube(self):
with mock.patch(self.snapshot_grid, side_effect=self.side_effect):
Expand Down Expand Up @@ -176,14 +183,16 @@ def test_same_crs(self):
with mock.patch(self.snapshot_grid, side_effect=side_effect):
with mock.patch(self.get_xy_dim_coords,
return_value=self.src_grid):
gxx, gyy = (mock.sentinel.gxx, mock.sentinel.gyy)
with mock.patch('numpy.meshgrid', return_value=(gxx, gyy)):
with mock.patch(self.meshgrid, return_value=self.gmesh):
data = 1
with mock.patch('agg_regrid.agg',
return_value=data) as magg:
regridder = Regridder(self.src_cube, self.tgt_cube)
result = regridder(self.cube)

with mock.patch(self.agg, return_value=data) as magg:
with mock.patch(self.add_dim_coord) as madd:
regridder = Regridder(self.src_cube,
self.tgt_cube,
buffer_depth=self.depth)
result = regridder(self.cube)

gxx, gyy = self.gmesh
self.assertEqual(regridder._sx_bounds, self.sxb)
self.assertEqual(regridder._sy_bounds, self.syb)
self.assertEqual(regridder._gx_bounds, gxx)
Expand All @@ -192,9 +201,32 @@ def test_same_crs(self):
self.syb, self.sx_dim, self.sy_dim, gxx, gyy,
self.depth)]
self.assertEqual(magg.call_args_list, expected)
expected = [mock.call(self.sx.copy(), [self.sx_dim]),
mock.call(self.sy.copy(), [self.sy_dim])]
self.assertEqual(madd.call_args_list, expected)
cube = iris.cube.Cube(data)
cube.metadata = self.metadata
self.assertEqual(result, cube)
self.assertEqual(regridder.buffer_depth, self.depth)

def test_masked_with_no_masked_points(self):
data = ma.arange(1)
self.cube.data = data
side_effect = (self.src_grid, self.src_grid)
with mock.patch(self.snapshot_grid, side_effect=side_effect):
with mock.patch(self.get_xy_dim_coords,
return_value=self.src_grid):
with mock.patch(self.meshgrid, return_value=self.gmesh):
with mock.patch(self.agg, return_value=1) as magg:
with mock.patch(self.add_dim_coord):
regridder = Regridder(self.src_cube, self.tgt_cube)
regridder(self.cube)

gxx, gyy = self.gmesh
expected = [mock.call(data.data, self.sxp, self.sxb, self.syp,
self.syb, self.sx_dim, self.sy_dim, gxx, gyy,
DEFAULT_BUFFER_DEPTH)]
self.assertEqual(magg.call_args_list, expected)


if __name__ == '__main__':
Expand Down