Python颤抖和pcolormesh排列不正确 [英] Python quiver and pcolormesh not lining up exactly right

查看:108
本文介绍了Python颤抖和pcolormesh排列不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图用风速的pcolormesh在地图上叠加风场的颤动图.

from mpl_toolkits.basemap import Basemap
from pylab import * 

lonMin = 115.5
lonMax = 124.5
latMin = 10
latMax = 20

res = 0.25
lonGrid = arange(lonMin, lonMax, res)
latGrid = arange(latMin, latMax, res)
lonGrid,latGrid = meshgrid(lonGrid,latGrid)

u = random(lonGrid.shape)
v = random(lonGrid.shape)
m = Basemap(llcrnrlon=lonMin,llcrnrlat=latMin,urcrnrlon=lonMax,urcrnrlat=latMax, resolution = 'i')

m.pcolormesh(lonGrid, latGrid, sqrt(u**2+v**2))
m.quiver(lonGrid,latGrid,u,v, latlon = 'true')
m.drawcoastlines()
m.fillcontinents()

这给了我类似下面的情节

我注意到两件事:

  1. 颤动箭头发自pcolormesh而不是中心的像素的左下角
  2. 情节的上边框和最右边框未着色

这到底是怎么回事,我该如何解决?

解决方案

您的代码存在一些问题.

首先,避免使用from pylab import *,这将严重污染您的命名空间.

第二,在顶部和右侧缺少数据:这是由于pcolormesh的行为所致,它模仿了同名的MATLAB函数.引用功能相似的pcolor 的文档:

pcolor(X, Y, C, **kwargs)

[...]

理想地,X和Y的尺寸应比C的尺寸大一;如果尺寸相同,则C的最后一行和最后一列将被忽略.

因此,您可以使用纬度/经度的辅助数组来消除空白边框.另外,我建议使用imshow,其底图版本会自动调整比例,以使绘制的图像跨过可见图.将您的pcolormesh呼叫切换到

m.imshow(sqrt(u**2+v**2),interpolation='none')

你得到

现在,最后一个问题是如何尝试可视化数据.您的数据是什么?在上图中,数据点对应于每个像素"的右下角,即(lat,lon)点的位置.因此,当前的可视化效果如下:每个箭头均从其对应的点开始,每个像素均对应于其左下角的数据.

您想要做的就是以某种方式将那些箭头移到像素中心.如果要精确,则实际上需要移动像素,因为颤动图在定义上应位于应有的位置.另一种选择是保持地图不变,并移动颤动图(此版本的基本原理是离散化数据,并且在像素范围内,箭头/像素的放置位置都无关紧要). /p>

由于我认为,如果您的箭矢箭头停留在更精确的位置,我建议将整个底图移动半个(lat,lon)单位,以使像素位于实际数据点的中心.您可以通过将pivot='middle'选项传递给quiver使其最漂亮:在这种情况下,您的箭头将以数据点(位于每个像素的中间)为中心,而不是从这些点出发:

from mpl_toolkits.basemap import Basemap
#from pylab import * 
from pylab import arange,meshgrid,random,sqrt

lonMin = 115.5
lonMax = 124.5
latMin = 10
latMax = 20

res = 0.25
lonGrid = arange(lonMin, lonMax, res)
latGrid = arange(latMin, latMax, res)
lonGrid,latGrid = meshgrid(lonGrid,latGrid)

u = random(lonGrid.shape)
v = random(lonGrid.shape)
m = Basemap(llcrnrlon=lonMin-res/2,llcrnrlat=latMin-res/2,
            urcrnrlon=lonMax-res/2,urcrnrlat=latMax-res/2,
            resolution='i') # shifted!
# data corresponds to (latGrid,lonGrid)
# basemap plot is shifted with (-res/2,-res/2)
# imshow will automatically use the visible map anyway

m.imshow(sqrt(u**2+v**2), interpolation='none')
m.quiver(lonGrid,latGrid,u,v, latlon='true', pivot='middle')
m.drawcoastlines()
m.fillcontinents()

生成的图看起来相当不错,现在很明显,颜色与箭头的大小有关:

I am trying to overlay a quiver plot of wind field on a map with a pcolormesh of the windspeed.

from mpl_toolkits.basemap import Basemap
from pylab import * 

lonMin = 115.5
lonMax = 124.5
latMin = 10
latMax = 20

res = 0.25
lonGrid = arange(lonMin, lonMax, res)
latGrid = arange(latMin, latMax, res)
lonGrid,latGrid = meshgrid(lonGrid,latGrid)

u = random(lonGrid.shape)
v = random(lonGrid.shape)
m = Basemap(llcrnrlon=lonMin,llcrnrlat=latMin,urcrnrlon=lonMax,urcrnrlat=latMax, resolution = 'i')

m.pcolormesh(lonGrid, latGrid, sqrt(u**2+v**2))
m.quiver(lonGrid,latGrid,u,v, latlon = 'true')
m.drawcoastlines()
m.fillcontinents()

This gives me something like the below plot

Two things I notice:

  1. The quiver arrows emanate from the lower left corner of the pixels generated from pcolormesh, rather than the center
  2. the upper and right-most border of the plot isn't colored

What exactly is going on here, and how do I fix it?

解决方案

There are a few problems with your code.

First of all, avoid using from pylab import *, that will pollute your namespace horribly.

Secondly, the missing data on top and to the right: this is due to the behaviour of pcolormesh, which mimics the MATLAB function of the same name. Quoting the documentation of the functionally similar pcolor where this is explained:

pcolor(X, Y, C, **kwargs)

[...]

Ideally the dimensions of X and Y should be one greater than those of C; if the dimensions are the same, then the last row and column of C will be ignored.

So you can get rid of the empty borders by using an auxiliary array of latitudes/longitudes. Alternatively, I suggest using imshow, the basemap version of which automatically adjusts the scale such that the plotted image spans the visible map. Switching your pcolormesh call to

m.imshow(sqrt(u**2+v**2),interpolation='none')

you get

Now, the last issue is how you are trying to visualize your data. What is your data? In the above plot, data points correspond to the bottom right of each "pixel", that is where your (lat,lon) points are situated. So the current visualization is such: each arrow starts from the point it corresponds to, and each pixel corresponds to data on its lower left corner.

What you want to do is somehow shift those arrows into the center of pixels. If you want to be precise, you actually need to shift the pixels, since the quiver plot is by definition where it should be. The other option is to leave your map as-is, and shift the quiver plots (the rationale behind this version is that you discretize your data, and on a pixel scale it doesn't matter where you put the arrows/pixels).

Since in my opinion it is more exact if your quiver arrows stay where they are, I suggest shifting the whole basemap by half a (lat,lon) unit so that pixels are centered on actual data points. You can make it prettiest by passing the pivot='middle' option to quiver: in this case your arrows will be centered on data points (this situated in the middle of each pixel) rather than originating from said points:

from mpl_toolkits.basemap import Basemap
#from pylab import * 
from pylab import arange,meshgrid,random,sqrt

lonMin = 115.5
lonMax = 124.5
latMin = 10
latMax = 20

res = 0.25
lonGrid = arange(lonMin, lonMax, res)
latGrid = arange(latMin, latMax, res)
lonGrid,latGrid = meshgrid(lonGrid,latGrid)

u = random(lonGrid.shape)
v = random(lonGrid.shape)
m = Basemap(llcrnrlon=lonMin-res/2,llcrnrlat=latMin-res/2,
            urcrnrlon=lonMax-res/2,urcrnrlat=latMax-res/2,
            resolution='i') # shifted!
# data corresponds to (latGrid,lonGrid)
# basemap plot is shifted with (-res/2,-res/2)
# imshow will automatically use the visible map anyway

m.imshow(sqrt(u**2+v**2), interpolation='none')
m.quiver(lonGrid,latGrid,u,v, latlon='true', pivot='middle')
m.drawcoastlines()
m.fillcontinents()

The resulting plot looks fairly nice, and now it is also obvious that colour is related to the magnitude of the arrows:

这篇关于Python颤抖和pcolormesh排列不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆