Cody Piersall
Cody Piersall

Reputation: 8547

How to Smooth a Plot in Matplotlib Without Losing Contour Lines?

I have some jagged contour plots that I need to smooth. I need to smooth them out without losing any of the contour lines. I have referred to these SO questions, but they don't quite offer a solution to my problem. Without any kind of filter, my plots look like this:

enter image description here

You can see that the outer contours are very jagged, and so are not presentation quality. If I run the data through a Gaussian filter of order 0 and sigma 2, (i.e., scipy.ndimage.gaussian_filter(z, 2)), it smooths out the plots, but I lose the inner contours:

Gaussian interpolation -- note the missing inner contours

What is the best way to smooth the plot without losing the inner contours? The nature of the data I work with is that it always has the highest values near the center. Filtering spreads out the information and makes the inner contours disappear. These are the most important contours: the contours represent the risk for a loss of life, so generally the higher the value the more important it is.

I have considered two methods of smoothing the contour lines.

  1. Get each contour line coordinates via contour_object.collections[col_index].get_paths()[path_index].vertices and smooth / re-plot each one. This seems possible, but inelegant, and I'm not sure where to start on it.
  2. Apply a Gaussian filter only on data greater than a certain value: e.g., 5*10-6. That is easy to do (loop through the array of data, and take from the original set if the value is greater than the cutoff, and the filtered set if it is not), but seems pretty arbitrary and difficult to justify.

I would like to do something like the first option, but it seems kind of like a hack. What is the best way to smooth out these contour plots?

Upvotes: 3

Views: 3785

Answers (1)

ely
ely

Reputation: 77424

Smoothing data -> losing data.

My first reaction is: why do you want to display smoothed data? I've rarely ever seen data presentations in which data smoothing was actually helpful for the task of comprehending the data's implications. In fact, it's something Tufte has often criticized (that's not a reason to avoid doing it of course, but perhaps for asking yourself to come up with more justification than normal).

If the plot needs to look pretty for some non-data-related reason, that's totally OK, but if you're trying to make it more pleasing to the eye when the task is to understand something about the nature of the contours, you're way better off just presenting the raw data as it is.

If you have the different contours stored as separate sets of data (e.g. if you just steal the different line plot data sets that the contour plotter is using) then you could apply smoothing to only those contours where the data loss from smoothing is acceptable, and leave the smaller, inner contours unsmoothed and jagged.

Or you can tinker with the parameters of the smoothing so that your smoothing kernel is narrow enough that it doesn't completely kill the tiny inner rings from your data set.

In principle though, there's no way to "smooth" data without "losing" data in some sense, and any method of doing this that isn't applied uniformly to the whole data set is going to be suspicious.

Added:

Why not make the figure as a series of two plots? The large smoothed plot that you already have (with some data missing due to the smoothed display) and then a plot to the side that is just the zoomed-in version only containing the small contours that were dropped. This (along with proper titles and captions) will draw attention to the smoothing so that there's no risk of anyone misunderstanding the fact that the smoothed plot is altered data, and lets you display the prettier large contours with another panel for the uglier, jagged small contours. It also adds a nice visual mix of the smoothed vs. raw data, which is often a good effect for plots like this.

Upvotes: 4

Related Questions