Skip to content

Instantly share code, notes, and snippets.

@pelson
Created June 13, 2018 03:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pelson/acd2fabf901f0bb093cf370949e4beca to your computer and use it in GitHub Desktop.
Save pelson/acd2fabf901f0bb093cf370949e4beca to your computer and use it in GitHub Desktop.
Working around a scalar PP saving issue by adding an extra point to a scalar dimension
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Iris: saving PP for singleton dimensions\n",
"\n",
"A question about what Iris does when it tries to save a PP file with a length one coordinate cropped up at https://groups.google.com/forum/#!topic/scitools-iris/CVhGzusweeg.\n",
"\n",
"I reproduced the problem, first by setting up a dummy cube:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"<style>\n",
" a.iris {\n",
" text-decoration: none !important;\n",
" }\n",
" table.iris {\n",
" white-space: pre;\n",
" border: 1px solid;\n",
" border-color: #9c9c9c;\n",
" font-family: monaco, monospace;\n",
" }\n",
" th.iris {\n",
" background: #303f3f;\n",
" color: #e0e0e0;\n",
" border-left: 1px solid;\n",
" border-color: #9c9c9c;\n",
" font-size: 1.05em;\n",
" min-width: 50px;\n",
" max-width: 125px;\n",
" }\n",
" tr.iris :first-child {\n",
" border-right: 1px solid #9c9c9c !important;\n",
" }\n",
" td.iris-title {\n",
" background: #d5dcdf;\n",
" border-top: 1px solid #9c9c9c;\n",
" font-weight: bold;\n",
" }\n",
" .iris-word-cell {\n",
" text-align: left !important;\n",
" white-space: pre;\n",
" }\n",
" .iris-subheading-cell {\n",
" padding-left: 2em !important;\n",
" }\n",
" .iris-inclusion-cell {\n",
" padding-right: 1em !important;\n",
" }\n",
" .iris-panel-body {\n",
" padding-top: 0px;\n",
" }\n",
" .iris-panel-title {\n",
" padding-left: 3em;\n",
" }\n",
" .iris-panel-title {\n",
" margin-top: 7px;\n",
" }\n",
"</style>\n",
"<table class=\"iris\" id=\"4582740544\">\n",
" <tr class=\"iris\">\n",
"<th class=\"iris iris-word-cell\">X Wind (m s-1)</th>\n",
"<th class=\"iris iris-word-cell\">latitude</th>\n",
"<th class=\"iris iris-word-cell\">longitude</th>\n",
"</tr>\n",
" <tr class=\"iris\">\n",
"<td class=\"iris-word-cell iris-subheading-cell\">Shape</td>\n",
"<td class=\"iris iris-inclusion-cell\">4</td>\n",
"<td class=\"iris iris-inclusion-cell\">1</td>\n",
"</td>\n",
" <tr class=\"iris\">\n",
" <td class=\"iris-title iris-word-cell\">Dimension coordinates</td>\n",
" <td class=\"iris-title\"></td>\n",
" <td class=\"iris-title\"></td>\n",
"</tr>\n",
"<tr class=\"iris\">\n",
" <td class=\"iris-word-cell iris-subheading-cell\">\tlatitude</td>\n",
" <td class=\"iris-inclusion-cell\">x</td>\n",
" <td class=\"iris-inclusion-cell\">-</td>\n",
"</tr>\n",
"<tr class=\"iris\">\n",
" <td class=\"iris-word-cell iris-subheading-cell\">\tlongitude</td>\n",
" <td class=\"iris-inclusion-cell\">-</td>\n",
" <td class=\"iris-inclusion-cell\">x</td>\n",
"</tr>\n",
"</table>\n",
" "
],
"text/plain": [
"<iris 'Cube' of x_wind / (m s-1) (latitude: 4; longitude: 1)>"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import iris\n",
"import numpy as np\n",
"\n",
"shape = (4, 1)\n",
"cube = iris.cube.Cube(np.arange(np.prod(shape)).reshape(shape).astype(np.float32),\n",
" standard_name='x_wind', units='m s-1')\n",
"cube.add_dim_coord(iris.coords.DimCoord(standard_name='latitude', points=range(shape[0])), 0)\n",
"cube.add_dim_coord(iris.coords.DimCoord(standard_name='longitude', points=range(shape[1])), 1)\n",
"cube"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Followed by saving then subsequently loading the cube to PP:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"ename": "AttributeError",
"evalue": "'PPField3' object has no attribute 'x'",
"output_type": "error",
"traceback": [
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/fileformats/pp.py\u001b[0m in \u001b[0;36m__getattr__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 890\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 891\u001b[0;31m \u001b[0mloc\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mHEADER_DICT\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 892\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mKeyError\u001b[0m: 'x'",
"\nDuring handling of the above exception, another exception occurred:\n",
"\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)",
"\u001b[0;32m<ipython-input-2-c938d8c3ca6c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0miris\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msave\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcube\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'test.pp'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0miris\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mload_cube\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'test.pp'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/__init__.py\u001b[0m in \u001b[0;36mload_cube\u001b[0;34m(uris, constraint, callback)\u001b[0m\n\u001b[1;32m 371\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'only a single constraint is allowed'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 372\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 373\u001b[0;31m \u001b[0mcubes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_load_collection\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0muris\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcallback\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 374\u001b[0m \u001b[0mcubes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcubes\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmerged\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcubes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 375\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/__init__.py\u001b[0m in \u001b[0;36m_load_collection\u001b[0;34m(uris, constraints, callback)\u001b[0m\n\u001b[1;32m 311\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 312\u001b[0m \u001b[0mcubes\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_generate_cubes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0muris\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcallback\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 313\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0miris\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcube\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_CubeFilterCollection\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrom_cubes\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcubes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 314\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mEOFError\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 315\u001b[0m raise iris.exceptions.TranslationError(\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/cube.py\u001b[0m in \u001b[0;36mfrom_cubes\u001b[0;34m(cubes, constraints)\u001b[0m\n\u001b[1;32m 143\u001b[0m \u001b[0mpairs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0m_CubeFilter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconstraint\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mconstraint\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 144\u001b[0m \u001b[0mcollection\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_CubeFilterCollection\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpairs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 145\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mcube\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mcubes\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 146\u001b[0m \u001b[0mcollection\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd_cube\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcube\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 147\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mcollection\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/__init__.py\u001b[0m in \u001b[0;36m_generate_cubes\u001b[0;34m(uris, callback, constraints)\u001b[0m\n\u001b[1;32m 298\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mscheme\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'file'\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 299\u001b[0m \u001b[0mpart_names\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mgroups\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 300\u001b[0;31m \u001b[0;32mfor\u001b[0m \u001b[0mcube\u001b[0m \u001b[0;32min\u001b[0m \u001b[0miris\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mio\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mload_files\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mpart_names\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcallback\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconstraints\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 301\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0mcube\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 302\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mscheme\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m'http'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'https'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/io/__init__.py\u001b[0m in \u001b[0;36mload_files\u001b[0;34m(filenames, callback, constraints)\u001b[0m\n\u001b[1;32m 205\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mhandling_format_spec\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconstraint_aware_handler\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 206\u001b[0m for cube in handling_format_spec.handler(fnames, callback,\n\u001b[0;32m--> 207\u001b[0;31m constraints):\n\u001b[0m\u001b[1;32m 208\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0mcube\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/fileformats/rules.py\u001b[0m in \u001b[0;36mload_cubes\u001b[0;34m(filenames, user_callback, loader, filter_function)\u001b[0m\n\u001b[1;32m 427\u001b[0m \u001b[0mall_fields_and_filenames\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 428\u001b[0m \u001b[0mconverter\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mloader\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconverter\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 429\u001b[0;31m user_callback_wrapper=loadcubes_user_callback_wrapper):\n\u001b[0m\u001b[1;32m 430\u001b[0m \u001b[0;32myield\u001b[0m \u001b[0mcube\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/fileformats/rules.py\u001b[0m in \u001b[0;36m_load_pairs_from_fields_and_filenames\u001b[0;34m(fields_and_filenames, converter, user_callback_wrapper)\u001b[0m\n\u001b[1;32m 348\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mfield\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfilename\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mfields_and_filenames\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 349\u001b[0m \u001b[0;31m# Convert the field to a Cube, passing down the 'converter' function.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 350\u001b[0;31m \u001b[0mcube\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfactories\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mreferences\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_make_cube\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfield\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconverter\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 351\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 352\u001b[0m \u001b[0;31m# Post modify the new cube with a user-callback.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/fileformats/rules.py\u001b[0m in \u001b[0;36m_make_cube\u001b[0;34m(field, converter)\u001b[0m\n\u001b[1;32m 291\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_make_cube\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfield\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconverter\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 292\u001b[0m \u001b[0;31m# Convert the field to a Cube.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 293\u001b[0;31m \u001b[0mmetadata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mconverter\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfield\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 294\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 295\u001b[0m \u001b[0mcube_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfield\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcore_data\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/fileformats/pp_load_rules.py\u001b[0m in \u001b[0;36mconvert\u001b[0;34m(f)\u001b[0m\n\u001b[1;32m 693\u001b[0m \u001b[0;31m# All the other rules.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 694\u001b[0m \u001b[0mreferences\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstandard_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlong_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0munits\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattributes\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell_methods\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m\\\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 695\u001b[0;31m \u001b[0mdim_coords_and_dims\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother_aux_coords_and_dims\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_all_other_rules\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 696\u001b[0m \u001b[0maux_coords_and_dims\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother_aux_coords_and_dims\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 697\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/fileformats/pp_load_rules.py\u001b[0m in \u001b[0;36m_all_other_rules\u001b[0;34m(f)\u001b[0m\n\u001b[1;32m 838\u001b[0m (len(f.lbcode) == 5 and f.lbcode.ix == 11))):\n\u001b[1;32m 839\u001b[0m dim_coords_and_dims.append(\n\u001b[0;32m--> 840\u001b[0;31m (DimCoord(f.x, standard_name=f._x_coord_name(), units='degrees',\n\u001b[0m\u001b[1;32m 841\u001b[0m \u001b[0mbounds\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mx_bounds\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcircular\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlbhem\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m4\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 842\u001b[0m coord_system=f.coord_system()),\n",
"\u001b[0;32m~/dev/scitools/iris/lib/iris/fileformats/pp.py\u001b[0m in \u001b[0;36m__getattr__\u001b[0;34m(self, key)\u001b[0m\n\u001b[1;32m 897\u001b[0m \u001b[0mcls\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__name__\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 898\u001b[0m \u001b[0mmsg\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'{!r} object has no attribute {!r}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcls\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 899\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 900\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 901\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mloc\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
"\u001b[0;31mAttributeError\u001b[0m: 'PPField3' object has no attribute 'x'"
]
}
],
"source": [
"iris.save(cube, 'test.pp')\n",
"iris.load_cube('test.pp')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This was raised as a bug in https://github.com/SciTools/iris/issues/3022.\n",
"\n",
"The suggested workaround was to add another element to the longitude coordinate (and therefore double the amount of actual data the cube represents). This can be achieved in a number of ways, but the suggested route is to copy the cube, modify the copy's longitude points, then concatenate the original with the copy:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"<style>\n",
" a.iris {\n",
" text-decoration: none !important;\n",
" }\n",
" table.iris {\n",
" white-space: pre;\n",
" border: 1px solid;\n",
" border-color: #9c9c9c;\n",
" font-family: monaco, monospace;\n",
" }\n",
" th.iris {\n",
" background: #303f3f;\n",
" color: #e0e0e0;\n",
" border-left: 1px solid;\n",
" border-color: #9c9c9c;\n",
" font-size: 1.05em;\n",
" min-width: 50px;\n",
" max-width: 125px;\n",
" }\n",
" tr.iris :first-child {\n",
" border-right: 1px solid #9c9c9c !important;\n",
" }\n",
" td.iris-title {\n",
" background: #d5dcdf;\n",
" border-top: 1px solid #9c9c9c;\n",
" font-weight: bold;\n",
" }\n",
" .iris-word-cell {\n",
" text-align: left !important;\n",
" white-space: pre;\n",
" }\n",
" .iris-subheading-cell {\n",
" padding-left: 2em !important;\n",
" }\n",
" .iris-inclusion-cell {\n",
" padding-right: 1em !important;\n",
" }\n",
" .iris-panel-body {\n",
" padding-top: 0px;\n",
" }\n",
" .iris-panel-title {\n",
" padding-left: 3em;\n",
" }\n",
" .iris-panel-title {\n",
" margin-top: 7px;\n",
" }\n",
"</style>\n",
"<table class=\"iris\" id=\"4657667040\">\n",
" <tr class=\"iris\">\n",
"<th class=\"iris iris-word-cell\">X Wind (m s-1)</th>\n",
"<th class=\"iris iris-word-cell\">latitude</th>\n",
"<th class=\"iris iris-word-cell\">longitude</th>\n",
"</tr>\n",
" <tr class=\"iris\">\n",
"<td class=\"iris-word-cell iris-subheading-cell\">Shape</td>\n",
"<td class=\"iris iris-inclusion-cell\">4</td>\n",
"<td class=\"iris iris-inclusion-cell\">2</td>\n",
"</td>\n",
" <tr class=\"iris\">\n",
" <td class=\"iris-title iris-word-cell\">Dimension coordinates</td>\n",
" <td class=\"iris-title\"></td>\n",
" <td class=\"iris-title\"></td>\n",
"</tr>\n",
"<tr class=\"iris\">\n",
" <td class=\"iris-word-cell iris-subheading-cell\">\tlatitude</td>\n",
" <td class=\"iris-inclusion-cell\">x</td>\n",
" <td class=\"iris-inclusion-cell\">-</td>\n",
"</tr>\n",
"<tr class=\"iris\">\n",
" <td class=\"iris-word-cell iris-subheading-cell\">\tlongitude</td>\n",
" <td class=\"iris-inclusion-cell\">-</td>\n",
" <td class=\"iris-inclusion-cell\">x</td>\n",
"</tr>\n",
"</table>\n",
" "
],
"text/plain": [
"<iris 'Cube' of x_wind / (m s-1) (latitude: 4; longitude: 2)>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"dummy_lon_cube = cube.copy()\n",
"dummy_lon_cube.coord('longitude').points = cube.coord('longitude').points + 1\n",
"\n",
"dummy_cube = iris.cube.CubeList([cube, dummy_lon_cube]).concatenate_cube()\n",
"dummy_cube"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This should now save & load without issue:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"<style>\n",
" a.iris {\n",
" text-decoration: none !important;\n",
" }\n",
" table.iris {\n",
" white-space: pre;\n",
" border: 1px solid;\n",
" border-color: #9c9c9c;\n",
" font-family: monaco, monospace;\n",
" }\n",
" th.iris {\n",
" background: #303f3f;\n",
" color: #e0e0e0;\n",
" border-left: 1px solid;\n",
" border-color: #9c9c9c;\n",
" font-size: 1.05em;\n",
" min-width: 50px;\n",
" max-width: 125px;\n",
" }\n",
" tr.iris :first-child {\n",
" border-right: 1px solid #9c9c9c !important;\n",
" }\n",
" td.iris-title {\n",
" background: #d5dcdf;\n",
" border-top: 1px solid #9c9c9c;\n",
" font-weight: bold;\n",
" }\n",
" .iris-word-cell {\n",
" text-align: left !important;\n",
" white-space: pre;\n",
" }\n",
" .iris-subheading-cell {\n",
" padding-left: 2em !important;\n",
" }\n",
" .iris-inclusion-cell {\n",
" padding-right: 1em !important;\n",
" }\n",
" .iris-panel-body {\n",
" padding-top: 0px;\n",
" }\n",
" .iris-panel-title {\n",
" padding-left: 3em;\n",
" }\n",
" .iris-panel-title {\n",
" margin-top: 7px;\n",
" }\n",
"</style>\n",
"<table class=\"iris\" id=\"4657733136\">\n",
" <tr class=\"iris\">\n",
"<th class=\"iris iris-word-cell\">X Wind (m s-1)</th>\n",
"<th class=\"iris iris-word-cell\">latitude</th>\n",
"<th class=\"iris iris-word-cell\">longitude</th>\n",
"</tr>\n",
" <tr class=\"iris\">\n",
"<td class=\"iris-word-cell iris-subheading-cell\">Shape</td>\n",
"<td class=\"iris iris-inclusion-cell\">4</td>\n",
"<td class=\"iris iris-inclusion-cell\">2</td>\n",
"</td>\n",
" <tr class=\"iris\">\n",
" <td class=\"iris-title iris-word-cell\">Dimension coordinates</td>\n",
" <td class=\"iris-title\"></td>\n",
" <td class=\"iris-title\"></td>\n",
"</tr>\n",
"<tr class=\"iris\">\n",
" <td class=\"iris-word-cell iris-subheading-cell\">\tlatitude</td>\n",
" <td class=\"iris-inclusion-cell\">x</td>\n",
" <td class=\"iris-inclusion-cell\">-</td>\n",
"</tr>\n",
"<tr class=\"iris\">\n",
" <td class=\"iris-word-cell iris-subheading-cell\">\tlongitude</td>\n",
" <td class=\"iris-inclusion-cell\">-</td>\n",
" <td class=\"iris-inclusion-cell\">x</td>\n",
"</tr>\n",
"</table>\n",
" "
],
"text/plain": [
"<iris 'Cube' of x_wind / (m s-1) (latitude: 4; longitude: 2)>"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"iris.save(dummy_cube, 'test.pp')\n",
"iris.load_cube('test.pp')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Environment (conda_iris-dev-py3)",
"language": "python",
"name": "conda_iris-dev-py3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment