calling contour without plotting it, python, pylab inline
Asked Answered
U

4

6

For an algorithm I am using contour, but I'm only interested in its collection of paths. Since I have called

pylab inline

from the start, and it is now too painful to rewrite the code without the inline (many functions have to be declared more carefully, like np.something() instead of something(), etc...), I was wondering if there is a way to call contour without it plotting the contour map ? Something like

contour(image_matrix, 'No Show')? 

Regards

Unideaed answered 21/5, 2015 at 14:36 Comment(0)
L
4

The following is a modified code i used to get the points on a unit circle within in a declared meshgrid. It gives the contour points faster than plt.contour and doesn't plot the points.

The matplotlib._cntr is the core function called by plt.contour which tries to get the contour points.

import matplotlib._cntr as cntr
import numpy as np

# Test data.
x = np.linspace(-1, 1, 20)
y = np.linspace(-1, 1, 20)

x, y = np.meshgrid(x, y)
z = x**2 + y**2 - 1            # Function to get points from
# the above function can be replaced with any curve equation
# conics like ellipse or hyperbola: ((x**2)/a)+((y**2)/b)-1,etc. 


level = 0
c = cntr.Cntr(x, y, z)
nlist = c.trace(level, level, 0)
segs = nlist[:len(nlist)//2]
print segs[0][0]    # x,y coords of contour points.

Sorry for the poor explaination, I am not experienced enough with python. For a detailed explanation so you can refer to the link below.

link to discussion: http://matplotlib.1069221.n5.nabble.com/pyplot-Extract-contourset-without-plotting-td15868.html

At the end of discussion Mr.Ian Thomas has attached a code 'contour_test.py' which may be of help to you.

link to sample code: http://matplotlib.1069221.n5.nabble.com/attachment/15872/0/contour_test.py

Light answered 9/6, 2017 at 9:38 Comment(1)
"_cntr is not part of matplotlib any more". See: #49160642Geist
O
2

There is not specific option to suppress plotting of a contour (as far as I can see). The following question appears to provide exactly what you want using matplotlib._cntr.

For your case, it may be simpler to achieve the suppression of a figure in pylab inline by switching back to a different gui, e.g. using %pylab qt and then call cs = contour(image_matrix). This may not show anything without an explicit call to plt.show() and you can use cs to get the contour information you need.

You may also be able to use something like matplotlib.interactive(False) to suppress the figure.

Oxpecker answered 21/5, 2015 at 15:44 Comment(0)
K
1

Because matplotlib._cntr is not supported anymore, you can use the find_contour() function from skimage. Here is a simple code to extract a contour level 0.8 from an analytical function from the documentation.

import numpy as np
from skimage import measure

# Construct some test data
x, y = np.ogrid[-np.pi:np.pi:100j, -np.pi:np.pi:100j]
r = np.sin(np.exp((np.sin(x)**3 + np.cos(y)**2)))

# Find contours at a constant value of 0.8
contours = measure.find_contours(r, 0.8)

This will give you the contour in function of (row, column) coordinates along the contour, and not the value of x and y. To convert to x and y values, you can then interpolate using interp1d from scipy:

from scipy.interpolate import interp1d
fx = interp1d(np.arange(0,x.shape[0]), x.flatten())
fy = interp1d(np.arange(0,y.shape[1]), y.flatten())
for contour in contours:
    contour[:,0] = fx(contour[:,0])
    contour[:,1] = fy(contour[:,1])

Simple code to see the results and validate:

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
for contour in contours:
    ax.plot(contour[:,0], contour[:,1])
fig.show()

Figure of the extracted contours

Kab answered 29/3, 2019 at 15:21 Comment(4)
This becomes ridiculously difficult and computation-heavy if you try to do this in irregular (inseparable) grid. Is there any way to apply find_contour without having to deal with transformations via interpolation? Also, it seems that find_contour and matplotlib contour result in slightly different ones, and in my cases matplotlib contour seems far robust. It is such a frustration that matplotlib discontinued cntr functionality...Sophistic
Do you have an example?Kab
You can also take a look at the legacy contour repo.Kab
Another option might be to define a "throwaway" figure, use contour on that and then define another figure on which the actual plot for displaying is defined.Finable
P
1

There is a better way now. They have split off the underlying code into a new package called contourpy. In my case, the required code was simply:

from contourpy import contour_generator
cg = contour_generator(X, Y, Z)
contours = cg.lines(0.98*Z.min())

which gives me a polygon at 98% of the minimum of a Z matrix.

Preuss answered 22/6 at 1:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.