Python 使用底图时更改地图投影

Python 使用底图时更改地图投影,python,matplotlib,matplotlib-basemap,Python,Matplotlib,Matplotlib Basemap,我以前在basemap中更改过地图投影,所以我知道这应该是一个简单的修复方法,但对我来说似乎没有任何效果。我使用了网格,映射了我的x,y值等等,我得到了扭曲或疯狂的绘图。我认为这与我使用的数据被自动设置为绘制在Lambert共形图上(我不想要),并且尺寸是以km为单位的,而不是以lat和lon为单位的事实有关。我不知道从这里到哪里去 数据来源: 这是我的工作代码。我有一大堆被评论过的东西,我一直在尝试,但运气不好 import numpy as np import math as m impor

我以前在basemap中更改过地图投影,所以我知道这应该是一个简单的修复方法,但对我来说似乎没有任何效果。我使用了网格,映射了我的x,y值等等,我得到了扭曲或疯狂的绘图。我认为这与我使用的数据被自动设置为绘制在Lambert共形图上(我不想要),并且尺寸是以km为单位的,而不是以lat和lon为单位的事实有关。我不知道从这里到哪里去

数据来源:

这是我的工作代码。我有一大堆被评论过的东西,我一直在尝试,但运气不好

import numpy as np
import math as m
import urllib2
import time
import datetime as dt
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
from mpl_toolkits.basemap import Basemap, shiftgrid
from matplotlib.colors import LinearSegmentedColormap
from pydap.client import open_url
from pydap.proxy import ArrayProxy
import scipy

data_url = 'http://thredds.ucar.edu/thredds/dodsC/grib/NCEP/RAP/CONUS_13km/RR_CONUS_13km_' + '20150415' + '_' + '01' + '00.grib2/GC'

print('Getting Data from URL:\n\n    "{0}"\n'.format(data_url))

# Create Array of all data from URL
dataset = open_url(data_url)

# Map Projection Info

proj_attributes = dataset['LambertConformal_Projection'].attributes
rsphere = proj_attributes['earth_radius']

lat_0 = proj_attributes['latitude_of_projection_origin']
lon_0 = proj_attributes['longitude_of_central_meridian'] 
lat_1 = proj_attributes['standard_parallel']

llcrnrlat = 16.28100013732909 # (1,1)
llcrnrlon = 360-126.18 # (1,1)

urcrnrlat = 55.552133975329625 # (614,428)
urcrnrlon = 360-59.15590040502627 # (614,248)

x = np.array(dataset['x'][:])
y = np.array(dataset['y'][:])

def xy_converter(var):
    """
    Downloads entered variable (x or y) coordinates 
    and converts from m to km.  Inputs for var 
    should be 'x' or 'y'.
    """
    values = dataset[var][:]
    data_array = values * 1000
    newarray = data_array + abs(data_array.min())
    return newarray

# Download x & y coord. and convert m to km
x = xy_converter('x')
y = xy_converter('y')

# Temp Contour
temp_2m = dataset['Temperature_height_above_ground'].array[1,:,:,:]-273.
temp_2m = temp_2m * (9./5.) + 32.
temp_2m    = temp_2m.squeeze() 

#plot
fig = plt.figure(figsize=(11,11))
ax = fig.add_subplot(1,1,1)

map = Basemap(projection='lcc', lat_0 = lat_0, lon_0 = lon_0,
                                     llcrnrlon = llcrnrlon, llcrnrlat = llcrnrlat,
                                     urcrnrlat = urcrnrlat, urcrnrlon = urcrnrlon,
                                     area_thresh = 1000., rsphere = rsphere, resolution='i')
map.drawcoastlines(linewidth=0.3)
map.drawcountries(linewidth=0.3)
map.drawcounties(linewidth=0.1)
map.drawstates(linewidth=0.3)
map.drawmapboundary(linewidth=0.5)

#lons,lats = basemap_parameters.map(x,y)
#lon,lat = basemap_parameters.map(lons,lats,inverse=True)

#ny = range(len(y)); nx = range(len(x))
#ny = temp_2m.shape[0]; nx = temp_2m.shape[1]
#lons, lats = map(x, y) # get lat/lons of ny by nx evenly space grid.
#xx, yy = map(lons, lats)

levels = np.linspace(-42,122,320)
ticks = [-60,-50,-40,-30,-20,-10,0,10,20,30,40,50,60,70,80,90,100,110,120]  

plot = plt.contourf(x,y,temp_2m,levels,cmap='jet',extend='both')

# Set Colorbar Text Color
color_bar = map.colorbar(plot)
color_bar.set_ticks(ticks)

# CONUS
plt.xlim(x[30],x[440])
plt.ylim(y[30],y[290])    
plt.savefig('/home/public_html/conus_temp.png', dpi=100, bbox_inches='tight', pad_inches = .05)
  • 首先,您不应该将basemap实例定义为
    map
    ——它隐藏了Python内置的
    map()
    函数,只会造成混乱
  • 其次,下载的
    x
    y
    值的长度不同(分别为451和337个值)。在我们尝试其他方法之前,必须先解决这个问题
  • 我不知道为什么要将x和y数据(LCC中的投影坐标?)除以1000进行转换
无论如何,明智的做法如下:

下载数据,并使用Pyproj将坐标从LCC转换为lon/lat:

import pyproj
lc = pyproj.Proj("+proj=lcc +lat_1=33 +lat_2=45 +lat_0=40 +lon_0=-97 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs")
lons, lats = lc(x, y, inverse=True)
# lons & lats are now unprojected WGS84
将坐标转换为所需的地图投影坐标:

# now you can get ll and ur lons and lats
# set up your basemap with whatever projection you'd like, e.g.
m = Basemap(
    projection = 'merc',
    llcrnrlon = lllon, llcrnrlat = lllat, urcrnrlon = urlon, urcrnrlat = urlat,
    resolution='h')
# project lons & lats into map coordinates
projected_lons, projected_lats = m(x, y)
现在我们可以做其他事情:

我不确定你的温度数据是否已经插值到网格中。如果不是:

from matplotlib.mlab import griddata
# set up a square grid with the same extents as our measured data
numcols, numrows = 1000, 1000
xi = np.linspace(projected_lons.min(), projected_lons.max(), numcols)
yi = np.linspace(projected_lats.min(), projected_lats.max(), numrows)
# get lon and lat coords of our grid points
xi, yi = np.meshgrid(xi, yi)
# interpolate
x, y, z = projected_lons, projected_lats, temp2m
zi = griddata(x, y, z, xi, yi)
按照常规设置其他地图细节,并使用contourf绘制(不要使用jet colormap!)


您对
pyproj.Proj
的参数是否有误他的数据只有一个标准平行线(25度)。
conf = m.contourf(xi, yi, zi, cmap='coolwarm', ax=ax)