Python - 使用绘制的地图

时间:2018-02-11 06:24:02

标签: python matplotlib onclick netcdf

因缺乏可重复的例子而提前道歉。我的数据结构的方式使这很困难。

我正在构建程序以帮助我收集数据(在本例中为网格坐标)以训练分类算法。我希望能够从我点击的情节中拉出特定的网格单元格。到目前为止,我使用fig.canvas.mpl_connect('button_press_event', onclick)已经能够使用event.xevent.y提取像素坐标(我也尝试使用event.xdata和{{1}但这似乎给了我一些我不认识的坐标?)但我无法提取我想要的实际数据。

在我的代码中,我使用以下模块:

event.ydata

我的数据来自存储在NetCDF文件中的数据,NetCDF文件是大型模型运行的子集,变量存储为165 * 116阵列(这是网格尺寸)。为了构建我的绘图,我使用以下函数:

from netCDF4 import Dataset # reads netCDF file
from os import listdir
from os.path import isfile, join
import matplotlib.pyplot as plt
import pylab
from mpl_toolkits.basemap import Basemap # basemap tools
from datetime import datetime, timedelta # for working with datetimes
from random import randint
import numpy as np

当使用正确的数据调用时会产生如下情节:

Example plot

现在,我开始感到困惑。我从随机文件的沙子时间制作我的图,并尝试让它们返回我点击的数据并将其保存到数据库中。这是调用上述函数的代码:

def grab_sst_time(time_idx):
    """
    This reads the datetime value in my NetCDF files into local time
    """
    dtcon_days = time[time_idx]
    dtcon_start = datetime(1990,1,1) # This is the "days since" part
    dtcon_delta = timedelta(dtcon_days/24/60/60) # Create a time delta object from the number of days
    dtcon_offset = dtcon_start + dtcon_delta # Add the specified number of days to 1990
    frame_time = dtcon_offset
    return frame_time

def plot_temp(temp, time_idx, fig_no):
    """
    Plot temperature
    """

    # make frame_idx an integer to avoid slicing errors
    frame_idx = int(time_idx)

    # get 'frame_time'
    frame_time = grab_sst_time(frame_idx)

    # map setup
    fig = plt.figure()
    fig.subplots_adjust(left=0., right=1., bottom=0., top=0.9)
    # Setup the map
    m = Basemap(projection='merc', llcrnrlat=-38.050653, urcrnrlat=-34.453367,\
            llcrnrlon=147.996456, urcrnrlon=152.457344, lat_ts=20, resolution='h')
    # draw stuff
    m.drawcoastlines()
    m.fillcontinents(color='black')
    # plot temp
    cs = m.pcolor(lons,lats,np.squeeze(temp), latlon = True ,vmin=temp_min, vmax=temp_max, cmap='plasma')
    # plot colourbar
    plt.colorbar()
    # datetime title
    plt.title('Regional - Temperature (Celcius)\n' + 
           frame_time.strftime("%Y-%m-%d %H:%M:%S") + ' | ' + str(fname) + '_idx: ' + str(frame_idx))
    # stop axis from being cropped
    plt.tight_layout()

    return fig

这似乎工作正常,但我无法提取我真正想要的数据(NetCDF数据)。理想情况下,我想返回网格单元格(即165 * 116网格的坐标,类似于x = 112,y = 154)。而是点击给我一个如下输出:

def onclick(event):
    """
    On click function for selecting data
    """
    global ix, iy
    ix, iy = event.xdata, event.ydata
    print('x='+str(ix), 'y='+str(iy), 'class='+str(class_value), time_value)

    global train_data
    train_data.append((ix, iy, class, time_value))

# set colour scale variables
temp_min = 14
temp_max = 24 

# list to hold data collected
train_data = []

# __Random Data__

# get list of files in data directory
directory = "/Users/directory/with/my/data"
file_ls = [f for f in listdir(directory) if isfile(join(directory, f))]
file_ls = list(filter(lambda x:'naroom_avg' in x, file_ls))

# set randomness seed
plot_num = 2
np.random.seed(1010)
rnd_file = np.random.randint(len(file_ls), size=plot_num)
rnd_times = np.random.randint(29, size=plot_num)

# __Make plots__

for i in range(0, plot_num):
    # grab file
    file_no = rnd_file[i]
    file_path = directory + "/" + file_ls[file_no]
    fname = str(file_ls[i])[11:16]
    # grab time
    time_idx = rnd_times[i]
    fh = Dataset(file_path, mode='r')
    # extract data
    lats = fh.variables['lat_rho'][:]
    lons = fh.variables['lon_rho'][:]
    time = fh.variables['ocean_time'][:]
    temp = fh.variables['temp'][time_idx,29,:,:]

    # time output
    time_value = grab_sst_time(time_idx)

    # make interactive plot 
    fig = plot_temp(temp, time_idx, i)
    cid = fig.canvas.mpl_connect('button_press_event', onclick)

    # Select class A
    class = 'A'
    print('Select data...')
    input("Press Enter to continue...")
    plt.show()

有关如何获得所需输出的任何想法?

补充数据

以下是我的NetCDF文件的相关变量的结构:

x=432047.683555 y=449210.017634 class=A 2004-06-17 12:00:00
x=448214.625063 y=430733.513053 class=A 2004-06-17 12:00:00
x=448214.625063 y=408792.663863 class=A 2004-06-17 12:00:00
x=448792.015832 y=441703.937648 class=A 2004-06-17 12:00:00

1 个答案:

答案 0 :(得分:2)

要从lon,lat转换为投影坐标,请使用int value; for (int a = 0; a < count; ++a) { InFile >> value; cout << value << '\n'; } 值调用底图实例,

lon,lat

要将投影坐标转换​​回lon,lat坐标,请使用反向

m = Basemap(...)
xpt,ypt = m(lon,lat)

我们可能会修改here中的示例,以在屏幕上显示点击的坐标。

lon,lat = m(xpt,ypt, inverse=True)