Skip to content
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
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/SOI_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ def low_pass_weights(window, cutoff):


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load the monthly-valued Southern Oscillation Index (SOI) time-series.
fname = iris.sample_data_path('SOI_Darwin.nc')
soi = iris.load_cube(fname)
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/anomaly_log_colouring.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load a sample air temperatures sequence.
file_path = iris.sample_data_path('E1_north_america.nc')
temperatures = iris.load_cube(file_path)
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/cross_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load some test data.
fname = iris.sample_data_path('hybrid_height.nc')
theta = iris.load_cube(fname, 'air_potential_temperature')
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/custom_aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ def count_spells(data, threshold, axis, spell_length):


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load the whole time-sequence as a single cube.
file_path = iris.sample_data_path('E1_north_america.nc')
cube = iris.load_cube(file_path)
Expand Down
4 changes: 1 addition & 3 deletions docs/iris/example_code/General/inset_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@


def main():
# Load the data
with iris.FUTURE.context(netcdf_promote=True):
cube1 = iris.load_cube(iris.sample_data_path('ostia_monthly.nc'))
cube1 = iris.load_cube(iris.sample_data_path('ostia_monthly.nc'))
# Slice into cube to retrieve data for the inset map showing the
# data region
region = cube1[-1, :, :]
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/orca_projection.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load data
filepath = iris.sample_data_path('orca2_votemper.nc')
cube = iris.load_cube(filepath)
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/polynomial_fit.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load some test data.
fname = iris.sample_data_path('A1B_north_america.nc')
cube = iris.load_cube(fname)
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/projections_and_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@ def make_plot(projection_name, projection_crs):


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Demonstrate with two different display projections.
make_plot('Equidistant Cylindrical', ccrs.PlateCarree())
make_plot('North Polar Stereographic', ccrs.NorthPolarStereo())
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/General/rotated_pole_mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load some test data.
fname = iris.sample_data_path('rotated_pole.nc')
air_pressure = iris.load_cube(fname)
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/Meteorology/COP_1d_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load data into three Cubes, one for each set of NetCDF files.
e1 = iris.load_cube(iris.sample_data_path('E1_north_america.nc'))

Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/Meteorology/TEC.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load the "total electron content" cube.
filename = iris.sample_data_path('space_weather.nc')
cube = iris.load_cube(filename, 'total electron content')
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/Meteorology/hovmoller.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# load a single cube of surface temperature between +/- 5 latitude
fname = iris.sample_data_path('ostia_monthly.nc')
cube = iris.load_cube(fname,
Expand Down
4 changes: 0 additions & 4 deletions docs/iris/example_code/Oceanography/atlantic_profiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@


def main():
# Enable a future option, to ensure that the netcdf load works the same way
# as in future Iris versions.
iris.FUTURE.netcdf_promote = True

# Load the gridded temperature and salinity data.
fname = iris.sample_data_path('atlantic_profiles.nc')
cubes = iris.load(fname)
Expand Down
3 changes: 2 additions & 1 deletion docs/iris/src/userguide/interpolation_and_regridding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ For instance, the :class:`iris.analysis.Linear` scheme requires 1D numeric,
monotonic, coordinates. Supposing we have a single column cube such as
the one defined below:

>>> column = iris.load_cube(iris.sample_data_path('hybrid_height.nc'))[:, 0, 0]
>>> cube = iris.load_cube(iris.sample_data_path('hybrid_height.nc'), 'air_potential_temperature')
>>> column = cube[:, 0, 0]
>>> print(column.summary(shorten=True))
air_potential_temperature / (K) (model_level_number: 15)

Expand Down
2 changes: 1 addition & 1 deletion docs/iris/src/userguide/real_and_lazy_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ coordinates' lazy points and bounds:

.. doctest::

>>> cube = iris.load_cube(iris.sample_data_path('hybrid_height.nc'))
>>> cube = iris.load_cube(iris.sample_data_path('hybrid_height.nc'), 'air_potential_temperature')

>>> dim_coord = cube.coord('model_level_number')
>>> print(dim_coord.has_lazy_points())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* Deprecated FUTURE flag :attr:`iris.Future.netcdf_promote`.

* Removed deprecated behaviour that does not automatically promote NetCDF variables to cubes.
This change means that NetCDF variables that define reference surfaces for dimensionless vertical coordinates
will always be promoted and loaded as independent cubes.
23 changes: 17 additions & 6 deletions lib/iris/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ def callback(cube, field, filename):
class Future(threading.local):
"""Run-time configuration controller."""

def __init__(self, cell_datetime_objects=True, netcdf_promote=False,
def __init__(self, cell_datetime_objects=True, netcdf_promote=True,
netcdf_no_unlimited=False, clip_latitudes=False):
"""
A container for run-time options controls.
Expand Down Expand Up @@ -172,9 +172,15 @@ def __init__(self, cell_datetime_objects=True, netcdf_promote=False,

For more details, see :ref:`using-time-constraints`.

The option `netcdf_promote` controls whether the netCDF loader
will expose variables which define reference surfaces for
dimensionless vertical coordinates as independent Cubes.
.. deprecated:: 2.0.0

The option `netcdf_promote` is deprecated and will be removed in a
future release and the deprecated code paths this option used to
toggle have been removed.

The option `netcdf_promote` controlled whether the netCDF loader
exposed variables that defined reference surfaces for
dimensionless vertical coordinates as independent Cubes.

The option `netcdf_no_unlimited`, when True, changes the
behaviour of the netCDF saver, such that no dimensions are set to
Expand All @@ -197,13 +203,18 @@ def __repr__(self):
return msg.format(self.cell_datetime_objects, self.netcdf_promote,
self.netcdf_no_unlimited, self.clip_latitudes)

deprecated_options = {'cell_datetime_objects': 'warning'}
deprecated_options = {'cell_datetime_objects': 'warning',
'netcdf_promote': 'error'}

def __setattr__(self, name, value):
if name in self.deprecated_options:
level = self.deprecated_options[name]
if level == 'error':
pass
emsg = ("setting the 'Future' property {prop!r} has been "
"deprecated to be removed in a future release, and "
"deprecated {prop!r} behaviour has been removed. "
"Please remove code that sets this property.")
raise AttributeError(emsg.format(prop=name))
else:
msg = ("setting the 'Future' property {!r} is deprecated "
"and will be removed in a future release. "
Expand Down
92 changes: 43 additions & 49 deletions lib/iris/fileformats/cf.py
Original file line number Diff line number Diff line change
Expand Up @@ -1008,9 +1008,14 @@ def _build(cf_variable):
for variable_type in self._variable_types:
# Prevent grid mapping variables being mis-identified as
# CF coordinate variables.
ignore = None if issubclass(variable_type, CFGridMappingVariable) else coordinate_names
match = variable_type.identify(self._dataset.variables, ignore=ignore,
target=cf_variable.cf_name, warn=False)
if issubclass(variable_type, CFGridMappingVariable):
ignore = None
else:
ignore = coordinate_names
match = variable_type.identify(self._dataset.variables,
ignore=ignore,
target=cf_variable.cf_name,
warn=False)
# Sanity check dimensionality coverage.
for cf_name, cf_var in six.iteritems(match):
if cf_var.spans(cf_variable):
Expand All @@ -1030,7 +1035,8 @@ def _build(cf_variable):
# Build CF data variable relationships.
if isinstance(cf_variable, CFDataVariable):
# Add global netCDF attributes.
cf_group.global_attributes.update(self.cf_group.global_attributes)
cf_group.global_attributes.update(
self.cf_group.global_attributes)
# Add appropriate "dimensioned" CF coordinate variables.
cf_group.update({cf_name: self.cf_group[cf_name] for cf_name
in cf_variable.dimensions if cf_name in
Expand All @@ -1043,7 +1049,8 @@ def _build(cf_variable):
# Add appropriate formula terms.
for cf_var in six.itervalues(self.cf_group.formula_terms):
for cf_root in cf_var.cf_terms_by_root:
if cf_root in cf_group and cf_var.cf_name not in cf_group:
if (cf_root in cf_group and
cf_var.cf_name not in cf_group):
# Sanity check dimensionality.
if cf_var.spans(cf_variable):
cf_group[cf_var.cf_name] = cf_var
Expand Down Expand Up @@ -1073,42 +1080,38 @@ def _build(cf_variable):
_build(cf_variable)

# Determine whether there are any formula terms that
# may be promoted to a CFDataVariable.
if iris.FUTURE.netcdf_promote:
# Restrict promotion to only those formula terms
# that are reference surface/phenomenon.
for cf_var in six.itervalues(self.cf_group.formula_terms):
for cf_root, cf_term in six.iteritems(cf_var.cf_terms_by_root):
cf_root_var = self.cf_group[cf_root]
name = cf_root_var.standard_name or cf_root_var.long_name
terms = reference_terms.get(name, [])
if isinstance(terms, six.string_types) or \
not isinstance(terms, Iterable):
terms = [terms]
cf_var_name = cf_var.cf_name
if cf_term in terms and \
cf_var_name not in self.cf_group.promoted:
data_var = CFDataVariable(cf_var_name, cf_var.cf_data)
self.cf_group.promoted[cf_var_name] = data_var
_build(data_var)
break
# Promote any ignored variables.
promoted = set()
not_promoted = ignored.difference(promoted)
while not_promoted:
cf_name = not_promoted.pop()
if cf_name not in self.cf_group.data_variables and \
cf_name not in self.cf_group.promoted:
data_var = CFDataVariable(cf_name,
self.cf_group[cf_name].cf_data)
self.cf_group.promoted[cf_name] = data_var
# may be promoted to a CFDataVariable and restrict promotion to only
# those formula terms that are reference surface/phenomenon.
for cf_var in six.itervalues(self.cf_group.formula_terms):
for cf_root, cf_term in six.iteritems(cf_var.cf_terms_by_root):
cf_root_var = self.cf_group[cf_root]
name = cf_root_var.standard_name or cf_root_var.long_name
terms = reference_terms.get(name, [])
if isinstance(terms, six.string_types) or \
not isinstance(terms, Iterable):
terms = [terms]
cf_var_name = cf_var.cf_name
if cf_term in terms and \
cf_var_name not in self.cf_group.promoted:
data_var = CFDataVariable(cf_var_name, cf_var.cf_data)
self.cf_group.promoted[cf_var_name] = data_var
_build(data_var)
# Determine whether there are still any ignored variables
# yet to be promoted.
promoted.add(cf_name)
not_promoted = ignored.difference(promoted)
else:
_netcdf_promote_warning()
break
# Promote any ignored variables.
promoted = set()
not_promoted = ignored.difference(promoted)
while not_promoted:
cf_name = not_promoted.pop()
if cf_name not in self.cf_group.data_variables and \
cf_name not in self.cf_group.promoted:
data_var = CFDataVariable(cf_name,
self.cf_group[cf_name].cf_data)
self.cf_group.promoted[cf_name] = data_var
_build(data_var)
# Determine whether there are still any ignored variables
# yet to be promoted.
promoted.add(cf_name)
not_promoted = ignored.difference(promoted)


def _reset(self):
Expand All @@ -1132,12 +1135,3 @@ def _getncattr(dataset, attr, default=None):
except AttributeError:
value = default
return value


def _netcdf_promote_warning():
msg = ('NetCDF default loading behaviour currently does not expose '
'variables which define reference surfaces for dimensionless '
'vertical coordinates as independent Cubes. This behaviour is '
'deprecated in favour of automatic promotion to Cubes. To switch '
'to the new behaviour, set iris.FUTURE.netcdf_promote to True.')
warn_deprecated(msg)
2 changes: 1 addition & 1 deletion lib/iris/tests/integration/test_cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class Test_aggregated_by(tests.IrisTest):
def test_agg_by_aux_coord(self):
problem_test_file = tests.get_data_path(('NetCDF', 'testing',
'small_theta_colpex.nc'))
cube = iris.load_cube(problem_test_file)
cube = iris.load_cube(problem_test_file, 'air_potential_temperature')

# Test aggregating by aux coord, notably the `forecast_period` aux
# coord on `cube`, whose `_points` attribute is a lazy array.
Expand Down
9 changes: 5 additions & 4 deletions lib/iris/tests/integration/test_netcdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ def test_save_load_loop(self):
with self.temp_filename(suffix='.nc') as filename, \
self.temp_filename(suffix='.nc') as other_filename:
iris.save(self.cube, filename)
cube = iris.load_cube(filename)
cube = iris.load_cube(filename, 'air_potential_temperature')
iris.save(cube, other_filename)
other_cube = iris.load_cube(other_filename)
other_cube = iris.load_cube(other_filename,
'air_potential_temperature')
self.assertEqual(cube, other_cube)


Expand Down Expand Up @@ -120,7 +121,7 @@ def test_hybrid_height_cubes(self):
sa.points = sa.points * 10
with self.temp_filename('.nc') as fname:
iris.save([hh1, hh2], fname)
cubes = iris.load(fname)
cubes = iris.load(fname, 'air_temperature')
cubes = sorted(cubes, key=lambda cube: cube.attributes['cube'])
self.assertCML(cubes)

Expand Down Expand Up @@ -203,7 +204,7 @@ class TestLazySave(tests.IrisTest):
def test_lazy_preserved_save(self):
fpath = tests.get_data_path(('NetCDF', 'label_and_climate',
'small_FC_167_mon_19601101.nc'))
acube = iris.load_cube(fpath)
acube = iris.load_cube(fpath, 'air_temperature')
self.assertTrue(acube.has_lazy_data())
with self.temp_filename('.nc') as nc_path:
with Saver(nc_path, 'NETCDF4') as saver:
Expand Down
2 changes: 1 addition & 1 deletion lib/iris/tests/system_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def system_test_supported_filetypes(self):
filetypes = ('.nc', '.pp')
if tests.GRIB_AVAILABLE:
filetypes += ('.grib2',)
with iris.FUTURE.context(netcdf_no_unlimited=True, netcdf_promote=True):
with iris.FUTURE.context(netcdf_no_unlimited=True):
for filetype in filetypes:
saved_tmpfile = iris.util.create_temp_filename(suffix=filetype)
iris.save(cm, saved_tmpfile)
Expand Down
Loading