-
Notifications
You must be signed in to change notification settings - Fork 285
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pycarto++ #115
Pycarto++ #115
Changes from all commits
1f3b37f
c96a699
3480056
8b21acb
b6f980e
a6e3af2
2c66d0f
15d3bd4
558d0b4
10c84de
0bb2366
cf69468
2789ca0
7bdea1e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,35 +24,35 @@ def main(): | |
temperature = iris.load_strict(fname) | ||
|
||
# Calculate the lat lon range and buffer it by 10 degrees | ||
lat_range, lon_range = iris.analysis.cartography.lat_lon_range(temperature) | ||
lon_range, lat_range = iris.analysis.cartography.xy_range(temperature) | ||
lat_range = lat_range[0] - 10, lat_range[1] + 10 | ||
lon_range = lon_range[0] - 10, lon_range[1] + 10 | ||
|
||
|
||
# Plot #1: Point plot showing data values & a colorbar | ||
plt.figure() | ||
iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) | ||
iplt.map_setup(cube=temperature, ylim=lat_range, xlim=lon_range) | ||
points = qplt.points(temperature, c=temperature.data) | ||
cb = plt.colorbar(points, orientation='horizontal') | ||
cb.set_label(temperature.units) | ||
iplt.gcm().drawcoastlines() | ||
plt.gca().coastlines() | ||
plt.show() | ||
|
||
|
||
# Plot #2: Contourf of the point based data | ||
plt.figure() | ||
iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) | ||
iplt.map_setup(cube=temperature, ylim=lat_range, xlim=lon_range) | ||
qplt.contourf(temperature, 15) | ||
iplt.gcm().drawcoastlines() | ||
plt.gca().coastlines() | ||
plt.show() | ||
|
||
|
||
# Plot #3: Contourf overlayed by coloured point data | ||
plt.figure() | ||
iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) | ||
iplt.map_setup(cube=temperature, ylim=lat_range, xlim=lon_range) | ||
qplt.contourf(temperature) | ||
iplt.points(temperature, c=temperature.data) | ||
iplt.gcm().drawcoastlines() | ||
plt.gca().coastlines() | ||
plt.show() | ||
|
||
|
||
|
@@ -64,10 +64,10 @@ def main(): | |
|
||
# Plot #4: Block plot | ||
plt.figure() | ||
iplt.map_setup(temperature, lat_range=lat_range, lon_range=lon_range) | ||
iplt.map_setup(cube=temperature, ylim=lat_range, xlim=lon_range) | ||
iplt.pcolormesh(temperature) | ||
iplt.gcm().bluemarble() | ||
iplt.gcm().drawcoastlines() | ||
plt.gca().bluemarble() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems odd that zorder isn't needed to be set here, given that it was in TEC. Can TEC's zorder kwarg be removed? |
||
plt.gca().coastlines() | ||
plt.show() | ||
|
||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,8 +22,9 @@ | |
import math | ||
import warnings | ||
|
||
from mpl_toolkits.basemap import pyproj | ||
import pyproj | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to be using cartopy here. Example:
|
||
import numpy | ||
import cartopy.crs | ||
|
||
import iris.analysis | ||
import iris.coords | ||
|
@@ -95,92 +96,105 @@ def _get_lat_lon_coords(cube): | |
lat_coords = filter(lambda coord: "latitude" in coord.name(), cube.coords()) | ||
lon_coords = filter(lambda coord: "longitude" in coord.name(), cube.coords()) | ||
if len(lat_coords) > 1 or len(lon_coords) > 1: | ||
raise ValueError("Calling lat_lon_range() with multiple lat or lon coords is currently disallowed") | ||
raise ValueError("Calling _get_lat_lon_coords() with multiple lat or lon coords is currently disallowed") | ||
lat_coord = lat_coords[0] | ||
lon_coord = lon_coords[0] | ||
return (lat_coord, lon_coord) | ||
|
||
|
||
def lat_lon_range(cube, mode=None): | ||
def xy_range(cube, mode=None, projection=None): | ||
""" | ||
Return the lat & lon range of this Cube. | ||
Return the x & y range of this Cube. | ||
|
||
If the coordinate has both points & bounds, the mode keyword can be set to determine which should be | ||
used in the min/max calculation. (Must be one of iris.coords.POINT_MODE or iris.coords.BOUND_MODE) | ||
Args: | ||
|
||
* cube - The cube for which to calculate xy extents. | ||
|
||
Kwargs: | ||
|
||
* mode - If the coordinate has bounds, use the mode keyword to specify the | ||
min/max calculation (iris.coords.POINT_MODE or iris.coords.BOUND_MODE). | ||
|
||
* projection - Calculate the xy range in an alternative projection. | ||
|
||
""" | ||
# Helpful error if we have an inappropriate CoordSystem | ||
cs = cube.coord_system("CoordSystem") | ||
if cs is not None and not isinstance(cs, (iris.coord_systems.GeogCS, iris.coord_systems.RotatedGeogCS)): | ||
raise ValueError("Latlon coords cannot be found with {0}.".format(type(cs))) | ||
|
||
# get the lat and lon coords (might have "grid_" at the start of the name, if rotated). | ||
lat_coord, lon_coord = _get_lat_lon_coords(cube) | ||
x_coord, y_coord = cube.coord(axis="X"), cube.coord(axis="Y") | ||
cs = cube.coord_system('CoordSystem') | ||
|
||
if lon_coord.has_bounds() != lat_coord.has_bounds(): | ||
raise ValueError('Cannot get the range of the latitude and longitude coordinates if they do ' | ||
if x_coord.has_bounds() != x_coord.has_bounds(): | ||
raise ValueError('Cannot get the range of the x and y coordinates if they do ' | ||
'not have the same presence of bounds.') | ||
|
||
if lon_coord.has_bounds(): | ||
if x_coord.has_bounds(): | ||
if mode not in [iris.coords.POINT_MODE, iris.coords.BOUND_MODE]: | ||
raise ValueError('When the coordinate has bounds, please specify "mode".') | ||
_mode = mode | ||
else: | ||
_mode = iris.coords.POINT_MODE | ||
|
||
# Get the x and y grids | ||
if isinstance(cs, iris.coord_systems.RotatedGeogCS): | ||
if _mode == iris.coords.POINT_MODE: | ||
lats, lons = get_lat_lon_grids(cube) | ||
x, y = get_xy_grids(cube) | ||
else: | ||
lats, lons = get_lat_lon_contiguous_bounded_grids(cube) | ||
x, y = get_xy_contiguous_bounded_grids(cube) | ||
else: | ||
if _mode == iris.coords.POINT_MODE: | ||
lons = lon_coord.points | ||
lats = lat_coord.points | ||
x = x_coord.points | ||
y = y_coord.points | ||
else: | ||
lons = lon_coord.bounds | ||
lats = lat_coord.bounds | ||
x = x_coord.bounds | ||
y = y_coord.bounds | ||
|
||
if projection: | ||
# source projection | ||
source_cs = cube.coord_system("CoordSystem") | ||
if source_cs is not None: | ||
source_proj = source_cs.as_cartopy_projection() | ||
else: | ||
source_proj = cartopy.crs.PlateCarree() | ||
|
||
if source_proj != projection: | ||
# TODO: Ensure there is a test for this | ||
x, y = projection.transform_points(x=x, y=y, src_crs=source_proj) | ||
|
||
if getattr(lon_coord, 'circular', False): | ||
lon_range = (numpy.min(lons), numpy.min(lons) + lon_coord.units.modulus) | ||
# Get the x and y range | ||
if getattr(x_coord, 'circular', False): | ||
x_range = (numpy.min(x), numpy.min(x) + x_coord.units.modulus) | ||
else: | ||
lon_range = (numpy.min(lons), numpy.max(lons)) | ||
return ( (numpy.min(lats), numpy.max(lats)), lon_range ) | ||
x_range = (numpy.min(x), numpy.max(x)) | ||
|
||
y_range = (numpy.min(y), numpy.max(y)) | ||
|
||
return (x_range, y_range) | ||
|
||
def get_lat_lon_grids(cube): | ||
|
||
def get_xy_grids(cube): | ||
""" | ||
Return 2d lat and lon points in the requested coordinate system. | ||
Return 2d x and y points in the native coordinate system. | ||
:: | ||
|
||
lats, lons = get_lat_lon_grids(cube) | ||
x, y = get_xy_grids(cube) | ||
|
||
""" | ||
# get the lat and lon coords (might have "grid_" at the start of the name, if rotated). | ||
lat_coord, lon_coord = _get_lat_lon_coords(cube) | ||
x_coord, y_coord = cube.coord(axis="X"), cube.coord(axis="Y") | ||
cs = cube.coord_system('CoordSystem') | ||
|
||
if lon_coord.units != 'degrees': | ||
lon_coord = lon_coord.unit_converted('degrees') | ||
if lat_coord.units != 'degrees': | ||
lat_coord = lat_coord.unit_converted('degrees') | ||
|
||
lons = lon_coord.points | ||
lats = lat_coord.points | ||
x = x_coord.points | ||
y = y_coord.points | ||
|
||
# Convert to 2 x 2d grid of data | ||
lons, lats = numpy.meshgrid(lons, lats) | ||
|
||
# if the pole was rotated, then un-rotate it | ||
if isinstance(cs, iris.coord_systems.RotatedGeogCS): | ||
lons, lats = unrotate_pole(lons, lats, cs.grid_north_pole_longitude, cs.grid_north_pole_latitude) | ||
|
||
return (lats, lons) | ||
x, y = numpy.meshgrid(x, y) | ||
|
||
return (x, y) | ||
|
||
def get_lat_lon_contiguous_bounded_grids(cube): | ||
|
||
def get_xy_contiguous_bounded_grids(cube): | ||
""" | ||
Return 2d lat and lon bounds. | ||
|
||
|
@@ -190,21 +204,14 @@ def get_lat_lon_contiguous_bounded_grids(cube): | |
lats, lons = cs.get_lat_lon_bounded_grids() | ||
|
||
""" | ||
# get the lat and lon coords (might have "grid_" at the start of the name, if rotated). | ||
lat_coord, lon_coord = _get_lat_lon_coords(cube) | ||
x_coord, y_coord = cube.coord(axis="X"), cube.coord(axis="Y") | ||
cs = cube.coord_system('CoordSystem') | ||
|
||
if lon_coord.units != 'degrees': | ||
lon_coord = lon_coord.unit_converted('degrees') | ||
if lat_coord.units != 'degrees': | ||
lat_coord = lat_coord.unit_converted('degrees') | ||
|
||
lons = lon_coord.contiguous_bounds() | ||
lats = lat_coord.contiguous_bounds() | ||
lons, lats = numpy.meshgrid(lons, lats) | ||
if isinstance(cs, iris.coord_systems.RotatedGeogCS): | ||
lons, lats = iris.analysis.cartography.unrotate_pole(lons, lats, cs.grid_north_pole_longitude, cs.grid_north_pole_latitude) | ||
return (lats, lons) | ||
x = x_coord.contiguous_bounds() | ||
y = y_coord.contiguous_bounds() | ||
x, y = numpy.meshgrid(x, y) | ||
|
||
return (x, y) | ||
|
||
|
||
def _quadrant_area(radian_colat_bounds, radian_lon_bounds, radius_of_earth): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole example can ow be significantly simplified - just let points/contour/pcolor figure out the range automatically (this wasn't possible before with Basemap).