Skip to content

Commit

Permalink
Avoid computing lazy scalar coordinates when printing a Cube (v2) (#5896
Browse files Browse the repository at this point in the history
)

* avoid running coord.cell for lazy data and bounds

* Special case for printing scalar hybrid coords.

* Convert test_CubeSummary to pytest.

* Add tests for cube printout of real/lazy/hybrid scalar coordinates.

* Review change.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Added whatsnew.

---------

Co-authored-by: Francesco Nattino <f.nattino@esciencecenter.nl>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 2, 2024
1 parent 03a2d5c commit b7685b9
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 86 deletions.
6 changes: 5 additions & 1 deletion docs/src/whatsnew/latest.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ This document explains the changes made to Iris for this release
:func:`dask.array.map_blocks`; known specifically to be a problem in the
:class:`iris.analysis.AreaWeighted` regridder. (:pull:`5767`)

#. `@fnattino`_ and `@pp-mo`_ prevented cube printout from showing the values of lazy
scalar coordinates, since this can involve a lengthy computation that must be
re-computed each time. (:pull:`5896`)


🔥 Deprecations
===============
Expand Down Expand Up @@ -105,7 +109,7 @@ This document explains the changes made to Iris for this release
core dev names are automatically included by the common_links.inc:
.. _@jfrost-mo: https://github.com/jfrost-mo

.. _@fnattino: https://github.com/fnattino


.. comment
Expand Down
66 changes: 54 additions & 12 deletions lib/iris/_representation/cube_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

import re

import numpy as np

import iris._lazy_data as _lazy
from iris.common.metadata import hexdigest
import iris.util

Expand Down Expand Up @@ -149,32 +152,71 @@ def __init__(self, cube, coord):
self.unit = ""
else:
self.unit = " {!s}".format(coord.units)
coord_cell = coord.cell(0)
if isinstance(coord_cell.point, str):

# Don't print values of lazy coords, as computing them could cost a lot.
safe_to_print = not _lazy.is_lazy_data(coord.core_points())
if not safe_to_print:
# However there is a special case: If it is a *factory* coord, then those
# are generally lazy. If all the dependencies are real, then it is useful
# (and safe) to compute + print the value.
for factory in cube._aux_factories:
# Note : a factory doesn't have a ".metadata" which can be matched
# against a coord. For now, just assume that it has a 'standard_name'
# property (also not actually guaranteed), and require them to match.
if coord.standard_name == factory.standard_name:
all_deps_real = True
for dependency_coord in factory.dependencies.values():
if (
dependency_coord.has_lazy_points()
or dependency_coord.has_lazy_bounds()
):
all_deps_real = False

if all_deps_real:
safe_to_print = True

if safe_to_print:
coord_cell = coord.cell(0)
else:
coord_cell = None

if coord.dtype.type is np.str_:
self.string_type = True
# 'lines' is value split on '\n', and _each one_ length-clipped.
self.lines = [
iris.util.clip_string(str(item))
for item in coord_cell.point.split("\n")
]
if coord_cell is not None:
# 'lines' is value split on '\n', and _each one_ length-clipped.
self.lines = [
iris.util.clip_string(str(item))
for item in coord_cell.point.split("\n")
]
# 'content' contains a one-line printable version of the string,
content = string_repr(coord_cell.point)
content = iris.util.clip_string(content)
else:
content = "<lazy>"
self.lines = [content]
self.point = None
self.bound = None
# 'content' contains a one-line printable version of the string,
content = string_repr(coord_cell.point)
content = iris.util.clip_string(content)
self.content = content
else:
self.string_type = False
self.lines = None
self.point = "{!s}".format(coord_cell.point)
coord_cell_cbound = coord_cell.bound
coord_cell_cbound = None
if coord_cell is not None:
self.point = "{!s}".format(coord_cell.point)
coord_cell_cbound = coord_cell.bound
else:
self.point = "<lazy>"

if coord_cell_cbound is not None:
self.bound = "({})".format(
", ".join(str(val) for val in coord_cell_cbound)
)
self.content = "{}{}, bound={}{}".format(
self.point, self.unit, self.bound, self.unit
)
elif coord.has_bounds():
self.bound = "+bound"
self.content = "{}{}".format(self.point, self.bound)
else:
self.bound = None
self.content = "{}{}".format(self.point, self.unit)
Expand Down
Loading

0 comments on commit b7685b9

Please sign in to comment.