Cartopy繪圖系列 | 繪制全球溫度場(chǎng)+風(fēng)矢量場(chǎng)

世上總會(huì)有“猝不及防的再見(jiàn)和毫無(wú)留戀的散場(chǎng)”肃弟, 但也會(huì)有 “突如其來(lái)的遇見(jiàn)和始料未及的歡喜”氨鹏, 無(wú)論何時(shí)争拐,記得不要失了好心情粮坞!

空間數(shù)據(jù)的可視化展示是空間數(shù)據(jù)可視化制圖的常見(jiàn)需求。目前常見(jiàn)的地圖繪圖工具和軟件有:
  • (1) 支持 多種操作系統(tǒng)的命令行工具 GMT(Generic Mapping Tools)
  • (2) ArcGIS赤拒、GrDAS等秫筏。
  • (3) NCAR Command Language): 常用于氣象數(shù)據(jù)讀取和可視化分析的高級(jí)語(yǔ)言(目前也已經(jīng)遷移到PyNGL上)
  • (4)Python 繪圖工具 matplotlib 的擴(kuò)展包 Basemap(作者在前面的文章中有簡(jiǎn)單介紹

除此之外,小編想給大家推薦 Python 的一種制圖工具包 Cartopy,(內(nèi)容比Basemap更加豐富和實(shí)用)

cartopy.png

Cartopy簡(jiǎn)介與安裝

Cartopy 是一個(gè)開(kāi)源免費(fèi)的第三方 Python 擴(kuò)展包挎挖,由英國(guó)氣象辦公室的科學(xué)家們開(kāi)發(fā)这敬,支持 Python 2.7 和 Python 3,致力于使用最簡(jiǎn)單直觀的方式生成地圖蕉朵,并提供對(duì) matplotlib 的接口崔涂,兩者可以完美的協(xié)作。
1始衅、Cartopy常用于用于地理空間數(shù)據(jù)處理堪伍,以便生成地圖和其他地理空間數(shù)據(jù)分析。Cartopy利用了強(qiáng)大的PROJ.4觅闽、NumPy和Shapely庫(kù),并在Matplotlib之上提供了一個(gè)編程接口涮俄,用于創(chuàng)建出版高質(zhì)量的地圖蛉拙。
2、Cartopy的關(guān)鍵特性是它面向?qū)ο蟮耐队岸x彻亲,以及在這些投影之間轉(zhuǎn)換點(diǎn)孕锄、線吮廉、向量、多邊形和圖像的能力畸肆。

為什么要選用Cartopy ?

  • Cartopy 的工作流非常簡(jiǎn)單:設(shè)置地圖投影宦芦,添加地圖要素,最后顯示地圖轴脐。
  • Basemap繪圖包配置相對(duì)較繁瑣调卑,自定義性不強(qiáng)而且Basemap 將在 2020 年版本的更新。因此大咱,如果你在尋找一個(gè)新的Python制圖工具包恬涧,Cartopy是Basemap官網(wǎng)欽定的繼承人,無(wú)疑是最佳選擇(https://matplotlib.org/basemap/users/intro.html#cartopy-new-management-and-eol-announcement)碴巾。

Cartopy安裝:

官網(wǎng)教程:https://scitools.org.uk/cartopy/docs/latest/installing.html#installing
1)Anaconda環(huán)境
如果你正在使用 Python 的科學(xué)計(jì)算發(fā)行版 Anaconda溯捆,安裝 Cartopy 非常容易。
命令行輸入: conda install -c conda-forge cartopy
2)Windows環(huán)境
命令行輸入:pip install cartopy
3)可以切換國(guó)內(nèi)像源厦瓢,安裝速度更快
命令行輸入:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple cartopy

測(cè)試是否安裝成功:
啟動(dòng)python命令行工具提揍,輸入 import cartopy 如果沒(méi)有報(bào)錯(cuò),則安裝成功煮仇!

Cartopy 制圖簡(jiǎn)介

  • Cartopy官方網(wǎng)站中列舉了許多繪圖案例劳跃,并且有完整的代碼演示。鏈接https://scitools.org.uk/cartopy/docs/latest/gallery/index.html

    image.png

  • Cartopy地圖繪制的總體流程就是:(1) 選擇合適的投影欺抗; (2) 添加地圖要素(自定義shp\海岸線\邊界線等)售碳;(3) 疊加空間數(shù)據(jù);(4) 設(shè)置地圖要素(經(jīng)緯度標(biāo)簽绞呈、比例尺贸人、文本等)

下面介紹幾種作者自己總結(jié)的常見(jiàn)繪圖案例

1、全球地圖顯示

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name : cartopy_script.py
# Author : zengsk in NanJing
# Created: 2020/6/15 0:54

"""
Details: Cartopy package 繪圖示例
"""

import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
import matplotlib.pyplot as plt

def main():
    fig = plt.figure(figsize=(8, 8))

    # Label axes of a Plate Carree projection with a central longitude of 180:
    ax1 = fig.add_subplot(2, 1, 1,
                          projection=ccrs.PlateCarree(central_longitude=180))
    ax1.set_global()
    ax1.coastlines() # 添加海岸線

    ax1.set_xticks([0, 60, 120, 180, 240, 300, 360], crs=ccrs.PlateCarree())
    ax1.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=ccrs.PlateCarree())
    lon_formatter = LongitudeFormatter(zero_direction_label=True)
    lat_formatter = LatitudeFormatter()
    ax1.xaxis.set_major_formatter(lon_formatter)
    ax1.yaxis.set_major_formatter(lat_formatter)

    ax2 = fig.add_subplot(2, 1, 2,
                          projection=ccrs.Robinson(central_longitude=0))

    # make the map global rather than have it zoom in to
    # the extents of any plotted data
    ax2.set_global()
    ax2.stock_img()
    ax2.coastlines()
    ax2.add_feature(cfeature.BORDERS, linestyle='-') # 添加國(guó)家邊界
    ax2.plot(-0.08, 51.53, 'o', transform=ccrs.PlateCarree())

    plt.savefig(r'C:\Users\zengsk\Desktop\test.jpg', dpi=300)
    plt.show()

if __name__ == '__main__':
    main()

結(jié)果展示

test.jpg

2佃声、顯示自定義 shapefile文件**

往往我們需要繪制自定義范圍的研究區(qū)域艺智,需要繪制指定shapefile文件的邊界!

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name : cartopy_test2.py

"""
Created by s.k zeng in Chengdu on 2020/07/07
"""

import numpy as np
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import cartopy.io.shapereader as shpreader
import cartopy.mpl.ticker as mticker
import matplotlib.pyplot as plt


def main():

    # 設(shè)置投影
    proj = ccrs.PlateCarree() # 圓柱投影圾亏, 默認(rèn)WGS1984
    extent = [70, 140, 0, 60] # 顯示范圍
    shpfn = r'E:\GisData\SHP\China_shp\bou2_4m\bou2_4l.shp'
    tpshp = r'E:\GisData\SHP\Tibetan\TP_boundary\TP_Clip.shp'
    glshp = r'E:\GisData\SHP\Global\country.shp'
    reader = shpreader.Reader(shpfn)
    states_provinces = cfeature.ShapelyFeature(reader.geometries(), proj, facecolor='none')
    reader = shpreader.Reader(tpshp)
    tpfeat = cfeature.ShapelyFeature(reader.geometries(), proj, facecolor='none')
    reader = shpreader.Reader(glshp)
    glfeat = cfeature.ShapelyFeature(reader.geometries(), proj, facecolor='none')

    fig = plt.figure(figsize=(8, 8), frameon=True)
    ax1 = fig.add_subplot(1, 1, 1, projection=proj)
    # Label axes of a Mercator projection without degree symbols in the labels
    # and formatting labels to include 1 decimal place:
    ax1.set_extent(extent, proj)
    ax1.add_feature(glfeat, linewidth=1.5, edgecolor='grey')
    ax1.add_feature(states_provinces, linewidth=1.5, edgecolor='blue')
    ax1.add_feature(tpfeat, linewidth=2.0, edgecolor='red')

    # 設(shè)置經(jīng)緯網(wǎng)以及標(biāo)簽
    ax1.gridlines(proj, draw_labels=False, linewidth=1.2, color='k', alpha=0.5, linestyle='--')
    ax1.set_xticks(np.arange(extent[0], extent[1] + 10, 10), crs=proj)
    ax1.set_yticks(np.arange(extent[2], extent[3] + 10, 10), crs=proj)
    ax1.xaxis.set_major_formatter(mticker.LongitudeFormatter())
    ax1.yaxis.set_major_formatter(mticker.LatitudeFormatter())

    plt.savefig(r'C:\Users\zengsk\Desktop\test.jpg', dpi=300)
    plt.show()

if __name__ == '__main__':
    main()

結(jié)果展示

test.jpg

3十拣、綜合案例:Cartopy繪制全球溫度場(chǎng)+風(fēng)矢量場(chǎng)數(shù)據(jù)**

NCEP/NCAR Reanalysis 1 再分析資料的地面10m風(fēng)場(chǎng)數(shù)據(jù)(u v)和地面溫度數(shù)據(jù)繪圖示例。(以2020年01月01日為例)
數(shù)據(jù)可在官網(wǎng)下載:https://psl.noaa.gov/data/gridded/data.ncep.reanalysis.html

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Name : uvwind_plot.py

"""
Details: NCEP/NCAR Reanalysis 1: Surface 10m風(fēng)速數(shù)據(jù)繪制風(fēng)矢量場(chǎng)圖
Created by s.k zeng in Chengdu on 2020/07/07
"""

import netCDF4 as nc
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.mpl.ticker as mticker


def read_uv():
    '''
    :return: lon, lat, uwind, vwind
    '''
    uwind = r"E:\Scripts\Test\uvdata\uwnd.10m.gauss.2020.nc"
    vwind = r"E:\Scripts\Test\uvdata\vwnd.10m.gauss.2020.nc"
    ufid = nc.Dataset(uwind)
    vfid = nc.Dataset(vwind)
    print(ufid.variables)
    lon = ufid.variables['lon'][:]
    lat = ufid.variables['lat'][:]
    u = ufid.variables['uwnd'][0, :, :] # unit: m/s
    v = vfid.variables['vwnd'][0, :, :]
    return lon, lat, u, v


def read_airtemper():
    temperFn = r"E:\Scripts\Test\uvdata\air.sig995.2020.nc"
    tfid = nc.Dataset(temperFn)
    print(tfid.variables)
    lon = tfid.variables['lon'][:]
    lat = tfid.variables['lat'][:]
    air = tfid.variables['air'][0, :, :] # air temperature unit: degK
    return lon, lat, air


def main():
    lon, lat, u, v = read_uv()
    lon2, lat2, air = read_airtemper()
    proj = ccrs.PlateCarree(central_longitude=180)

    fig = plt.figure(figsize=(9, 6), dpi=300)
    ax = fig.add_subplot(1, 1, 1, projection=proj)
    cs = ax.contourf(lon2, lat2, air, transform=proj, cmap='RdBu_r') # RdBu_r nipy_spectral
    ax.quiver(lon, lat, u, v, transform=ccrs.PlateCarree(), regrid_shape=35, width=0.002)
    ax.coastlines(color='dimgray')
    ax.set_global()

    cbar = fig.colorbar(cs, orientation='vertical', pad=0.02, aspect=20, shrink=0.6)
    cbar.set_label('degK')

    xticks = [-180, -120, -60, 0, 60, 120, 180]
    ax.set_xticks(xticks, crs=proj)
    ax.set_yticks([-90, -60, -30, 0, 30, 60, 90], crs=proj)
    lon_formatter = mticker.LongitudeFormatter(zero_direction_label=True)
    lat_formatter = mticker.LatitudeFormatter()
    ax.xaxis.set_major_formatter(lon_formatter)
    ax.yaxis.set_major_formatter(lat_formatter)

    plt.savefig(r'C:\Users\zengsk\Desktop\test.jpg', dpi=300)
    plt.show()


if __name__ == '__main__':
    main()

結(jié)果展示

test.jpg

感謝支持志鹃,本人能力有限夭问,如文章存在錯(cuò)誤和高見(jiàn)歡迎留言!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末曹铃,一起剝皮案震驚了整個(gè)濱河市缰趋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖秘血,帶你破解...
    沈念sama閱讀 210,978評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件味抖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡灰粮,警方通過(guò)查閱死者的電腦和手機(jī)仔涩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)粘舟,“玉大人熔脂,你說(shuō)我怎么就攤上這事”统耍” “怎么了锤悄?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,623評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)嘉抒。 經(jīng)常有香客問(wèn)我零聚,道長(zhǎng),這世上最難降的妖魔是什么些侍? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,324評(píng)論 1 282
  • 正文 為了忘掉前任隶症,我火速辦了婚禮,結(jié)果婚禮上岗宣,老公的妹妹穿的比我還像新娘蚂会。我一直安慰自己,他們只是感情好耗式,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布胁住。 她就那樣靜靜地躺著,像睡著了一般刊咳。 火紅的嫁衣襯著肌膚如雪彪见。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,741評(píng)論 1 289
  • 那天娱挨,我揣著相機(jī)與錄音余指,去河邊找鬼。 笑死跷坝,一個(gè)胖子當(dāng)著我的面吹牛酵镜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柴钻,決...
    沈念sama閱讀 38,892評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼淮韭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了贴届?” 一聲冷哼從身側(cè)響起靠粪,我...
    開(kāi)封第一講書(shū)人閱讀 37,655評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤足丢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后庇配,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡绍些,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年捞慌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柬批。...
    茶點(diǎn)故事閱讀 38,569評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡啸澡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出氮帐,到底是詐尸還是另有隱情嗅虏,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評(píng)論 4 328
  • 正文 年R本政府宣布上沐,位于F島的核電站皮服,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏参咙。R本人自食惡果不足惜龄广,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蕴侧。 院中可真熱鬧择同,春花似錦、人聲如沸净宵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,725評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)择葡。三九已至紧武,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刁岸,已是汗流浹背脏里。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,950評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虹曙,地道東北人迫横。 一個(gè)月前我還...
    沈念sama閱讀 46,260評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像酝碳,于是被迫代替她去往敵國(guó)和親矾踱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容