Skip to content

DEVEL: Isolating misbehaving polygons in cartopy's matplotlib interface

Phil Elson edited this page Aug 28, 2013 · 2 revisions

Suppose there is a bug that you would like to track down relating to a contour being drawn in matplotlib, but being transformed in cartopy, it is important to be able to isolate the bad polygon in question so that we can target a fix, and ultimately add a test to ensure that the fix continues to be effective through future cartopy versions. This wiki covers the details on how to reduce the scope of the problem so that it is easy to classify and ultimately quicker to fix.

  1. The first step is to be able to reproduce the problem consistently, if you can't do that, then there is a much bigger problem for which you should report as much information as possible.

  2. Identify the level in your contour which is causing the problem. To do this, pick contour levels manually, and do some leg-work to figure out which specific (hopefully it is just one) level which is causing the issue.

  3. Now that we have reduced the number of contours down to a single level, we can go ahead and identify a specific polygon in that level. The following code creates a contour (without using cartopy) and then attempts to transform that polygon using cartopy - if an error occurs then the index of the geometry is printed, and you've successfully isolated the path in question. You can then report this single path, or even better, just the shapely geometry which causes the issue:

import cartopy.crs as ccrs
import numpy as np
import matplotlib.pyplot as plt
from cartopy.mpl.patch import path_to_geos

data = np.linspace(0, 20, 12 * 14).reshape([12, 14])
data = np.sin(data) + np.cos(data) ** 2

cs = plt.contourf(data, levels=[0.5, 0.6])

source = ccrs.PlateCarree()
target = ccrs.Mercator()

for collection in cs.collections:
    for i, path in enumerate(collection.get_paths()):
        for geom in path_to_geos(path):
            try:
                target.project_geometry(geom, source)
            except:
                print 'Bad poly at index', i, geom
                raise

plt.show()
  1. Finally, it might still be possible to simplify the polygon/path to fewer coordinate points - the fewer to reproduce the better. It is certainly unmanageable to store several hundred coordinate values in a test, so anything under ~40 coordinate points is best.

  2. Submit/fix the issue with the newly isolated geometry.