Description
For the Astropy project, we provide astronomy-specific transforms that users can use in various Matplotlib methods/artists, including e.g. Axes.contour
. In fact, we have a sub-class of Axes called WCSAxes which until now just inherited the default contour
and contourf
. However, the complexity of the transforms means that there is a small overhead (>1-10ms) for every call to the transform that is unrelated to the number of elements to transform.
In Matplotlib, when drawing contours with a transform:
ax.contour(..., transform=...)
each individual path in the contour is passed to transform_path_non_affine
. This is done here:
https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/collections.py#L191
However, this means that in cases where a contour map has say 1000 individual lines (not that uncommon with some astronomy images), drawing a contour map can take >10s.
I found a solution in astropy/astropy#7568 - override contour
and call matplotlib's contour
without the transform, then modify the vertices in-place afterwards by constructing a single array with all the vertices and transforming it in one go and splitting it up again. The key function is:
https://github.com/astropy/astropy/pull/7568/files#diff-421f6873fdd2d8a90f39f3050534b0c3R139
This dramatically sped up drawing contours in our case. The reason I'm opening this issue (as suggested by @dopplershift on Gitter) is that this solution is not specific to Astropy. In fact, this could be copied almost as-is into Matplotlib if there was interest. In our case, there is basically no downside to doing this performance-wise even when there are very few contour lines, and I think this is generally true for this approach.
Feel free to close this if you'd rather not port this over to Matplotlib though, as there may be subtleties I am not aware of!