2019年年初，新东方年会的一个视频火爆全网，里面说出了无数职场人士的心声：

1.1 用到的数据

http://glider.ceotr.ca/data/live/otn200_sci_water_temp_live.csv

https://coastwatch.pfeg.noaa.gov/erddap/griddap/usgsCeSrtm30v1.nc?topo[(45):1:(42)][(-67):1:(-61.5)]

1.2 用到的Python库

from matplotlib.transforms import Bbox, TransformedBbox,  blended_transform_factoryfrom mpl_toolkits.axes_grid1.inset_locator import BboxPatch, BboxConnector, BboxConnectorPatchimport matplotlib.pyplot as pltfrom math import radians, cos, sin, asin, sqrtimport pandas as pdimport numpy as npimport netCDF4 as ncimport imageio

2.1 数据读取

nc文件使用netCDF4库来读取文件中的变量信息，csv文件中的信息使用pandas来读取。

topo为所在区域的水深情况，lon, lat, date, depth, temp分别为Glider观测到的站点经度、纬度、观测时间、深度和温度。

file2read = r'otn200_sci_water_temp_live.csv'ncfile = r'usgsCeSrtm30v1_6ebb_eec1_d277.nc'data = pd.read_csv(file2read)date = data.iloc[:, 0]lat = data.iloc[:, 1]lon = data.iloc[:, 2]depth = data.iloc[:, 3]temp = data.iloc[:, 4]etopo2 = nc.Dataset(ncfile)latDepth = etopo2.variables['latitude'][:]lonDepth = etopo2.variables['longitude'][:]topo = etopo2.variables['topo'][:]

2.2计算各观测点之间的距离

# Compute distance along transectdist = np.zeros((np.size(lon)))for i in range(1, np.size(lon)):    dist[i] = dist[i - 1] + haversine(lon[i - 1], lat[i - 1], lon[i], lat[i])
# Compute distance along transectdist = np.zeros((np.size(lon)))for i in range(1, np.size(lon)):    dist[i] = dist[i - 1] + haversine(lon[i - 1], lat[i - 1], lon[i], lat[i])

2.3得到断面上各个点的水深情况

bathy = np.zeros((np.size(lon)))for i in range(np.size(lon)):    cost_func = np.abs(lonDepth - lon[i])    xmin = np.where(cost_func == np.min(cost_func))[0]    cost_func = np.abs(latDepth - lat[i])    ymin = np.where(cost_func == np.min(cost_func))[0]    bathy[i] = -topo[ymin, xmin]

2.4 局部放大图像

def zoom_effect(ax1, ax2, xmin, xmax, **kwargs):    """    ax1 : the main axes    ax1 : the zoomed axes    (xmin,xmax) : the limits of the colored area in both plot axes.    connect ax1 & ax2. The x-range of (xmin, xmax) in both axes will    be marked.  The keywords parameters will be used ti create    patches.    Source: http://matplotlib.org/dev/users/annotations_guide.html#zoom-effect-between-axes    """    trans1 = blended_transform_factory(ax1.transData, ax1.transAxes)    trans2 = blended_transform_factory(ax2.transData, ax2.transAxes)    bbox = Bbox.from_extents(xmin, 0, xmax, 1)    mybbox1 = TransformedBbox(bbox, trans1)    mybbox2 = TransformedBbox(bbox, trans2)    prop_patches = kwargs.copy()    prop_patches["ec"] = "r"    prop_patches["alpha"] = None    prop_patches["facecolor"] = 'none'    prop_patches["linewidth"] = 2    c1, c2, bbox_patch1, bbox_patch2, p = \        connect_bbox(mybbox1, mybbox2,                     loc1a=3, loc2a=2, loc1b=4, loc2b=1,                     prop_lines=kwargs, prop_patches=prop_patches)    ax1.add_patch(bbox_patch1)    ax2.add_patch(bbox_patch2)    ax2.add_patch(c1)    ax2.add_patch(c2)    ax2.add_patch(p)    return c1, c2, bbox_patch1, bbox_patch2, p
def connect_bbox(bbox1, bbox2,                 loc1a, loc2a, loc1b, loc2b,                 prop_lines, prop_patches=None):    # Fuctions for zoom effect ****************************************************    # Source: http://matplotlib.org/dev/users/annotations_guide.html#zoom-effect-between-axes    if prop_patches is None:        prop_patches = prop_lines.copy()        prop_patches["alpha"] = prop_patches.get("alpha", 1) * 0.2    c1 = BboxConnector(bbox1, bbox2, loc1=loc1a, loc2=loc2a, **prop_lines)    c1.set_clip_on(False)    c2 = BboxConnector(bbox1, bbox2, loc1=loc1b, loc2=loc2b, **prop_lines)    c2.set_clip_on(False)    bbox_patch1 = BboxPatch(bbox1, **prop_patches)    bbox_patch2 = BboxPatch(bbox2, **prop_patches)    p = BboxConnectorPatch(bbox1, bbox2,                           # loc1a=3, loc2a=2, loc1b=4, loc2b=1,                           loc1a=loc1a, loc2a=loc2a, loc1b=loc1b, loc2b=loc2b,                           **prop_patches)    p.set_clip_on(False)    return c1, c2, bbox_patch1, bbox_patch2, p

2.5 生成多张图片

# Make plotsnframes = 20overlap = 0.95window = np.floor(max(dist) - min(dist)) / (nframes - (nframes * overlap) + overlap)xmin = 0xmax = xmin + windowcmp = plt.cm.get_cmap('jet', 16)fig1 = plt.figure()for i in range(0, nframes):    ax1 = plt.subplot(211)    plt.fill_between(dist, bathy, 1000, color='k')    plt.scatter(dist, np.asarray(depth), s=15, c=temp,                cmap = cmp, marker='o', edgecolor='none')    plt.ylim((-0.5, max(depth) + 5))    ax1.set_ylim(ax1.get_ylim()[::-1])    cbar = plt.colorbar(orientation='vertical', extend='both')    cbar.ax.set_ylabel('Temperature ($^\circ$C)')    plt.title('OTN Glider transect')    plt.ylabel('Depth (m)')    ax1.set_xlim(min(dist), max(dist))    ax2 = plt.subplot(212)    plt.fill_between(dist, bathy, 1000, color='k')    plt.scatter(dist, depth, s=15, c=temp,                cmap= cmp, marker='o', edgecolor='none')    plt.ylim((-0.5, max(depth) + 5))    ax2.set_ylim(ax2.get_ylim()[::-1])    plt.ylabel('Depth (m)')    plt.xlabel('Distance along transect (km)')    ax2.set_xlim(xmin, xmax)    zoom_effect(ax1, ax2, xmin, xmax)    file2write = 'glider_' + '%02d'%i + '.png'    plt.savefig(file2write, bbox_inches='tight')    plt.close()    xmin = xmax - np.floor(window * overlap)    xmax = xmin + window

2.6 生成gif文件

imagelist = ['glider_'+'%02d'%i +'.png' for i in range(0,20)]frames = [imageio.imread(_) for _ in imagelist]outname = 'gliders.gif'imageio.mimsave(outname, frames, 'GIF', duration=0.3)