oafuncs 0.0.81__py2.py3-none-any.whl → 0.0.82__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oafuncs/oa_data.py +107 -28
- oafuncs/oa_down/hycom_3hourly.py +151 -34
- oafuncs/oa_draw.py +148 -96
- oafuncs/oa_file.py +61 -50
- oafuncs/oa_nc.py +82 -114
- {oafuncs-0.0.81.dist-info → oafuncs-0.0.82.dist-info}/METADATA +1 -1
- oafuncs-0.0.82.dist-info/RECORD +24 -0
- oafuncs/oa_down/test.py +0 -151
- oafuncs/oa_s/__init__.py +0 -23
- oafuncs/oa_s/oa_cmap.py +0 -163
- oafuncs/oa_s/oa_data.py +0 -187
- oafuncs/oa_s/oa_draw.py +0 -451
- oafuncs/oa_s/oa_file.py +0 -332
- oafuncs/oa_s/oa_help.py +0 -39
- oafuncs/oa_s/oa_nc.py +0 -410
- oafuncs/oa_s/oa_python.py +0 -107
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/__init__.py" +0 -26
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_cmap.py" +0 -163
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_data.py" +0 -187
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/__init__.py" +0 -20
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/hycom_3hourly.py" +0 -1176
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/literature.py" +0 -332
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/test_ua.py" +0 -151
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_draw.py" +0 -451
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_file.py" +0 -332
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_help.py" +0 -39
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_nc.py" +0 -410
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_python.py" +0 -107
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/__init__.py" +0 -21
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/meteorological.py" +0 -168
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/ocean.py" +0 -158
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/scientific.py" +0 -139
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/__init__.py" +0 -18
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/email.py" +0 -114
- oafuncs-0.0.81.dist-info/RECORD +0 -51
- {oafuncs-0.0.81.dist-info → oafuncs-0.0.82.dist-info}/LICENSE.txt +0 -0
- {oafuncs-0.0.81.dist-info → oafuncs-0.0.82.dist-info}/WHEEL +0 -0
- {oafuncs-0.0.81.dist-info → oafuncs-0.0.82.dist-info}/top_level.txt +0 -0
oafuncs/oa_draw.py
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
#!/usr/bin/env python
|
2
2
|
# coding=utf-8
|
3
|
-
|
3
|
+
"""
|
4
4
|
Author: Liu Kun && 16031215@qq.com
|
5
5
|
Date: 2024-09-17 17:26:11
|
6
6
|
LastEditors: Liu Kun && 16031215@qq.com
|
7
7
|
LastEditTime: 2024-11-21 13:10:47
|
8
8
|
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_draw.py
|
9
|
-
Description:
|
9
|
+
Description:
|
10
10
|
EditPlatform: vscode
|
11
11
|
ComputerInfo: XPS 15 9510
|
12
12
|
SystemInfo: Windows 11
|
13
13
|
Python Version: 3.11
|
14
|
-
|
15
|
-
|
14
|
+
"""
|
16
15
|
|
17
16
|
import math
|
18
17
|
import warnings
|
@@ -26,22 +25,23 @@ import xarray as xr
|
|
26
25
|
from cartopy.mpl.ticker import LatitudeFormatter, LongitudeFormatter
|
27
26
|
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
28
27
|
|
29
|
-
__all__ = [
|
28
|
+
__all__ = ["fig_minus", "create_gif", "add_cartopy", "add_gridlines", 'MidpointNormalize', "xy2lonlat", "plot_contourf", "plot_contourf_lonlat", "plot_quiver", "plot_contourf_cartopy"]
|
29
|
+
|
30
|
+
warnings.filterwarnings("ignore")
|
30
31
|
|
31
|
-
warnings.filterwarnings('ignore')
|
32
32
|
|
33
33
|
def fig_minus(ax_x=None, ax_y=None, cbar=None, decimal=None, add_space=False):
|
34
|
-
|
34
|
+
"""
|
35
35
|
Description: 将坐标轴刻度中的负号替换为减号
|
36
|
-
|
36
|
+
|
37
37
|
param {*} ax_x : x轴
|
38
38
|
param {*} ax_y : y轴
|
39
39
|
param {*} cbar : colorbar
|
40
40
|
param {*} decimal : 小数位数
|
41
41
|
param {*} add_space : 是否在非负数前面加空格
|
42
|
-
|
42
|
+
|
43
43
|
return {*} ax_x or ax_y or cbar
|
44
|
-
|
44
|
+
"""
|
45
45
|
if ax_x is not None:
|
46
46
|
current_ticks = ax_x.get_xticks()
|
47
47
|
if ax_y is not None:
|
@@ -74,37 +74,38 @@ def fig_minus(ax_x=None, ax_y=None, cbar=None, decimal=None, add_space=False):
|
|
74
74
|
cbar.set_ticklabels(out_ticks)
|
75
75
|
return cbar
|
76
76
|
|
77
|
-
# ** 将生成图片/已有图片制作成动图
|
78
|
-
|
79
77
|
|
78
|
+
# ** 将生成图片/已有图片制作成动图
|
80
79
|
def create_gif(image_list: list, gif_name: str, duration=0.2): # 制作动图,默认间隔0.2
|
81
|
-
|
80
|
+
"""
|
82
81
|
func : 制作动图,将已有图片拼接
|
83
82
|
description : Gif格式动图
|
84
83
|
param {*} image_list 图片列表
|
85
84
|
param {*} gif_name 动图名称(含路径)
|
86
85
|
param {*} duration 动图间隔
|
87
86
|
return {*} 自动保存至指定路径(包含于动图名称中)
|
88
|
-
example :
|
89
|
-
|
87
|
+
example :
|
88
|
+
"""
|
90
89
|
import imageio.v2 as imageio
|
90
|
+
|
91
91
|
frames = []
|
92
92
|
for image_name in image_list:
|
93
93
|
frames.append(imageio.imread(image_name))
|
94
|
-
imageio.mimsave(gif_name, frames, format=
|
95
|
-
print(
|
94
|
+
imageio.mimsave(gif_name, frames, format="GIF", duration=duration)
|
95
|
+
print("Gif制作完成!")
|
96
96
|
return
|
97
97
|
|
98
98
|
|
99
99
|
# ** 转化经/纬度刻度
|
100
|
-
def xy2lonlat(xy, lonlat=
|
101
|
-
|
100
|
+
def xy2lonlat(xy, lonlat="lon", decimal=2):
|
101
|
+
"""
|
102
102
|
param {*} xy : 经/纬度列表
|
103
103
|
param {*} lonlat : 'lon' or 'lat'
|
104
104
|
param {*} decimal : 小数位数
|
105
105
|
return {*} 转化后的经/纬度列表
|
106
106
|
example : xy2lonlat(x, lonlat='lon', decimal=2)
|
107
|
-
|
107
|
+
"""
|
108
|
+
|
108
109
|
def format_longitude(x_list):
|
109
110
|
out_list = []
|
110
111
|
for x in x_list:
|
@@ -127,9 +128,9 @@ def xy2lonlat(xy, lonlat='lon', decimal=2):
|
|
127
128
|
out_list.append(f"{degrees:.{decimal}f}°{direction}" if y != 0 else f"{degrees}°")
|
128
129
|
return out_list if len(out_list) > 1 else out_list[0]
|
129
130
|
|
130
|
-
if lonlat ==
|
131
|
+
if lonlat == "lon":
|
131
132
|
return format_longitude(xy)
|
132
|
-
elif lonlat ==
|
133
|
+
elif lonlat == "lat":
|
133
134
|
return format_latitude(xy)
|
134
135
|
|
135
136
|
|
@@ -142,32 +143,31 @@ class _MyFormatter(mpl.ticker.ScalarFormatter):
|
|
142
143
|
self.vmin = min(cticks)
|
143
144
|
self.vmax = max(cticks)
|
144
145
|
self.p_n = self.vmin < 0 and self.vmax > 0
|
145
|
-
self.magnitude_min = int(
|
146
|
-
math.modf(math.log10(min(abs(cticks[cticks != 0]))))[1])
|
146
|
+
self.magnitude_min = int(math.modf(math.log10(min(abs(cticks[cticks != 0]))))[1])
|
147
147
|
self.magnitude_max = int(math.modf(math.log10(max(abs(cticks))))[1])
|
148
148
|
# print(self.vmin, self.vmax)
|
149
149
|
|
150
150
|
def __call__(self, x, pos):
|
151
151
|
if ((abs(x) < 1e-2) or (abs(x) > 1e4)) and x != 0:
|
152
152
|
if self.magnitude_max - self.magnitude_min == 1 and (int(math.modf(math.log10(abs(x)))[1]) == self.magnitude_min):
|
153
|
-
a, b =
|
153
|
+
a, b = "{:.1e}".format(x).split("e")
|
154
154
|
a = float(a) / 10
|
155
155
|
b = int(b) + 1
|
156
156
|
else:
|
157
|
-
a, b =
|
157
|
+
a, b = "{:.2e}".format(x).split("e")
|
158
158
|
a = float(a)
|
159
159
|
b = int(b)
|
160
160
|
# return '${}{} \\times 10^{{{}}}$'.format(' ' if (self.p_n and x > 0) else '', a, b)
|
161
|
-
return
|
161
|
+
return "${}{:.2f}$".format(" " if (self.p_n and x > 0) else "", a)
|
162
162
|
elif x == 0:
|
163
|
-
return
|
163
|
+
return "0"
|
164
164
|
else:
|
165
165
|
return mpl.ticker.ScalarFormatter.__call__(self, x, pos)
|
166
166
|
|
167
167
|
|
168
168
|
# ** 绘制单张填色图
|
169
|
-
def plot_contourf(pic_data, picname=None, c_map=
|
170
|
-
|
169
|
+
def plot_contourf(pic_data, picname=None, c_map="rainbow", minmax=None, labels=None, ticks_space=None, ticks=None, figsize=(12, 9)):
|
170
|
+
"""
|
171
171
|
func : 绘制填色等值线图,单张
|
172
172
|
description : 绘制单张填色等值线图,输入参数为横纵坐标、等值数据、图例标注等
|
173
173
|
param {*}pic_data : 填色等值线图的等值数据
|
@@ -178,7 +178,7 @@ def plot_contourf(pic_data, picname=None, c_map='rainbow', minmax=None, labels=N
|
|
178
178
|
param {*}ticks_space : x、y轴刻度,以及所显示的标签,默认不显示
|
179
179
|
param {*}figsize : 图片大小,默认(12,9)
|
180
180
|
example : plot_contourf(pic_data, pictpath, var_name, c_map='bwr', labels=None, ticks_space=None, ticks=None, h=0, figsize=(12, 9))
|
181
|
-
|
181
|
+
"""
|
182
182
|
cmap = mpl.colormaps.get_cmap(c_map)
|
183
183
|
if minmax is not None:
|
184
184
|
value_min, value_max = minmax[0], minmax[1]
|
@@ -186,8 +186,7 @@ def plot_contourf(pic_data, picname=None, c_map='rainbow', minmax=None, labels=N
|
|
186
186
|
value_min, value_max = pic_data.nanmin(), pic_data.nanmax()
|
187
187
|
v_bry = max(abs(value_min), abs(value_max))
|
188
188
|
flag = (value_min < 0) and (value_max > 0)
|
189
|
-
norm = mpl.colors.TwoSlopeNorm(
|
190
|
-
vmin=-1 * v_bry, vcenter=0, vmax=v_bry) if flag else mpl.colors.Normalize(vmin=value_min, vmax=value_max)
|
189
|
+
norm = mpl.colors.TwoSlopeNorm(vmin=-1 * v_bry, vcenter=0, vmax=v_bry) if flag else mpl.colors.Normalize(vmin=value_min, vmax=value_max)
|
191
190
|
cticks = [num for num in np.linspace(-1 * v_bry if flag else value_min, v_bry if flag else value_max, 9)] if value_min != value_max else None
|
192
191
|
levels = np.linspace(-1 * v_bry, v_bry, 20) if flag else None if value_min == value_max else np.linspace(value_min, value_max, 20)
|
193
192
|
|
@@ -196,8 +195,8 @@ def plot_contourf(pic_data, picname=None, c_map='rainbow', minmax=None, labels=N
|
|
196
195
|
|
197
196
|
fig, ax = plt.subplots(figsize=figsize)
|
198
197
|
flag_lc = levels is not None and cticks is not None
|
199
|
-
CS = ax.contourf(x, y, pic_data, cmap=cmap, norm=norm, levels=levels, extend=
|
200
|
-
cb = fig.colorbar(CS, ax=ax, orientation=
|
198
|
+
CS = ax.contourf(x, y, pic_data, cmap=cmap, norm=norm, levels=levels, extend="both") if flag_lc else ax.contourf(x, y, pic_data, cmap=cmap, norm=norm, extend="both")
|
199
|
+
cb = fig.colorbar(CS, ax=ax, orientation="vertical", shrink=1, format="%.3g", spacing="uniform", ticks=cticks) if cticks is not None else fig.colorbar(CS, ax=ax, orientation="vertical", shrink=1, format="%.3g", spacing="uniform")
|
201
200
|
"""%.3g采用的是自动调整格式,也可设置为%.3f,则改为3位小数"""
|
202
201
|
|
203
202
|
# 将格式化器设置为自定义的函数
|
@@ -209,20 +208,16 @@ def plot_contourf(pic_data, picname=None, c_map='rainbow', minmax=None, labels=N
|
|
209
208
|
cb.update_ticks()
|
210
209
|
|
211
210
|
if labels is not None:
|
212
|
-
cb.set_label(labels[
|
213
|
-
plt.xlabel(labels[
|
214
|
-
plt.ylabel(labels[
|
211
|
+
cb.set_label(labels["c"])
|
212
|
+
plt.xlabel(labels["x"])
|
213
|
+
plt.ylabel(labels["y"])
|
215
214
|
if ticks_space is not None and ticks is not None:
|
216
|
-
plt.xticks(np.arange(0, len(x[0, :]) +
|
217
|
-
|
218
|
-
plt.yticks(np.arange(0, len(y[:, 0]) +
|
219
|
-
1e-5, ticks_space['y']), ticks['y'])
|
215
|
+
plt.xticks(np.arange(0, len(x[0, :]) + 1e-5, ticks_space["x"]), ticks["x"])
|
216
|
+
plt.yticks(np.arange(0, len(y[:, 0]) + 1e-5, ticks_space["y"]), ticks["y"])
|
220
217
|
|
221
|
-
plt.title(
|
222
|
-
pic_data.min(), pic_data.max()))
|
218
|
+
plt.title("Min: {:.3g}, Max: {:.3g}".format(pic_data.min(), pic_data.max()))
|
223
219
|
|
224
|
-
plt.savefig(
|
225
|
-
picname, bbox_inches='tight') if picname is not None else plt.show()
|
220
|
+
plt.savefig(picname, bbox_inches="tight") if picname is not None else plt.show()
|
226
221
|
# plt.show()
|
227
222
|
plt.clf()
|
228
223
|
# 关闭当前figure
|
@@ -230,8 +225,8 @@ def plot_contourf(pic_data, picname=None, c_map='rainbow', minmax=None, labels=N
|
|
230
225
|
|
231
226
|
|
232
227
|
# ** 画等高线图,带经纬度坐标轴
|
233
|
-
def plot_contourf_lonlat(data, lon, lat, interval=5, picname=None, c_map=
|
234
|
-
|
228
|
+
def plot_contourf_lonlat(data, lon, lat, interval=5, picname=None, c_map="rainbow"):
|
229
|
+
"""
|
235
230
|
param {*} data : 二维数据
|
236
231
|
param {*} lon : 经度
|
237
232
|
param {*} lat : 纬度
|
@@ -239,7 +234,7 @@ def plot_contourf_lonlat(data, lon, lat, interval=5, picname=None, c_map='rainbo
|
|
239
234
|
param {*} picname : 图片保存的文件名(含路径)
|
240
235
|
param {*} c_map : 颜色映射,默认rainbow
|
241
236
|
return {*} 无返回值
|
242
|
-
|
237
|
+
"""
|
243
238
|
if len(lon.shape) == 2:
|
244
239
|
lon = lon[0, :]
|
245
240
|
if len(lat.shape) == 2:
|
@@ -267,14 +262,13 @@ def plot_contourf_lonlat(data, lon, lat, interval=5, picname=None, c_map='rainbo
|
|
267
262
|
plt.xticks(np.arange(0, len(lon), x_space), [format_longitude(lon[i]) for i in range(0, len(lon), x_space)])
|
268
263
|
plt.yticks(np.arange(0, len(lat), y_space), [format_latitude(lat[i]) for i in range(0, len(lat), y_space)])
|
269
264
|
plt.colorbar()
|
270
|
-
plt.savefig(
|
271
|
-
picname, bbox_inches='tight') if picname is not None else plt.show()
|
265
|
+
plt.savefig(picname, bbox_inches="tight") if picname is not None else plt.show()
|
272
266
|
plt.close()
|
273
267
|
|
274
268
|
|
275
269
|
# ** 绘制矢量场
|
276
|
-
def plot_quiver(u, v, lon, lat, picname=None, cmap=
|
277
|
-
|
270
|
+
def plot_quiver(u, v, lon, lat, picname=None, cmap="coolwarm", scale=0.25, width=0.002, x_space=5, y_space=5):
|
271
|
+
"""
|
278
272
|
param {*} u : 二维数据
|
279
273
|
param {*} v : 二维数据
|
280
274
|
param {*} lon : 经度, 1D or 2D
|
@@ -286,7 +280,7 @@ def plot_quiver(u, v, lon, lat, picname=None, cmap='coolwarm', scale=0.25, width
|
|
286
280
|
param {*} x_space : x轴间隔
|
287
281
|
param {*} y_space : y轴间隔
|
288
282
|
return {*} 无返回值
|
289
|
-
|
283
|
+
"""
|
290
284
|
# 创建新的网格位置变量(lat_c, lon_c)
|
291
285
|
if len(lon.shape) == 1 and len(lat.shape) == 1:
|
292
286
|
lon_c, lat_c = np.meshgrid(lon, lat)
|
@@ -307,29 +301,31 @@ def plot_quiver(u, v, lon, lat, picname=None, cmap='coolwarm', scale=0.25, width
|
|
307
301
|
|
308
302
|
# 使用 plt.quiver 函数绘制矢量图
|
309
303
|
# 通过设置 quiver 函数的 pivot 参数来指定箭头的位置
|
310
|
-
quiver_plot = plt.quiver(
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
304
|
+
quiver_plot = plt.quiver(
|
305
|
+
lon_c[::y_space, ::x_space],
|
306
|
+
lat_c[::y_space, ::x_space],
|
307
|
+
u[::y_space, ::x_space],
|
308
|
+
v[::y_space, ::x_space],
|
309
|
+
S[::y_space, ::x_space], # 矢量的大小,可以不要
|
310
|
+
pivot="middle",
|
311
|
+
scale=scale,
|
312
|
+
# color=color, # 矢量的颜色,单色
|
313
|
+
cmap=cmap, # 矢量的颜色,多色
|
314
|
+
width=width,
|
315
|
+
)
|
320
316
|
# plt.quiverkey(quiver_plot, X=0.90, Y=0.975, U=1, label='1 m/s', labelpos='E', fontproperties={'size': 10})
|
321
|
-
plt.quiverkey(quiver_plot, X=0.87, Y=0.975, U=mean_S, label=f
|
317
|
+
plt.quiverkey(quiver_plot, X=0.87, Y=0.975, U=mean_S, label=f"{mean_S:.2f} m/s", labelpos="E", fontproperties={"size": 10})
|
322
318
|
plt.colorbar(quiver_plot)
|
323
|
-
plt.xlabel(
|
324
|
-
plt.ylabel(
|
319
|
+
plt.xlabel("X")
|
320
|
+
plt.ylabel("Y")
|
325
321
|
|
326
|
-
plt.savefig(picname, bbox_inches=
|
322
|
+
plt.savefig(picname, bbox_inches="tight") if picname is not None else plt.show()
|
327
323
|
plt.clf()
|
328
324
|
plt.close()
|
329
325
|
|
330
326
|
|
331
|
-
def plot_contourf_cartopy(data, lon, lat, picname=None, cmap=
|
332
|
-
|
327
|
+
def plot_contourf_cartopy(data, lon, lat, picname=None, cmap="rainbow", cn_fill_num=20, fig_size=(12, 9), title="Cartopy", land_color="green", ocean_color="lightgrey"):
|
328
|
+
"""
|
333
329
|
param {*} data : 二维数据
|
334
330
|
param {*} lon : 经度
|
335
331
|
param {*} lat : 纬度
|
@@ -341,7 +337,7 @@ def plot_contourf_cartopy(data, lon, lat, picname=None, cmap='rainbow', cn_fill_
|
|
341
337
|
param {*} land_color : 陆地颜色
|
342
338
|
param {*} ocean_color : 海洋颜色
|
343
339
|
return {*} 无返回值
|
344
|
-
|
340
|
+
"""
|
345
341
|
if len(lon.shape) == 2:
|
346
342
|
lon = lon[0, :]
|
347
343
|
if len(lat.shape) == 2:
|
@@ -381,37 +377,33 @@ def plot_contourf_cartopy(data, lon, lat, picname=None, cmap='rainbow', cn_fill_
|
|
381
377
|
cticks = cbar_ticks
|
382
378
|
norm = mpl.colors.BoundaryNorm(cticks, cmap.N)
|
383
379
|
|
384
|
-
cnplot = ax.contourf(X, Y, data, levels=levels, cmap=cmap, norm=norm, transform=proj, extend=
|
380
|
+
cnplot = ax.contourf(X, Y, data, levels=levels, cmap=cmap, norm=norm, transform=proj, extend="both", alpha=1, zorder=0)
|
385
381
|
# cllevels = np.linspace(data_min, data_max, 9)
|
386
382
|
# clplot = ax.contour(X, Y, data, levels=levels[9::10], colors='k', linewidths=0.5, transform=proj, zorder=1, alpha=0.8, linestyle='--')
|
387
383
|
# 添加色标,并选择位置
|
388
384
|
divider = make_axes_locatable(ax)
|
389
385
|
location = 3
|
390
386
|
if location == 1: # 左侧
|
391
|
-
cax = divider.new_horizontal(
|
392
|
-
size="5%", pad=1, axes_class=plt.Axes, pack_start=True)
|
387
|
+
cax = divider.new_horizontal(size="5%", pad=1, axes_class=plt.Axes, pack_start=True)
|
393
388
|
fig.add_axes(cax)
|
394
|
-
cbar = plt.colorbar(
|
395
|
-
cnplot, cax=cax, orientation='vertical', extend='both')
|
389
|
+
cbar = plt.colorbar(cnplot, cax=cax, orientation="vertical", extend="both")
|
396
390
|
elif location == 2: # 下方
|
397
|
-
cax = divider.new_vertical(
|
398
|
-
size="5%", pad=0.3, axes_class=plt.Axes, pack_start=True)
|
391
|
+
cax = divider.new_vertical(size="5%", pad=0.3, axes_class=plt.Axes, pack_start=True)
|
399
392
|
fig.add_axes(cax)
|
400
|
-
cbar = plt.colorbar(
|
401
|
-
cnplot, cax=cax, orientation='horizontal', extend='both')
|
393
|
+
cbar = plt.colorbar(cnplot, cax=cax, orientation="horizontal", extend="both")
|
402
394
|
elif location == 3: # 右侧
|
403
395
|
cax = divider.new_horizontal(size="5%", pad=0.1, axes_class=plt.Axes)
|
404
396
|
fig.add_axes(cax)
|
405
397
|
# cbar = plt.colorbar(cnplot, cax=cax, orientation='vertical', extend='both', format='%.0f')
|
406
|
-
cbar = fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm), cax=cax, orientation=
|
407
|
-
cax.yaxis.set_ticks_position(
|
408
|
-
cax.yaxis.set_label_position(
|
398
|
+
cbar = fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm), cax=cax, orientation="vertical", extend="both", format="%.3f")
|
399
|
+
cax.yaxis.set_ticks_position("right")
|
400
|
+
cax.yaxis.set_label_position("right")
|
409
401
|
else: # 上方
|
410
402
|
cax = divider.new_vertical(size="5%", pad=0.2, axes_class=plt.Axes)
|
411
403
|
fig.add_axes(cax)
|
412
|
-
cbar = plt.colorbar(cnplot, cax=cax, orientation=
|
404
|
+
cbar = plt.colorbar(cnplot, cax=cax, orientation="horizontal", extend="both")
|
413
405
|
cbar.ax.tick_params(labelsize=10)
|
414
|
-
cbar.ax.xaxis.set_tick_params(direction=
|
406
|
+
cbar.ax.xaxis.set_tick_params(direction="in", width=1, length=2)
|
415
407
|
# 添加cbar_ticks
|
416
408
|
# cbar.set_ticks(np.arange(round(levels[0]), round(levels[-1]), round((levels[-1]-levels[0])/9))) # 设置色标刻度
|
417
409
|
# cbar.set_ticks(cbar_ticks) # 设置色标刻度
|
@@ -421,31 +413,91 @@ def plot_contourf_cartopy(data, lon, lat, picname=None, cmap='rainbow', cn_fill_
|
|
421
413
|
# cbar.set_ticks(np.arange(round(levels[0]), round(levels[-1]), round((levels[-1]-levels[0])/9))) # 设置色标刻度
|
422
414
|
|
423
415
|
# 单独设置label
|
424
|
-
cbar.set_label(title, fontsize=10, weight=
|
416
|
+
cbar.set_label(title, fontsize=10, weight="bold")
|
425
417
|
# cax.set_position([0.1, 0.2, 0.02, 0.6]) # 调整色标位置
|
426
|
-
fig.savefig(picname, bbox_inches=
|
418
|
+
fig.savefig(picname, bbox_inches="tight", dpi=600) if picname is not None else plt.show()
|
427
419
|
plt.close()
|
428
420
|
|
429
421
|
|
430
|
-
|
422
|
+
def add_gridlines(ax, projection=ccrs.PlateCarree(), color="k", alpha=0.5, linestyle="--", linewidth=0.5):
|
423
|
+
# add gridlines
|
424
|
+
gl = ax.gridlines(crs=projection, draw_labels=True, linewidth=linewidth, color=color, alpha=alpha, linestyle=linestyle)
|
425
|
+
gl.right_labels = False
|
426
|
+
gl.top_labels = False
|
427
|
+
gl.xformatter = LongitudeFormatter(zero_direction_label=False)
|
428
|
+
gl.yformatter = LatitudeFormatter()
|
429
|
+
|
430
|
+
return ax, gl
|
431
|
+
|
432
|
+
|
433
|
+
def add_cartopy(ax,lon=None,lat=None,projection=ccrs.PlateCarree(), gridlines=True,landcolor="lightgrey",oceancolor="lightblue", cartopy_linewidth=0.5):
|
434
|
+
# Set the projection for the axes
|
435
|
+
ax.set_projection(projection)
|
436
|
+
|
437
|
+
# add coastlines
|
438
|
+
ax.add_feature(cfeature.LAND, facecolor=landcolor)
|
439
|
+
ax.add_feature(cfeature.OCEAN, facecolor=oceancolor)
|
440
|
+
ax.add_feature(cfeature.COASTLINE, linewidth=cartopy_linewidth)
|
441
|
+
ax.add_feature(cfeature.BORDERS, linewidth=cartopy_linewidth, linestyle=":")
|
442
|
+
|
443
|
+
# add gridlines
|
444
|
+
if gridlines:
|
445
|
+
ax, gl = add_gridlines(ax, projection)
|
446
|
+
|
447
|
+
# set longitude and latitude format
|
448
|
+
lon_formatter = LongitudeFormatter(zero_direction_label=False)
|
449
|
+
lat_formatter = LatitudeFormatter()
|
450
|
+
ax.xaxis.set_major_formatter(lon_formatter)
|
451
|
+
ax.yaxis.set_major_formatter(lat_formatter)
|
452
|
+
|
453
|
+
# set extent
|
454
|
+
if lon is not None and lat is not None:
|
455
|
+
lon_min, lon_max = lon.min(), lon.max()
|
456
|
+
lat_min, lat_max = lat.min(), lat.max()
|
457
|
+
ax.set_extent([lon_min, lon_max, lat_min, lat_max], crs=projection)
|
458
|
+
|
459
|
+
|
460
|
+
class MidpointNormalize(mpl.colors.Normalize):
|
461
|
+
'''
|
462
|
+
Description: 自定义归一化类,使得0值处为中心点
|
463
|
+
|
464
|
+
param {*} mpl.colors.Normalize : 继承Normalize类
|
465
|
+
return {*}
|
466
|
+
|
467
|
+
Example:
|
468
|
+
nrom = MidpointNormalize(vmin=-2, vmax=1, vcenter=0)
|
469
|
+
'''
|
470
|
+
def __init__(self, vmin=None, vmax=None, vcenter=None, clip=False):
|
471
|
+
self.vcenter = vcenter
|
472
|
+
super().__init__(vmin, vmax, clip)
|
473
|
+
|
474
|
+
def __call__(self, value, clip=None):
|
475
|
+
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1.]
|
476
|
+
return np.ma.masked_array(np.interp(value, x, y, left=-np.inf, right=np.inf))
|
477
|
+
|
478
|
+
def inverse(self, value):
|
479
|
+
y, x = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
|
480
|
+
return np.interp(value, x, y, left=-np.inf, right=np.inf)
|
481
|
+
|
482
|
+
if __name__ == "__main__":
|
431
483
|
# ** 绘制填色图
|
432
484
|
data = np.random.randn(100, 100)
|
433
|
-
picname =
|
434
|
-
plot_contourf(data, picname, c_map=
|
485
|
+
picname = "test.png"
|
486
|
+
plot_contourf(data, picname, c_map="rainbow", minmax=None, labels=None, ticks_space=None, ticks=None, figsize=(12, 9))
|
435
487
|
# ** 绘制矢量场
|
436
488
|
u = np.random.randn(100, 100)
|
437
489
|
v = np.random.randn(100, 100)
|
438
490
|
lon = np.linspace(0, 360, 100)
|
439
491
|
lat = np.linspace(-90, 90, 100)
|
440
|
-
picname =
|
441
|
-
plot_quiver(u, v, lon, lat, picname, cmap=
|
492
|
+
picname = "test.png"
|
493
|
+
plot_quiver(u, v, lon, lat, picname, cmap="coolwarm", scale=0.25, width=0.002, x_space=5, y_space=5)
|
442
494
|
# ** 绘制经纬度填色图
|
443
495
|
data = np.random.randn(100, 100)
|
444
496
|
lon = np.linspace(0, 360, 100)
|
445
497
|
lat = np.linspace(-90, 90, 100)
|
446
|
-
picname =
|
447
|
-
plot_contourf_lonlat(data, lon, lat, interval=5, picname=picname, c_map=
|
498
|
+
picname = "test.png"
|
499
|
+
plot_contourf_lonlat(data, lon, lat, interval=5, picname=picname, c_map="rainbow")
|
448
500
|
# ** 制作动图
|
449
|
-
image_list = [
|
450
|
-
gif_name =
|
501
|
+
image_list = ["test1.png", "test2.png", "test3.png"]
|
502
|
+
gif_name = "test.gif"
|
451
503
|
create_gif(image_list, gif_name, duration=0.2)
|