python4oceanographers

Turning ripples into waves

Iris load, loads, and load_raw

Anyone that reads this blog knows that I use iris a lot. Still, every now and then I get bitten by some iris quirkiness. This post is to explain on of those quirkiness that a lot of my colleagues, myself included, like to rant about: "How to load a cube?!"

In [2]:
import iris

url = ('http://hfrnet.ucsd.edu/thredds/dodsC/HFR/USWC/6km/hourly/GNOME/'
       'HFRADAR,_US_West_Coast,_6km_Resolution,_Hourly_RTV_(GNOME)_best.ncd')

It is only natural to use load_cubes to load your cubes, right?

In [3]:
cubes = iris.load_cubes(url)
/home/filipe/.virtualenvs/blog/lib/python2.7/site-packages/iris/fileformats/_pyke_rules/compiled_krb/fc_rules_cf_fc.py:1395: UserWarning: Gracefully filling 'time' dimension coordinate masked points
  warnings.warn(msg.format(str(cf_coord_var.cf_name)))

---------------------------------------------------------------------------
ConstraintMismatchError                   Traceback (most recent call last)
<ipython-input-3-44813a800bd2> in <module>()
----> 1 cubes = iris.load_cubes(url)

/home/filipe/.virtualenvs/blog/lib/python2.7/site-packages/iris/__init__.py in load_cubes(uris, constraints, callback)
    369         bits = [fmt.format(pair.constraint, len(pair)) for pair in bad_pairs]
    370         msg = '\n' + '\n'.join(bits)
--> 371         raise iris.exceptions.ConstraintMismatchError(msg)
    372 
    373     return collection.cubes()

ConstraintMismatchError: 
   Constraint() -> 8 cubes

Apparently not!

(And you have to love when the error messages are cryptic ;-)

Time to read the docs! From the docstring (the online docs are better BTW):

  • iris.load_cubes :: Loads exactly one Cube for each constraint.
  • iris.load :: Loads any number of Cubes for each constraint.
  • iris.load_raw :: Loads non-merged cubes.

OK, I admit. This confusion looks a lot like the PERL TIMTOWTDI philosophy and I do not like. I try to follow the rule:

    There should be one -- and preferably only one -- obvious way to do it.

However, I see the appeal for at least load_raw() and, even though the docs do not recommend it, I use it a lot. Let's see what is going on with that dataset using load_raw().

In [4]:
cubes = iris.load_raw(url)

print(cubes)
0: Contributing radar site code / (no_unit) (-- : 56; -- : 64)
1: longitude / (degrees)               (-- : 56)
2: RTV processing parameters / (1)     (-- : 7)
3: surface_northward_sea_water_velocity / (m s-1) (time: 32080; latitude: 367; longitude: 234)
4: surface_eastward_sea_water_velocity / (m s-1) (time: 32080; latitude: 367; longitude: 234)
5: forecast_period / (hours since 2011-10-01T00:00:00Z) (time: 32080)
6: Contributing radar site network affiliation code / (no_unit) (-- : 56; -- : 64)
7: latitude / (degrees)                (-- : 56)

One of those cubes is not OK with the rule "exactly one Cube for each constraint." What constraint? We did not specify anything!

In [5]:
for cube in cubes:
    standard_name = cube.standard_name
    print(standard_name)
None
longitude
None
surface_northward_sea_water_velocity
surface_eastward_sea_water_velocity
forecast_period
None
latitude

I guess the issue is the None as standard_name. Iris is OK loading them using the long_name though.

In [6]:
print(iris.load_cube(url, 'RTV processing parameters'))
RTV processing parameters / (1)     (-- : 7)
     Attributes:
          Conventions: CF-1.4, _Coordinates
          DODS.dimName: nSites_maxStrlen
          DODS.strlen: 25
          _CoordSysBuilder: ucar.nc2.dataset.conv.CF1Convention
          cdm_data_type: GRID
          comment: 
01) Maximum GDOP threshold
02) Maximum speed threshold (cm s-1)
03) Minimum...
          creator_email: motero@ucsd.edu
          creator_name: Mark Otero
          creator_url: http://cordc.ucsd.edu/projects/mapping/
          featureType: GRID
          format_version: HFRNet_1.0.0
          geospatial_lat_max: 49.992
          geospatial_lat_min: 30.25
          geospatial_lon_max: -115.806
          geospatial_lon_min: -130.36
          grid_projection: equidistant cylindrical
          grid_resolution: 6km
          grid_type: REGULAR
          history: 21-May-2015 04:36:10: NetCDF file created
21-May-2015 04:36:10: Filtered...
          institution: Scripps Institution of Oceanography
          location: Proto fmrc:HFRADAR,_US_West_Coast,_6km_Resolution,_Hourly_RTV_(GNOME)
          netcdf_library_version: 4.1.3
          product_version: HFRNet_1.1.05
          references: Terrill, E. et al., 2006. Data Management and Real-time
Distribution in...
          regional_description: Unites States, West Coast
          source: Surface Ocean HF-Radar
          summary: Surface ocean velocities estimated from HF-Radar are
representative of...
          title: Near-Real Time Surface Ocean Velocity, US West Coast, 6 km Resolution ...

And OK with load (Any number of Cubes for each constraint).

In [7]:
cubes = iris.load(url)

print(cubes)
0: Contributing radar site code / (no_unit) (-- : 56; -- : 64)
1: RTV processing parameters / (1)     (-- : 7)
2: Contributing radar site network affiliation code / (no_unit) (-- : 56; -- : 64)
3: forecast_period / (hours since 2011-10-01T00:00:00Z) (time: 32080)
4: latitude / (degrees)                (-- : 56)
5: longitude / (degrees)               (-- : 56)
6: surface_eastward_sea_water_velocity / (m s-1) (time: 32080; latitude: 367; longitude: 234)
7: surface_northward_sea_water_velocity / (m s-1) (time: 32080; latitude: 367; longitude: 234)

In conclusion? Stick with either load or load_raw when you do not want to be strict about loading.

In [8]:
HTML(html)
Out[8]:

This post was written as an IPython notebook. It is available for download or as a static html.

Creative Commons License
python4oceanographers by Filipe Fernandes is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Based on a work at https://ocefpaf.github.io/.

Comments