diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py
index b54cabc3ef..df21a8cd76 100644
--- a/lib/iris/analysis/__init__.py
+++ b/lib/iris/analysis/__init__.py
@@ -2490,8 +2490,3 @@ def regridder(self, src_cube, target_grid):
from iris.analysis.trajectory import \
UnstructuredNearestNeigbourRegridder
return UnstructuredNearestNeigbourRegridder(src_cube, target_grid)
-
-
-# Import "iris.analysis.interpolate" to replicate older automatic imports.
-# NOTE: do this at end, as otherwise its import of 'Linear' will fail.
-from . import _interpolate_backdoor as interpolate
diff --git a/lib/iris/analysis/_interpolate_backdoor.py b/lib/iris/analysis/_interpolate_backdoor.py
deleted file mode 100644
index c7392fc0f6..0000000000
--- a/lib/iris/analysis/_interpolate_backdoor.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# (C) British Crown Copyright 2010 - 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 .
-"""
-Interpolation and re-gridding routines.
-
-The core definitions of the now deprecated 'iris.analysis.interpolate', with
-added deprecation wrappers.
-
-These contents are exposed as 'iris.analysis.interpolate', which is
-automatically available when 'iris.analysis' is imported.
-This is provided *only* because removing the automatic import broke some user
-code -- even though reliance on automatic imports is accepted bad practice.
-
-The "real" module 'iris.analysis.interpolate' can also be explicitly
-imported, and provides exactly the same definitions.
-The only difference is that the explicit import *itself* emits a deprecation
-warning.
-
-"""
-
-from __future__ import (absolute_import, division, print_function)
-from six.moves import (filter, input, map, range, zip) # noqa
-import six
-
-import collections
-from functools import wraps
-
-import numpy as np
-import scipy
-import scipy.spatial
-from scipy.interpolate.interpolate import interp1d
-
-from iris._deprecation import (warn_deprecated as iris_warn_deprecated,
- ClassWrapperSameDocstring)
-from iris.analysis import Linear
-import iris.cube
-import iris.coord_systems
-import iris.coords
-import iris.exceptions
-from . import _interpolate_private as _interp
-
-
-_INTERPOLATE_DEPRECATION_WARNING = \
- "The module 'iris.analysis.interpolate' is deprecated."
-
-
-# Define a common callpoint for deprecation warnings.
-def _warn_deprecated(msg=None):
- if msg is None:
- msg = _INTERPOLATE_DEPRECATION_WARNING
- iris_warn_deprecated(msg)
diff --git a/lib/iris/analysis/_interpolate_private.py b/lib/iris/analysis/_interpolate_private.py
deleted file mode 100644
index d928800767..0000000000
--- a/lib/iris/analysis/_interpolate_private.py
+++ /dev/null
@@ -1,251 +0,0 @@
-# (C) British Crown Copyright 2010 - 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 .
-"""
-This is the 'original' content of :mod:`iris.analysis.interpolate`, which has
-now been deprecated.
-
-A rename was essential to provide a deprecation warning on import of the
-original name, while still providing this code for internal usage (for now)
-without triggering the deprecation notice.
-
-"""
-
-from __future__ import (absolute_import, division, print_function)
-from six.moves import (filter, input, map, range, zip) # noqa
-import six
-
-import collections
-import warnings
-
-import numpy as np
-import scipy
-import scipy.spatial
-from scipy.interpolate.interpolate import interp1d
-
-from iris.analysis import Linear
-import iris.cube
-import iris.coord_systems
-import iris.coords
-from iris._deprecation import warn_deprecated
-import iris.exceptions
-
-
-def linear(cube, sample_points, extrapolation_mode='linear'):
- """
- Return a cube of the linearly interpolated points given the desired
- sample points.
-
- Given a list of tuple pairs mapping coordinates (or coordinate names)
- to their desired values, return a cube with linearly interpolated values.
- If more than one coordinate is specified, the linear interpolation will be
- carried out in sequence, thus providing n-linear interpolation
- (bi-linear, tri-linear, etc.).
-
- If the input cube's data is masked, the result cube will have a data
- mask interpolated to the new sample points
-
- .. testsetup::
-
- import numpy as np
-
- For example:
-
- >>> cube = iris.load_cube(iris.sample_data_path('air_temp.pp'))
- >>> sample_points = [('latitude', np.linspace(-90, 90, 10)),
- ... ('longitude', np.linspace(-180, 180, 20))]
- >>> iris.analysis.interpolate.linear(cube, sample_points)
-
-
- .. note::
-
- By definition, linear interpolation requires all coordinates to
- be 1-dimensional.
-
- .. note::
-
- If a specified coordinate is single valued its value will be
- extrapolated to the desired sample points by assuming a gradient of
- zero.
-
- Args:
-
- * cube
- The cube to be interpolated.
-
- * sample_points
- List of one or more tuple pairs mapping coordinate to desired
- points to interpolate. Points may be a scalar or a numpy array
- of values. Multi-dimensional coordinates are not supported.
-
- Kwargs:
-
- * extrapolation_mode - string - one of 'linear', 'nan' or 'error'
-
- * If 'linear' the point will be calculated by extending the
- gradient of closest two points.
- * If 'nan' the extrapolation point will be put as a NaN.
- * If 'error' a value error will be raised notifying of the
- attempted extrapolation.
-
- .. note::
-
- If the source cube's data, or any of its resampled coordinates,
- have an integer data type they will be promoted to a floating
- point data type in the result.
-
- .. deprecated:: 1.10
-
- The module :mod:`iris.analysis.interpolate` is deprecated.
- Please replace usage of
- :func:`iris.analysis.interpolate.linear`
- with :meth:`iris.cube.Cube.interpolate` using the scheme
- :class:`iris.analysis.Linear`.
-
- """
- if isinstance(sample_points, dict):
- sample_points = list(sample_points.items())
-
- # catch the case where a user passes a single (coord/name, value) pair rather than a list of pairs
- if sample_points and not (isinstance(sample_points[0], collections.Container) and not isinstance(sample_points[0], six.string_types)):
- raise TypeError('Expecting the sample points to be a list of tuple pairs representing (coord, points), got a list of %s.' % type(sample_points[0]))
-
- scheme = Linear(extrapolation_mode)
- return cube.interpolate(sample_points, scheme)
-
-
-def _interp1d_rolls_y():
- """
- Determines if :class:`scipy.interpolate.interp1d` rolls its array `y` by
- comparing the shape of y passed into interp1d to the shape of its internal
- representation of y.
-
- SciPy v0.13.x+ no longer rolls the axis of its internal representation
- of y so we test for this occurring to prevent us subsequently
- extrapolating along the wrong axis.
-
- For further information on this change see, for example:
- * https://github.com/scipy/scipy/commit/0d906d0fc54388464603c63119b9e35c9a9c4601
- (the commit that introduced the change in behaviour).
- * https://github.com/scipy/scipy/issues/2621
- (a discussion on the change - note the issue is not resolved
- at time of writing).
-
- """
- y = np.arange(12).reshape(3, 4)
- f = interp1d(np.arange(3), y, axis=0)
- # If the initial shape of y and the shape internal to interp1d are *not*
- # the same then scipy.interp1d rolls y.
- return y.shape != f.y.shape
-
-
-class Linear1dExtrapolator(object):
- """
- Extension class to :class:`scipy.interpolate.interp1d` to provide linear extrapolation.
-
- See also: :mod:`scipy.interpolate`.
-
- .. deprecated :: 1.10
-
- """
- roll_y = _interp1d_rolls_y()
-
- def __init__(self, interpolator):
- """
- Given an already created :class:`scipy.interpolate.interp1d` instance, return a callable object
- which supports linear extrapolation.
-
- .. deprecated :: 1.10
-
- """
- self._interpolator = interpolator
- self.x = interpolator.x
- # Store the y values given to the interpolator.
- self.y = interpolator.y
- """
- The y values given to the interpolator object.
-
- .. note:: These are stored with the interpolator.axis last.
-
- """
- # Roll interpolator.axis to the end if scipy no longer does it for us.
- if not self.roll_y:
- self.y = np.rollaxis(self.y, self._interpolator.axis, self.y.ndim)
-
- def all_points_in_range(self, requested_x):
- """Given the x points, do all of the points sit inside the interpolation range."""
- test = (requested_x >= self.x[0]) & (requested_x <= self.x[-1])
- if isinstance(test, np.ndarray):
- test = test.all()
- return test
-
- def __call__(self, requested_x):
- if not self.all_points_in_range(requested_x):
- # cast requested_x to a numpy array if it is not already.
- if not isinstance(requested_x, np.ndarray):
- requested_x = np.array(requested_x)
-
- # we need to catch the special case of providing a single value...
- remember_that_i_was_0d = requested_x.ndim == 0
-
- requested_x = requested_x.flatten()
-
- gt = np.where(requested_x > self.x[-1])[0]
- lt = np.where(requested_x < self.x[0])[0]
- ok = np.where( (requested_x >= self.x[0]) & (requested_x <= self.x[-1]) )[0]
-
- data_shape = list(self.y.shape)
- data_shape[-1] = len(requested_x)
- result = np.empty(data_shape, dtype=self._interpolator(self.x[0]).dtype)
-
- # Make a variable to represent the slice into the resultant data. (This will be updated in each of gt, lt & ok)
- interpolator_result_index = [slice(None, None)] * self.y.ndim
-
- if len(ok) != 0:
- interpolator_result_index[-1] = ok
-
- r = self._interpolator(requested_x[ok])
- # Reshape the properly formed array to put the interpolator.axis last i.e. dims 0, 1, 2 -> 0, 2, 1 if axis = 1
- axes = list(range(r.ndim))
- del axes[self._interpolator.axis]
- axes.append(self._interpolator.axis)
-
- result[interpolator_result_index] = r.transpose(axes)
-
- if len(lt) != 0:
- interpolator_result_index[-1] = lt
-
- grad = (self.y[..., 1:2] - self.y[..., 0:1]) / (self.x[1] - self.x[0])
- result[interpolator_result_index] = self.y[..., 0:1] + (requested_x[lt] - self.x[0]) * grad
-
- if len(gt) != 0:
- interpolator_result_index[-1] = gt
-
- grad = (self.y[..., -1:] - self.y[..., -2:-1]) / (self.x[-1] - self.x[-2])
- result[interpolator_result_index] = self.y[..., -1:] + (requested_x[gt] - self.x[-1]) * grad
-
- axes = list(range(len(interpolator_result_index)))
- axes.insert(self._interpolator.axis, axes.pop(axes[-1]))
- result = result.transpose(axes)
-
- if remember_that_i_was_0d:
- new_shape = list(result.shape)
- del new_shape[self._interpolator.axis]
- result = result.reshape(new_shape)
-
- return result
- else:
- return self._interpolator(requested_x)
diff --git a/lib/iris/cube.py b/lib/iris/cube.py
index 1301ebf57d..b38ec55035 100644
--- a/lib/iris/cube.py
+++ b/lib/iris/cube.py
@@ -46,7 +46,6 @@
import iris.analysis
from iris.analysis.cartography import wrap_lons
import iris.analysis.maths
-import iris.analysis._interpolate_private
import iris.aux_factory
import iris.coord_systems
import iris.coords
diff --git a/lib/iris/tests/test_coding_standards.py b/lib/iris/tests/test_coding_standards.py
index f90d25e323..a6631c72a4 100644
--- a/lib/iris/tests/test_coding_standards.py
+++ b/lib/iris/tests/test_coding_standards.py
@@ -82,7 +82,6 @@
class StandardReportWithExclusions(pep8.StandardReport):
expected_bad_files = [
'*/iris/std_names.py',
- '*/iris/analysis/_interpolate_private.py',
'*/iris/fileformats/cf.py',
'*/iris/fileformats/dot.py',
'*/iris/fileformats/grib/_grib_cf_map.py',
diff --git a/lib/iris/tests/unit/analysis/interpolate_private/__init__.py b/lib/iris/tests/unit/analysis/interpolate_private/__init__.py
deleted file mode 100644
index bb8f1ebc4a..0000000000
--- a/lib/iris/tests/unit/analysis/interpolate_private/__init__.py
+++ /dev/null
@@ -1,20 +0,0 @@
-# (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 .
-"""Unit tests for the :mod:`iris.analysis._interpolate_private` module."""
-
-from __future__ import (absolute_import, division, print_function)
-from six.moves import (filter, input, map, range, zip) # noqa