Last active
April 14, 2021 15:39
-
-
Save pelson/9763057 to your computer and use it in GitHub Desktop.
Sorting an Iris cube by coordinate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"metadata": { | |
"name": "" | |
}, | |
"nbformat": 3, | |
"nbformat_minor": 0, | |
"worksheets": [ | |
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Question\n", | |
"\n", | |
"Is it possible to sort a cube by a coordinate?\n", | |
"\n", | |
"## Answer\n", | |
"\n", | |
"There is nothing in Iris to do this currently, but it should be relatively easy to implement." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Stratergy for implementing `sorted(cube, coord)`\n", | |
"\n", | |
"Rather than doing anything in-place as ``[].sort()`` does, let's follow the ``sorted(list)`` pattern to produce a new, sorted, cube. As a result we can quickly make use of Iris' indexing to return the sorted indices in order. The secret here is that numpy has a function, ``argsort`` which returns the indices of the sorted array, so all we need to do is index the cube on the dimension of the 1d coordinate to be sorted with the result of passing the coordinate points to ``argsort``." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import numpy as np\n", | |
"\n", | |
"def sorted(cube, coord):\n", | |
" coord_to_sort = cube.coord(coord)\n", | |
" assert coord_to_sort.ndim == 1, 'One dim coords only please.'\n", | |
" dim, = cube.coord_dims(coord_to_sort)\n", | |
" index = [slice(None)] * cube.ndim\n", | |
" index[dim] = np.argsort(coord_to_sort.points)\n", | |
" return cube[tuple(index)]" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [], | |
"prompt_number": 1 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Let's test this with a simple 1D cube:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"import iris.coords\n", | |
"import iris.cube\n", | |
"\n", | |
"cube = iris.cube.Cube([0, 1, 2, 3])\n", | |
"cube.add_aux_coord(iris.coords.AuxCoord([2, 1, 0, 3], long_name='tbd'), 0)\n", | |
"\n", | |
"print cube\n", | |
"print cube.data\n", | |
"print cube.coord('tbd')" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"unknown / (unknown) (-- : 4)\n", | |
" Auxiliary coordinates:\n", | |
" tbd x\n", | |
"[0 1 2 3]\n", | |
"AuxCoord(array([2, 1, 0, 3]), standard_name=None, units=Unit('1'), long_name='tbd')\n" | |
] | |
} | |
], | |
"prompt_number": 2 | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"And when we call our ``sorted`` function on the coordinate to sort we see our data is now changed:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"collapsed": false, | |
"input": [ | |
"cube = sorted(cube, 'tbd')\n", | |
"print cube\n", | |
"print cube.data\n", | |
"print cube.coord('tbd')" | |
], | |
"language": "python", | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"output_type": "stream", | |
"stream": "stdout", | |
"text": [ | |
"unknown / (unknown) (-- : 4)\n", | |
" Auxiliary coordinates:\n", | |
" tbd x\n", | |
"[2 1 0 3]\n", | |
"AuxCoord(array([0, 1, 2, 3]), standard_name=None, units=Unit('1'), long_name='tbd')\n" | |
] | |
} | |
], | |
"prompt_number": 3 | |
} | |
], | |
"metadata": {} | |
} | |
] | |
} |
I like finding answers to questions that I wrote many years ago. That still work today! 🎉
Just wish I'd implemented multiple coordinate sorting, not just one...
I guess it would work just as well to split the cube into single length items on the dimension to sort then to merge them together again...
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
FWIW to upcast the cube's new coordinate to a DimCoord (such that when saving NetCDF the dimension name comes from the coord's var_name) one would need to do: