-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
DOC: Revive Irregularly spaced data contour example #11180
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
Merged
dstansby
merged 1 commit into
matplotlib:master
from
ImportanceOfBeingErnest:revive-irregular-data-contour-example
May 8, 2018
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
105 changes: 105 additions & 0 deletions
105
examples/images_contours_and_fields/irregulardatagrid.py
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
""" | ||
======================================= | ||
Contour plot of irregularly spaced data | ||
======================================= | ||
|
||
Comparison of a contour plot of irregularly spaced data interpolated | ||
on a regular grid versus a tricontour plot for an unstructured triangular grid. | ||
|
||
Since :meth:`~.axes.Axes.contour` and :meth:`~.axes.Axes.contourf` expect the | ||
data to live on a regular grid, plotting a contour plot of irregularly spaced | ||
data requires different methods. The two options are: | ||
|
||
* Interpolate the data to a regular grid first. This can be done with on-borad | ||
means, e.g. via `~.tri.LinearTriInterpolator` or using external functionality | ||
e.g. via `scipy.interpolate.griddata`. Then plot the | ||
interpolated data with the usual :meth:`~.axes.Axes.contour`. | ||
* Directly use :meth:`~.axes.Axes.tricontour` or | ||
:meth:`~.axes.Axes.tricontourf` which will perform a triangulation | ||
internally. | ||
|
||
This example shows both methods in action. | ||
""" | ||
|
||
import matplotlib.pyplot as plt | ||
import matplotlib.tri as tri | ||
import numpy as np | ||
|
||
np.random.seed(19680801) | ||
npts = 200 | ||
ngridx = 100 | ||
ngridy = 200 | ||
x = np.random.uniform(-2, 2, npts) | ||
y = np.random.uniform(-2, 2, npts) | ||
z = x * np.exp(-x**2 - y**2) | ||
|
||
fig, (ax1, ax2) = plt.subplots(nrows=2) | ||
|
||
# ----------------------- | ||
# Interpolation on a grid | ||
# ----------------------- | ||
# A contour plot of irregularly spaced data coordinates | ||
# via interpolation on a grid. | ||
|
||
# Create grid values first. | ||
xi = np.linspace(-2.1, 2.1, ngridx) | ||
yi = np.linspace(-2.1, 2.1, ngridy) | ||
|
||
# Perform linear interpolation of the data (x,y) | ||
# on a grid defined by (xi,yi) | ||
triang = tri.Triangulation(x, y) | ||
interpolator = tri.LinearTriInterpolator(triang, z) | ||
Xi, Yi = np.meshgrid(xi, yi) | ||
zi = interpolator(Xi, Yi) | ||
|
||
# Note that scipy.interpolate provides means to interpolate data on a grid | ||
# as well. The following would be an alternative to the four lines above: | ||
#from scipy.interpolate import griddata | ||
#zi = griddata((x, y), z, (xi[None,:], yi[:,None]), method='linear') | ||
|
||
|
||
ax1.contour(xi, yi, zi, 14, linewidths=0.5, colors='k') | ||
cntr1 = ax1.contourf(xi, yi, zi, 14, cmap="RdBu_r") | ||
|
||
fig.colorbar(cntr1, ax=ax1) | ||
ax1.plot(x, y, 'ko', ms=3) | ||
ax1.axis((-2, 2, -2, 2)) | ||
ax1.set_title('grid and contour (%d points, %d grid points)' % | ||
(npts, ngridx * ngridy)) | ||
|
||
|
||
# ---------- | ||
# Tricontour | ||
# ---------- | ||
# Directly supply the unordered, irregularly spaced coordinates | ||
# to tricontour. | ||
|
||
ax2.tricontour(x, y, z, 14, linewidths=0.5, colors='k') | ||
cntr2 = ax2.tricontourf(x, y, z, 14, cmap="RdBu_r") | ||
|
||
fig.colorbar(cntr2, ax=ax2) | ||
ax2.plot(x, y, 'ko', ms=3) | ||
ax2.axis((-2, 2, -2, 2)) | ||
ax2.set_title('tricontour (%d points)' % npts) | ||
|
||
plt.subplots_adjust(hspace=0.5) | ||
plt.show() | ||
|
||
############################################################################# | ||
# | ||
# ------------ | ||
# | ||
# References | ||
# """""""""" | ||
# | ||
# The use of the following functions and methods is shown in this example: | ||
|
||
import matplotlib | ||
matplotlib.axes.Axes.contour | ||
matplotlib.pyplot.contour | ||
matplotlib.axes.Axes.contourf | ||
matplotlib.pyplot.contourf | ||
matplotlib.axes.Axes.tricontour | ||
matplotlib.pyplot.tricontour | ||
matplotlib.axes.Axes.tricontourf | ||
matplotlib.pyplot.tricontourf |
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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
OK, Hmmmm. I'm not 100% convinced that we should suggest people use the in-house triangular and interpolator. In the same vein that
mlab
is going away, my guess is thattri
will go away. I'd rather we tell people the "best practice" and I'm not sure our sparsely documented in-house triangulation routine is that. Happy to be corrected, but I'd lean towards the scipy reference.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.
@jklymak I assure you that
tri
is not going to "go away". What on earth possessed you to assert such a guess?I am 100% convinced that we should suggest people use the in-house triangulator and interpolator, and unlike yourself I am an expert in the area. Consider yourself corrected, and in future kindly refrain from expressing derogatory opinions on functionality you have no knowledge of.
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.
I wasn’t meaning to be offensive about the actual algorithm, any more that I would be about mlab.psd. Just that it does something that scipy also does. Do we need to be providing duplicate functionality, and more importantly do we want to guide users to this code?
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.
I don't think what @jklymak said was particularly derogatory...
Is there a reason Matplotlib runs a custom triangulator, and doesn't use an upstream one? And if ours is better than what is available in either numpy or scipy, should we try and push the mpl triangulation code upstream? It feels to me like that's where good triangulation code should live.
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.
I don't think this is about triangulation. It's about the interpolators from
tri.triinterpolate
.I cannot judge on whether they are needed or not, but here are the timings from the example:
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.
I'm totally in favor of sharing the love in any stream direction.
In this particular case the motivation is to share the love with users looking for ways to plot irregularly spaced data.
One way of doing so is to inform them about the in-built option for interpolation. Since this in-built option will not vanish from the 2.2 branch with 110% certainty, there is nothing wrong with using that for now. And it would prevent the necessity to include a new large dependecy for the docs during the final stage of this branch.
For the development branch, one may sure discuss if it's useful to change the example and include scipy (a 12 Mb package, 40 Mb extracted) as documentation dependency.
I do not have a clear opinion on that, but I wouldn't want to wait to include this example until someone may or may not have shared their love for
tri
upstream (and got their love returned).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.
There is no 'upstream', no de facto standard library for representing and manipulating triangular grids in python. If there was, we should certainly use it. Until then, we are one of the gathering places for such functionality. It started as just rendering triangular grids, which is clearly within our remit, and when interpolation and mesh refinement were implemented they were added to our code as the best (least bad?) place to put them as our code is actively maintained and will be around for a long time.
Numpy isn't the place for such functionality, scipy would be more appropriate but I don't think it is as suitable as a specific tri grids library (named
tripy
perhaps?). Every so often there is an interest in such as library, but after lots of chat my summary is that there are plenty of people who want to use such a library, nobody wants to write it. From my point of view, even if atripy
existed the rendering of tri grids, which is what I am mostly interested it, would still reside within mpl.Without delving too deeply into the workings of our tri code, there are three use cases for creating and using a triangulation object:
scipy.griddata can only deal with use case 1, our code deals with all three. Unfortunately use case 1 is the one that most examples refer to as it is the entry point to triangular grids for those not used to them. But nearly all serious tri grid work uses the other 2 use cases.
Hence we should not recommend using scipy.griddata, it simply doesn't include the functionality that our code requires and has. But unfortunately we can't just ignore it and not mention it in such examples; we need to keep it as there are lots of historical web pages mentioning griddata, and we need to catch the attention of people looking for it so that we can point out our alternatives. Keeping it in this example but just within a comment is an approach that I like.
Unfortunately griddata have been around for years and people are familiar with it, so anyone who asks about tri grids receives a well-intended but sub-optimal answer to interpolate to a regular grid. It is simply unnecessary. Everyone should use
tricontour
for optimal results: the boundaries and masked areas are correct, it has higher resolution where the grid has higher resolution. If higher resolution is required, there is an excellentTriRefiner
that creates a new triangulation, keeping sensible boundaries, etc and can avoid badly-formed triangles (e.g. long and thin); it is featured in thetricontour_smooth_delaunay
andtricontour_smooth_user
examples.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 is quite a bit of useful information. I think it shouldn't stay hidden inside the review section of a PR; but is there any good place for such meta information to be stored?
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.
Thanks for taking the time to explain, and sorry for all of our questions.
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.
@ianthomas23 Thanks for the explanations. I agree that the tri-mesh plotting utilities that I assume you have developed are very impressive. Having the ability to plot directly from a tessellation is hugely useful, particularly in fields where a finite-volume modelling approach has been used. I certainly never meant that those capabilities should be curtailed or go away. OTOH I agree w/ @ImportanceOfBeingErnest that they should get their own tutorial. Unless you are looking for tri-grid solutions, the examples in the examples directory are clearly labeled, but obscure.
gridding data sets is often necessary for reasons other than direct data presentation, usually in the context of comparing to another data set that is supplied on a regular grid.