2015-01-15 28 views
2

我正在尋找一種解決方法,在Lambert投影中將x和y軸刻度和標籤添加到Cartopy貼圖。Cartopy:軸標籤 - 解決方法

我提出的解決方案只是一種近似方法,它會對較大的地圖產生較差的結果:它涉及使用transform_points方法轉換所需的刻度位置以映射投影。爲此,我使用我的y軸(或x軸)的中值經度(或緯度)以及所需的緯度(或經度)滴答位置來計算地圖投影座標。見下面的代碼。因此,我假設沿着y軸(緯度沿着x軸)的恆定經度,這是不正確的,因此導致偏差。 (請注意所附數字中的差異:set_extent中設置的46°和最終的tick位置)。

有沒有更準確的解決方案呢? 任何提示,我可以如何處理這個問題,否則?

感謝您的任何意見!

import matplotlib.pyplot as plt 
import cartopy.crs as ccrs 
import numpy as np 

def main(): 
    #my desired Lambert projection: 
    myproj = ccrs.LambertConformal(central_longitude=13.3333, central_latitude=47.5, 
            false_easting=400000, false_northing=400000, 
            secant_latitudes=(46, 49)) 

    arat = 1.1 #just some factor for the aspect ratio 
    fig_len = 12 
    fig_hig = fig_len/arat 
    fig = plt.figure(figsize=(fig_len,fig_hig), frameon=True) 
    ax = fig.add_axes([0.08,0.05,0.8,0.94], projection = myproj) 

    ax.set_extent([10,16,46,49]) 
    #This is what is not (yet) working in Cartopy due to Lambert projection: 
    #ax.gridlines(draw_labels=True) #TypeError: Cannot label gridlines on a LambertConformal plot. Only PlateCarree and Mercator plots are currently supported. 
    x_lons = [12,13,14] #want these longitudes as tick positions 
    y_lats = [46, 47, 48, 49] #want these latitudes as tick positions 
    tick_fs = 16 
    #my workaround functions: 
    cartopy_xlabel(ax,x_lons,myproj,tick_fs) 
    cartopy_ylabel(ax,y_lats,myproj,tick_fs) 

    plt.show() 
    plt.close() 

def cartopy_xlabel(ax,x_lons,myproj,tick_fs):  
    #transform the corner points of my map to lat/lon 
    xy_bounds = ax.get_extent() 
    ll_lonlat = ccrs.Geodetic().transform_point(xy_bounds[0],xy_bounds[2], myproj) 
    lr_lonlat = ccrs.Geodetic().transform_point(xy_bounds[1],xy_bounds[2], myproj) 
    #take the median value as my fixed latitude for the x-axis 
    l_lat_median = np.median([ll_lonlat[1],lr_lonlat[1]]) #use this lat for transform on lower x-axis 
    x_lats_helper = np.ones_like(x_lons)*l_lat_median 

    x_lons = np.asarray(x_lons) 
    x_lats_helper = np.asarray(x_lats_helper) 
    x_lons_xy = myproj.transform_points(ccrs.Geodetic(), x_lons,x_lats_helper) 
    x_lons_xy = list(x_lons_xy[:,0]) #only lon pos in xy are of interest  
    x_lons = list(x_lons) 

    x_lons_labels =[] 
    for j in xrange(len(x_lons)): 
     if x_lons[j]>0: 
      ew=r'$^\circ$E' 
     else: 
      ew=r'$^\circ$W' 
     x_lons_labels.append(str(x_lons[j])+ew) 
    ax.set_xticks(x_lons_xy) 
    ax.set_xticklabels(x_lons_labels,fontsize=tick_fs) 

def cartopy_ylabel(ax,y_lats,myproj,tick_fs):   
    xy_bounds = ax.get_extent() 
    ll_lonlat = ccrs.Geodetic().transform_point(xy_bounds[0],xy_bounds[2], myproj) 
    ul_lonlat = ccrs.Geodetic().transform_point(xy_bounds[0],xy_bounds[3], myproj) 
    l_lon_median = np.median([ll_lonlat[0],ul_lonlat[0]]) #use this lon for transform on left y-axis 
    y_lons_helper = np.ones_like(y_lats)*l_lon_median 

    y_lats = np.asarray(y_lats)  
    y_lats_xy = myproj.transform_points(ccrs.Geodetic(), y_lons_helper, y_lats) 
    y_lats_xy = list(y_lats_xy[:,1]) #only lat pos in xy are of interest 

    y_lats = list(y_lats) 

    y_lats_labels =[] 
    for j in xrange(len(y_lats)): 
     if y_lats[j]>0: 
      ew=r'$^\circ$N' 
     else: 
      ew=r'$^\circ$S' 
     y_lats_labels.append(str(y_lats[j])+ew) 
    ax.set_yticks(y_lats_xy) 
    ax.set_yticklabels(y_lats_labels,fontsize=tick_fs) 

if __name__ == '__main__': main() 

enter image description here

回答

1

我(相當粗糙)的變通此詳述在這個筆記本:http://nbviewer.ipython.org/gist/ajdawson/dd536f786741e987ae4e

筆記本需要cartopy> = 0.12。

我所做的一切都是找到相應的網格線與地圖邊界的交點。我假設地圖邊界將始終是矩形,而且我只能標記底部和左側。希望這可能是有用的東西來建立。

+0

感謝您的這種做法!網格線看起來有些扭曲,但放置蜱的功能工作得很好! – user3497890

0

我沒有嘗試過自己,但我注意到在salem package docs有能力處理其他投影的網格線與他們自己的繪圖工具,它不會改變matplotlib的軸的投影。