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.
Files changed (38) hide show
  1. oafuncs/oa_data.py +107 -28
  2. oafuncs/oa_down/hycom_3hourly.py +151 -34
  3. oafuncs/oa_draw.py +148 -96
  4. oafuncs/oa_file.py +61 -50
  5. oafuncs/oa_nc.py +82 -114
  6. {oafuncs-0.0.81.dist-info → oafuncs-0.0.82.dist-info}/METADATA +1 -1
  7. oafuncs-0.0.82.dist-info/RECORD +24 -0
  8. oafuncs/oa_down/test.py +0 -151
  9. oafuncs/oa_s/__init__.py +0 -23
  10. oafuncs/oa_s/oa_cmap.py +0 -163
  11. oafuncs/oa_s/oa_data.py +0 -187
  12. oafuncs/oa_s/oa_draw.py +0 -451
  13. oafuncs/oa_s/oa_file.py +0 -332
  14. oafuncs/oa_s/oa_help.py +0 -39
  15. oafuncs/oa_s/oa_nc.py +0 -410
  16. oafuncs/oa_s/oa_python.py +0 -107
  17. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/__init__.py" +0 -26
  18. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_cmap.py" +0 -163
  19. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_data.py" +0 -187
  20. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/__init__.py" +0 -20
  21. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/hycom_3hourly.py" +0 -1176
  22. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/literature.py" +0 -332
  23. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/test_ua.py" +0 -151
  24. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_draw.py" +0 -451
  25. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_file.py" +0 -332
  26. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_help.py" +0 -39
  27. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_nc.py" +0 -410
  28. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_python.py" +0 -107
  29. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/__init__.py" +0 -21
  30. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/meteorological.py" +0 -168
  31. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/ocean.py" +0 -158
  32. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/scientific.py" +0 -139
  33. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/__init__.py" +0 -18
  34. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/email.py" +0 -114
  35. oafuncs-0.0.81.dist-info/RECORD +0 -51
  36. {oafuncs-0.0.81.dist-info → oafuncs-0.0.82.dist-info}/LICENSE.txt +0 -0
  37. {oafuncs-0.0.81.dist-info → oafuncs-0.0.82.dist-info}/WHEEL +0 -0
  38. {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__ = ['fig_minus', 'create_gif', 'xy2lonlat', 'plot_contourf', 'plot_contourf_lonlat', 'plot_quiver', 'plot_contourf_cartopy']
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='GIF', duration=duration)
95
- print('Gif制作完成!')
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='lon', decimal=2):
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 == 'lon':
131
+ if lonlat == "lon":
131
132
  return format_longitude(xy)
132
- elif lonlat == 'lat':
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 = '{:.1e}'.format(x).split('e')
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 = '{:.2e}'.format(x).split('e')
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 '${}{:.2f}$'.format(' ' if (self.p_n and x > 0) else '', a)
161
+ return "${}{:.2f}$".format(" " if (self.p_n and x > 0) else "", a)
162
162
  elif x == 0:
163
- return '0'
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='rainbow', minmax=None, labels=None, ticks_space=None, ticks=None, figsize=(12, 9)):
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='both') if flag_lc else ax.contourf(x, y, pic_data, cmap=cmap, norm=norm, extend='both')
200
- 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')
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['c'])
213
- plt.xlabel(labels['x'])
214
- plt.ylabel(labels['y'])
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
- 1e-5, ticks_space['x']), ticks['x'])
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('Min: {:.3g}, Max: {:.3g}'.format(
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='rainbow'):
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='coolwarm', scale=0.25, width=0.002, x_space=5, y_space=5):
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(lon_c[::y_space, ::x_space],
311
- lat_c[::y_space, ::x_space],
312
- u[::y_space, ::x_space],
313
- v[::y_space, ::x_space],
314
- S[::y_space, ::x_space], # 矢量的大小,可以不要
315
- pivot='middle',
316
- scale=scale,
317
- # color=color, # 矢量的颜色,单色
318
- cmap=cmap, # 矢量的颜色,多色
319
- width=width)
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'{mean_S:.2f} m/s', labelpos='E', fontproperties={'size': 10})
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('X')
324
- plt.ylabel('Y')
319
+ plt.xlabel("X")
320
+ plt.ylabel("Y")
325
321
 
326
- plt.savefig(picname, bbox_inches='tight') if picname is not None else plt.show()
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='rainbow', cn_fill_num=20, fig_size=(12, 9), title='Cartopy', land_color='green', ocean_color='lightgrey'):
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='both', alpha=1, zorder=0)
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='vertical', extend='both', format='%.3f')
407
- cax.yaxis.set_ticks_position('right')
408
- cax.yaxis.set_label_position('right')
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='horizontal', extend='both')
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='in', width=1, length=2)
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='bold')
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='tight', dpi=600) if picname is not None else plt.show()
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
- if __name__ == '__main__':
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 = 'test.png'
434
- plot_contourf(data, picname, c_map='rainbow', minmax=None, labels=None, ticks_space=None, ticks=None, figsize=(12, 9))
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 = 'test.png'
441
- plot_quiver(u, v, lon, lat, picname, cmap='coolwarm', scale=0.25, width=0.002, x_space=5, y_space=5)
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 = 'test.png'
447
- plot_contourf_lonlat(data, lon, lat, interval=5, picname=picname, c_map='rainbow')
498
+ picname = "test.png"
499
+ plot_contourf_lonlat(data, lon, lat, interval=5, picname=picname, c_map="rainbow")
448
500
  # ** 制作动图
449
- image_list = ['test1.png', 'test2.png', 'test3.png']
450
- gif_name = 'test.gif'
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)