问题
I am working with some weather data to plot contour lines on basemap using matplotlib. The data I have used (x, y and data) is uploaded here http://www.mediafire.com/download/0epjjdm8auit611/mslp.txt here http://www.mediafire.com/download/1dn6p8nw96h2mmd/xlong.txt and here http://www.mediafire.com/download/31suzsz6j7u2bgz/xlat.txt. The working example code is below:-
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
m = Basemap(projection='merc', llcrnrlat=7, urcrnrlat=40,
llcrnrlon=68, urcrnrlon=110, resolution='l')
x = np.loadtxt('xlong.txt', delimiter=',')
y = np.loadtxt('xlat.txt', delimiter=',')
Z = np.loadtxt('mslp.txt', delimiter=',')
x, y = m(x, y)
CS = plt.contour(x, y, Z, colors='b')
plt.show()
The above code gives me the following plot...
The plot is absolutely OK. But I would like to hide/ remove contour lines over a particular area. So, I have drawn a polygon over a basemap and tried to hide data beneath the polygon. The code I have used for doing is as follows:-
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Polygon
def draw_screen_poly(lats, lons, m):
x, y = m(lons, lats)
xy = zip(x, y)
poly = Polygon(xy, facecolor='red')
plt.gca().add_patch(poly)
lats = [30, 35, 35, 30]
lons = [80, 80, 90, 90]
m = Basemap(projection='merc', llcrnrlat=7, urcrnrlat=40,
llcrnrlon=68, urcrnrlon=110, resolution='l')
x = np.loadtxt('xlong.txt', delimiter=',')
y = np.loadtxt('xlat.txt', delimiter=',')
Z = np.loadtxt('mslp.txt', delimiter=',')
x, y = m(x, y)
CS = plt.contour(x, y, Z, colors='b')
draw_screen_poly(lats, lons, m)
plt.show()
The resulting image is lloking like below. As you can see, there is no effect of facecolour
as it does not hide any data beneath it.
What I want to do is either remove contour lines passing through this polygon or hide/ clip the polygon area using image processing technique.
The solution I think of are:-
1. Apply some white colour to polygon region so that it matches the basemap colour and data is hidden (this is already done in the above example and does not work).
2. Go through each contour from contour collection and check if it is passing through the polygon region. Finally remove it from plot.
3. Finally, Chip off the polygon area.
My mind is not proceeding beyond above ideas. Any solution to solve this issue is highly appreciated.
回答1:
The Basemap toolkit for matplotlib follows most of the same logic as matplotlib itself. You'll notice that you have zorder arguments to give to your plot calls. You just need to make sure that the zorder of the rectangle is higher than the zorder
of the contour.
Recently I've given an awnser for a similar question here. The code logic should be reproducible for you example:
import numpy as np
import matplotlib.pyplot as plt
t = np.arange(-1, 2, .01)
s = np.sin(2*np.pi*t)
plt.plot(t, s,zorder=4)
p = plt.axvspan(1.25, 1.55, facecolor='g', alpha=1,zorder=3)
plt.axis([-1, 2, -1, 2])
plt.grid(zorder=2)
plt.show()
, notice how the axvspan
and the plot
data itself is forced to be on top of the grid
(by tinkering with the zorder
).
EDIT: Working example of contour plot with lower zorder than a rectangle.
import matplotlib
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
matplotlib.rcParams['xtick.direction'] = 'out'
matplotlib.rcParams['ytick.direction'] = 'out'
delta = 0.025
x = np.arange(-3.0, 3.0, delta)
y = np.arange(-2.0, 2.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
# difference of Gaussians
Z = 10.0 * (Z2 - Z1)
# Create a simple contour plot with labels using default colors. The
# inline argument to clabel will control whether the labels are draw
# over the line segments of the contour, removing the lines beneath
# the label
fig = plt.figure()
ax = fig.add_subplot(111)
CS = plt.contour(X, Y, Z,zorder=3)
plt.clabel(CS, inline=1, fontsize=10)
plt.title('Simplest default with labels')
rect1 = matplotlib.patches.Rectangle((0,0), 2, 1, color='yellow',zorder=5)
ax.add_patch(rect1)
plt.show()
, which results in:
, the original is:
, which brings the labels there.
来源:https://stackoverflow.com/questions/36578628/how-to-remove-contour-path-inside-ploygon-on-basemap-using-matplotlib