oafuncs 0.0.84__py2.py3-none-any.whl → 0.0.86__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.
Binary file
oafuncs/oa_cmap.py CHANGED
@@ -16,17 +16,23 @@ Python Version: 3.11
16
16
  import matplotlib as mpl
17
17
  import matplotlib.pyplot as plt
18
18
  import numpy as np
19
+ from rich import print
19
20
 
20
- __all__ = ["show", "cmap2colors", "create_cmap", "create_cmap_rgbtxt", "choose_cmap"]
21
+ __all__ = ["show", "to_color", "create", "create_rgbtxt", "get"]
21
22
 
22
23
  # ** 将cmap用填色图可视化(官网摘抄函数)
23
- def show(colormaps: list):
24
+ def show(colormaps):
24
25
  """
25
- Helper function to plot data with associated colormap.
26
- example:
27
- cmap = ListedColormap(["darkorange", "gold", "lawngreen", "lightseagreen"])
28
- show([cmap])
26
+ Description:
27
+ Helper function to plot data with associated colormap.
28
+ Parameters:
29
+ colormaps : list of colormaps, or a single colormap; can be a string or a colormap object.
30
+ Example:
31
+ cmap = ListedColormap(["darkorange", "gold", "lawngreen", "lightseagreen"])
32
+ show([cmap]); show("viridis"); show(["viridis", "cividis"])
29
33
  """
34
+ if isinstance(colormaps, str) or isinstance(colormaps, mpl.colors.Colormap):
35
+ colormaps = [colormaps]
30
36
  np.random.seed(19680801)
31
37
  data = np.random.randn(30, 30)
32
38
  n = len(colormaps)
@@ -38,12 +44,17 @@ def show(colormaps: list):
38
44
 
39
45
 
40
46
  # ** 将cmap转为list,即多个颜色的列表
41
- def cmap2colors(cmap, n=256):
47
+ def to_color(cmap, n=256):
42
48
  """
43
- cmap : cmap名称
44
- n : 提取颜色数量
45
- return : 提取的颜色列表
46
- example : out_colors = cmap2colors('viridis', 256)
49
+ Description:
50
+ Convert a colormap to a list of colors
51
+ Parameters:
52
+ cmap : str; the name of the colormap
53
+ n : int, optional; the number of colors
54
+ Return:
55
+ out_colors : list of colors
56
+ Example:
57
+ out_colors = to_color('viridis', 256)
47
58
  """
48
59
  c_map = mpl.colormaps.get_cmap(cmap)
49
60
  out_colors = [c_map(i) for i in np.linspace(0, 1, n)]
@@ -51,16 +62,22 @@ def cmap2colors(cmap, n=256):
51
62
 
52
63
 
53
64
  # ** 自制cmap,多色,可带位置
54
- def create_cmap(colors: list, nodes=None, under=None, over=None): # 利用颜色快速配色
65
+ def create(colors: list, nodes=None, under=None, over=None): # 利用颜色快速配色
55
66
  """
56
- func : 自制cmap,自动确定颜色位置(等比例)
57
- description : colors可以是颜色名称,也可以是十六进制颜色代码
58
- param {*} colors 颜色
59
- param {*} nodes 颜色位置,默认不提供,等间距
60
- return {*} cmap
61
- example : cmap = create_cmap(['#C2B7F3','#B3BBF2','#B0CBF1','#ACDCF0','#A8EEED'])
62
- cmap = create_cmap(['aliceblue','skyblue','deepskyblue'],[0.0,0.5,1.0])
67
+ Description:
68
+ Create a custom colormap
69
+ Parameters:
70
+ colors : list of colors
71
+ nodes : list of positions
72
+ under : color
73
+ over : color
74
+ Return:
75
+ cmap : colormap
76
+ Example:
77
+ cmap = create(['#C2B7F3','#B3BBF2','#B0CBF1','#ACDCF0','#A8EEED'])
78
+ cmap = create(['aliceblue','skyblue','deepskyblue'],[0.0,0.5,1.0])
63
79
  """
80
+
64
81
  if nodes is None: # 采取自动分配比例
65
82
  cmap_color = mpl.colors.LinearSegmentedColormap.from_list("mycmap", colors)
66
83
  else: # 按照提供比例分配
@@ -73,17 +90,30 @@ def create_cmap(colors: list, nodes=None, under=None, over=None): # 利用颜
73
90
 
74
91
 
75
92
  # ** 根据RGB的txt文档制作色卡(利用Grads调色盘)
76
- def create_cmap_rgbtxt(rgbtxt_file,split_mark=','): # 根据RGB的txt文档制作色卡/根据rgb值制作
93
+ def create_rgbtxt(rgbtxt_file,split_mark=','): # 根据RGB的txt文档制作色卡/根据rgb值制作
77
94
  """
78
- func : 根据RGB的txt文档制作色卡
79
- description : rgbtxt_file='E:/python/colorbar/test.txt'
80
- param {*} rgbtxt_file txt文件路径
81
- return {*} camp
82
- example : cmap=create_cmap_rgbtxt(path,split_mark=',') #
83
-
84
- txt example : 251,251,253
85
- 225,125,25
86
- 250,205,255
95
+ Description
96
+ -----------
97
+ Make a color card according to the RGB txt document, each line in the txt file is an RGB value, separated by commas, such as: 251,251,253
98
+
99
+ Parameters
100
+ ----------
101
+ rgbtxt_file : str, the path of txt file
102
+ split_mark : str, optional, default is ','; the split mark of rgb value
103
+
104
+ Returns
105
+ -------
106
+ cmap : colormap
107
+
108
+ Example
109
+ -------
110
+ cmap=create_rgbtxt(path,split_mark=',')
111
+
112
+ txt example
113
+ -----------
114
+ 251,251,253
115
+ 225,125,25
116
+ 250,205,255
87
117
  """
88
118
  with open(rgbtxt_file) as fid:
89
119
  data = fid.readlines()
@@ -94,27 +124,36 @@ def create_cmap_rgbtxt(rgbtxt_file,split_mark=','): # 根据RGB的txt文档制
94
124
  rgb[i][1] = data[i].split(split_mark)[1]
95
125
  rgb[i][2] = data[i].split(split_mark)[2]
96
126
  max_rgb = np.max(rgb)
97
- if max_rgb > 2: # 如果rgb值大于2,则认为是0-255的值,需要归一化
127
+ if max_rgb > 2: # if the value is greater than 2, it is normalized to 0-1
98
128
  rgb = rgb / 255.0
99
- icmap = mpl.colors.ListedColormap(rgb, name="my_color")
100
- return icmap
129
+ my_cmap = mpl.colors.ListedColormap(rgb, name="my_color")
130
+ return my_cmap
101
131
 
102
132
 
103
133
  # ** 选择cmap
104
- def choose_cmap(cmap_name=None, query=False):
134
+ def get(cmap_name=None, query=False):
105
135
  """
106
- description: Choosing a colormap from the list of available colormaps or a custom colormap
107
- param {*} cmap_name:
108
- param {*} query:
109
- return {*}
136
+ Description:
137
+ Choosing a colormap from the list of available colormaps or a custom colormap
138
+ Parameters:
139
+ cmap_name : str, optional; the name of the colormap
140
+ query : bool, optional; whether to query the available colormap names
141
+ Return:
142
+ cmap : colormap
143
+ Example:
144
+ cmap = get('viridis')
145
+ cmap = get('diverging_1')
146
+ cmap = get('cold_1')
147
+ cmap = get('warm_1')
148
+ cmap = get('colorful_1')
110
149
  """
111
150
 
112
151
  my_cmap_dict = {
113
- "diverging_1": create_cmap(["#4e00b3", "#0000FF", "#00c0ff", "#a1d3ff", "#DCDCDC", "#FFD39B", "#FF8247", "#FF0000", "#FF5F9E"]),
114
- "cold_1": create_cmap(["#4e00b3", "#0000FF", "#00c0ff", "#a1d3ff", "#DCDCDC"]),
115
- "warm_1": create_cmap(["#DCDCDC", "#FFD39B", "#FF8247", "#FF0000", "#FF5F9E"]),
116
- # "land_1": create_custom(["#3E6436", "#678A59", "#91A176", "#B8A87D", "#D9CBB2"], under="#A6CEE3", over="#FFFFFF"), # 陆地颜色从深绿到浅棕,表示从植被到沙地的递减
117
- # "ocean_1": create_custom(["#126697", "#2D88B3", "#4EA1C9", "#78B9D8", "#A6CEE3"], under="#8470FF", over="#3E6436"), # 海洋颜色从深蓝到浅蓝,表示从深海到浅海的递减
152
+ "diverging_1": create(["#4e00b3", "#0000FF", "#00c0ff", "#a1d3ff", "#DCDCDC", "#FFD39B", "#FF8247", "#FF0000", "#FF5F9E"]),
153
+ "cold_1": create(["#4e00b3", "#0000FF", "#00c0ff", "#a1d3ff", "#DCDCDC"]),
154
+ "warm_1": create(["#DCDCDC", "#FFD39B", "#FF8247", "#FF0000", "#FF5F9E"]),
155
+ # "land_1": create_custom(["#3E6436", "#678A59", "#91A176", "#B8A87D", "#D9CBB2"], under="#A6CEE3", over="#FFFFFF"),
156
+ # "ocean_1": create_custom(["#126697", "#2D88B3", "#4EA1C9", "#78B9D8", "#A6CEE3"], under="#8470FF", over="#3E6436"),
118
157
  # "ocean_land_1": create_custom(
119
158
  # [
120
159
  # "#126697", # 深蓝(深海)
@@ -130,11 +169,21 @@ def choose_cmap(cmap_name=None, query=False):
130
169
  # "#3E6436", # 深绿(高山)
131
170
  # ]
132
171
  # ),
133
- "colorful_1": create_cmap(["#6d00db", "#9800cb", "#F2003C", "#ff4500", "#ff7f00", "#FE28A2", "#FFC0CB", "#DDA0DD", "#40E0D0", "#1a66f2", "#00f7fb", "#8fff88", "#E3FF00"]),
172
+ "colorful_1": create(["#6d00db", "#9800cb", "#F2003C", "#ff4500", "#ff7f00", "#FE28A2", "#FFC0CB", "#DDA0DD", "#40E0D0", "#1a66f2", "#00f7fb", "#8fff88", "#E3FF00"]),
134
173
  }
135
174
  if query:
175
+ print("Available cmap names:")
176
+ print('-' * 20)
177
+ print('Defined by myself:')
136
178
  for key, _ in my_cmap_dict.items():
137
179
  print(key)
180
+ print('-' * 20)
181
+ print('Matplotlib built-in:')
182
+ print(mpl.colormaps())
183
+ print("-" * 20)
184
+
185
+ if cmap_name is None:
186
+ return
138
187
 
139
188
  if cmap_name in my_cmap_dict:
140
189
  return my_cmap_dict[cmap_name]
@@ -149,16 +198,16 @@ if __name__ == "__main__":
149
198
  # ** 测试自制cmap
150
199
  colors = ["#C2B7F3", "#B3BBF2", "#B0CBF1", "#ACDCF0", "#A8EEED"]
151
200
  nodes = [0.0, 0.2, 0.4, 0.6, 1.0]
152
- c_map = create_cmap(colors, nodes)
201
+ c_map = create(colors, nodes)
153
202
  show([c_map])
154
203
 
155
204
  # ** 测试自制diverging型cmap
156
- diverging_cmap = create_cmap(["#4e00b3", "#0000FF", "#00c0ff", "#a1d3ff", "#DCDCDC", "#FFD39B", "#FF8247", "#FF0000", "#FF5F9E"])
205
+ diverging_cmap = create(["#4e00b3", "#0000FF", "#00c0ff", "#a1d3ff", "#DCDCDC", "#FFD39B", "#FF8247", "#FF0000", "#FF5F9E"])
157
206
  show([diverging_cmap])
158
207
 
159
208
  # ** 测试根据RGB的txt文档制作色卡
160
209
  file_path = "E:/python/colorbar/test.txt"
161
- cmap_rgb = create_cmap_rgbtxt(file_path)
210
+ cmap_rgb = create_rgbtxt(file_path)
162
211
 
163
212
  # ** 测试将cmap转为list
164
- out_colors = cmap2colors("viridis", 256)
213
+ out_colors = to_color("viridis", 256)
oafuncs/oa_data.py CHANGED
@@ -15,12 +15,12 @@ Python Version: 3.11
15
15
 
16
16
  import itertools
17
17
  import multiprocessing as mp
18
- from concurrent.futures import ThreadPoolExecutor
18
+ from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
19
19
 
20
20
  import numpy as np
21
21
  from scipy.interpolate import griddata
22
22
 
23
- __all__ = ["interp_2d"]
23
+ __all__ = ["interp_2d","ParallelExecutor"]
24
24
 
25
25
 
26
26
  def interp_2d(target_x, target_y, origin_x, origin_y, data, method="linear", parallel=True):
@@ -90,6 +90,73 @@ def interp_2d(target_x, target_y, origin_x, origin_y, data, method="linear", par
90
90
  return np.array(interpolated_data)
91
91
 
92
92
 
93
+ class ParallelExecutor:
94
+ """
95
+ 通用并行计算类,支持多进程和多线程模式。
96
+
97
+ 使用说明:
98
+ 1. 创建实例时选择模式:
99
+ - mode="process" 使用多进程(适合 CPU 密集型任务)。
100
+ - mode="thread" 使用多线程(适合 IO 密集型任务)。
101
+
102
+ 2. 调用 run 方法:
103
+ - 参数 func:需要并行执行的函数。
104
+ - 参数 param_list:参数列表,每个元素是传递给 func 的参数元组。
105
+
106
+ 示例:
107
+ # 示例 1:计算平方
108
+ def compute_square(x):
109
+ return x * x
110
+
111
+ params = [(i,) for i in range(10)]
112
+ executor = ParallelExecutor(mode="process", max_workers=4)
113
+ results = executor.run(compute_square, params)
114
+ print("Results:", results)
115
+
116
+ # 示例 2:计算两数之和
117
+ def compute_sum(a, b):
118
+ return a + b
119
+
120
+ params = [(1, 2), (3, 4), (5, 6)]
121
+ executor = ParallelExecutor(mode="thread", max_workers=2)
122
+ results = executor.run(compute_sum, params)
123
+ print("Results:", results)
124
+
125
+ 参数:
126
+ mode (str): 并行模式,"process" 表示多进程,"thread" 表示多线程。
127
+ max_workers (int): 最大并行工作数,默认为 CPU 核心数减 2。
128
+ """
129
+
130
+ def __init__(self, mode="process", max_workers=mp.cpu_count() - 2):
131
+ self.mode = mode
132
+ self.max_workers = max_workers
133
+ self.executor = ProcessPoolExecutor if mode == "process" else ThreadPoolExecutor
134
+
135
+ def run(self, func, param_list):
136
+ """
137
+ 并行运行指定函数,并确保结果顺序与输入参数顺序一致。
138
+
139
+ 参数:
140
+ func (callable): 需要并行执行的函数。
141
+ param_list (list): 参数列表,每个元素是传递给 func 的参数元组。
142
+
143
+ 返回:
144
+ results (list): 按输入顺序返回的结果。
145
+ """
146
+ results = [None] * len(param_list) # 预分配结果数组
147
+
148
+ with self.executor(max_workers=self.max_workers) as executor:
149
+ # 提交任务并保存其索引
150
+ future_to_index = {executor.submit(func, *params): idx for idx, params in enumerate(param_list)}
151
+
152
+ for future in future_to_index:
153
+ idx = future_to_index[future] # 获取原始索引
154
+ results[idx] = future.result() # 将结果存放到对应位置
155
+
156
+ return results
157
+
158
+
159
+ # ---------------------------------------------------------------------------------- not used below ----------------------------------------------------------------------------------
93
160
  # ** 高维插值函数,插值最后两个维度
94
161
  def interp_2d_20241213(target_x, target_y, origin_x, origin_y, data, method="linear"):
95
162
  """
@@ -228,8 +295,25 @@ def interp_2d_parallel_20241213(target_x, target_y, origin_x, origin_y, data, me
228
295
  return interpolated_data
229
296
 
230
297
 
298
+ def _test_sum(a,b):
299
+ return a+b
300
+
301
+
231
302
  if __name__ == "__main__":
232
- import time
303
+ # 参数列表:每个参数是元组
304
+ params_list = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10)]
305
+
306
+ # 创建并行执行器
307
+ executor = ParallelExecutor()
308
+
309
+ # 并行运行
310
+ results = executor.run(_test_sum, params_list)
311
+
312
+ # 验证结果顺序
313
+ print("Params:", params_list)
314
+ print("Results:", results)
315
+ pass
316
+ """ import time
233
317
 
234
318
  import matplotlib.pyplot as plt
235
319
 
@@ -263,4 +347,4 @@ if __name__ == "__main__":
263
347
  plt.figure()
264
348
  plt.contourf(target_x, target_y, interpolated_data[0, 0, :, :])
265
349
  plt.colorbar()
266
- plt.show()
350
+ plt.show() """
oafuncs/oa_draw.py CHANGED
@@ -13,7 +13,7 @@ SystemInfo: Windows 11
13
13
  Python Version: 3.11
14
14
  """
15
15
 
16
- import math
16
+
17
17
  import warnings
18
18
 
19
19
  import cartopy.crs as ccrs
@@ -23,9 +23,8 @@ import matplotlib.pyplot as plt
23
23
  import numpy as np
24
24
  import xarray as xr
25
25
  from cartopy.mpl.ticker import LatitudeFormatter, LongitudeFormatter
26
- from mpl_toolkits.axes_grid1 import make_axes_locatable
27
26
 
28
- __all__ = ["fig_minus", "create_gif", "add_cartopy", "add_gridlines", 'MidpointNormalize', "add_lonlat_unit", "plot_contourf", "plot_contourf_lonlat", "plot_quiver", "plot_contourf_cartopy"]
27
+ __all__ = ["fig_minus", "gif", "add_cartopy", "add_gridlines", "MidpointNormalize", "add_lonlat_unit", "contour", "contourf", "quiver"]
29
28
 
30
29
  warnings.filterwarnings("ignore")
31
30
 
@@ -76,15 +75,18 @@ def fig_minus(ax_x=None, ax_y=None, cbar=None, decimal=None, add_space=False):
76
75
 
77
76
 
78
77
  # ** 将生成图片/已有图片制作成动图
79
- def create_gif(image_list: list, gif_name: str, duration=0.2): # 制作动图,默认间隔0.2
78
+ def gif(image_list: list, gif_name: str, duration=0.2): # 制作动图,默认间隔0.2
80
79
  """
81
- func : 制作动图,将已有图片拼接
82
- description : Gif格式动图
83
- param {*} image_list 图片列表
84
- param {*} gif_name 动图名称(含路径)
85
- param {*} duration 动图间隔
86
- return {*} 自动保存至指定路径(包含于动图名称中)
87
- example :
80
+ Description
81
+ Make gif from images
82
+ Parameters
83
+ image_list : list, list of images
84
+ gif_name : str, name of gif
85
+ duration : float, duration of each frame
86
+ Returns
87
+ None
88
+ Example
89
+ gif(["1.png", "2.png"], "test.gif", duration=0.2)
88
90
  """
89
91
  import imageio.v2 as imageio
90
92
 
@@ -150,12 +152,11 @@ def add_gridlines(ax, projection=ccrs.PlateCarree(), color="k", alpha=0.5, lines
150
152
 
151
153
  # ** 添加地图
152
154
  def add_cartopy(ax, lon=None, lat=None, projection=ccrs.PlateCarree(), gridlines=True, landcolor="lightgrey", oceancolor="lightblue", cartopy_linewidth=0.5):
153
-
154
155
  # add coastlines
155
156
  ax.add_feature(cfeature.LAND, facecolor=landcolor)
156
157
  ax.add_feature(cfeature.OCEAN, facecolor=oceancolor)
157
158
  ax.add_feature(cfeature.COASTLINE, linewidth=cartopy_linewidth)
158
- ax.add_feature(cfeature.BORDERS, linewidth=cartopy_linewidth, linestyle=":")
159
+ # ax.add_feature(cfeature.BORDERS, linewidth=cartopy_linewidth, linestyle=":")
159
160
 
160
161
  # add gridlines
161
162
  if gridlines:
@@ -201,141 +202,68 @@ class MidpointNormalize(mpl.colors.Normalize):
201
202
 
202
203
  # -----------------------------------------------------------------------------------------------------------------------------------------------------------------
203
204
 
204
-
205
- # ** 设置colorbar格式
206
- class _MyFormatter(mpl.ticker.ScalarFormatter):
207
- def __init__(self, cticks, fmt=None, useOffset=True, useMathText=True):
208
- mpl.ticker.ScalarFormatter.__init__(self, useOffset, useMathText)
209
- self.cticks = cticks
210
- self.fmt = fmt
211
- self.vmin = min(cticks)
212
- self.vmax = max(cticks)
213
- self.p_n = self.vmin < 0 and self.vmax > 0
214
- self.magnitude_min = int(math.modf(math.log10(min(abs(cticks[cticks != 0]))))[1])
215
- self.magnitude_max = int(math.modf(math.log10(max(abs(cticks))))[1])
216
- # print(self.vmin, self.vmax)
217
-
218
- def __call__(self, x, pos):
219
- if ((abs(x) < 1e-2) or (abs(x) > 1e4)) and x != 0:
220
- if self.magnitude_max - self.magnitude_min == 1 and (int(math.modf(math.log10(abs(x)))[1]) == self.magnitude_min):
221
- a, b = "{:.1e}".format(x).split("e")
222
- a = float(a) / 10
223
- b = int(b) + 1
224
- else:
225
- a, b = "{:.2e}".format(x).split("e")
226
- a = float(a)
227
- b = int(b)
228
- # return '${}{} \\times 10^{{{}}}$'.format(' ' if (self.p_n and x > 0) else '', a, b)
229
- return "${}{:.2f}$".format(" " if (self.p_n and x > 0) else "", a)
230
- elif x == 0:
231
- return "0"
232
- else:
233
- return mpl.ticker.ScalarFormatter.__call__(self, x, pos)
234
-
235
-
236
- # ** 绘制单张填色图
237
- def plot_contourf(pic_data, picname=None, c_map="rainbow", minmax=None, labels=None, ticks_space=None, ticks=None, figsize=(12, 9)):
205
+ # ** 绘制填色图
206
+ def contourf(data,x=None,y=None,cmap='coolwarm',show=True,store=None,cartopy=False):
238
207
  """
239
- func : 绘制填色等值线图,单张
240
- description : 绘制单张填色等值线图,输入参数为横纵坐标、等值数据、图例标注等
241
- param {*}pic_data : 填色等值线图的等值数据
242
- param {*}picname : 图片保存的文件名(含路径)
243
- param {*}c_map : 颜色映射,默认rainbow
244
- param {*}minmax : 指定绘图的最大、小值,默认不指定
245
- param {*}labels : x、y轴以及图例的标注,默认不标注
246
- param {*}ticks_space : x、y轴刻度,以及所显示的标签,默认不显示
247
- param {*}figsize : 图片大小,默认(12,9)
248
- example : plot_contourf(pic_data, pictpath, var_name, c_map='bwr', labels=None, ticks_space=None, ticks=None, h=0, figsize=(12, 9))
208
+ Description: 绘制填色图
209
+
210
+ param {*} data : 二维数据
211
+ param {*} x : x轴坐标
212
+ param {*} y : y轴坐标
213
+ param {*} cmap : 颜色映射
214
+ param {*} show : 是否显示
215
+ param {*} store : 是否保存
216
+ param {*} cartopy : 是否使用cartopy
217
+
218
+ return {*}
249
219
  """
250
- cmap = mpl.colormaps.get_cmap(c_map)
251
- if minmax is not None:
252
- value_min, value_max = minmax[0], minmax[1]
220
+ data = np.array(data)
221
+ if x is None or y is None:
222
+ x = np.arange(data.shape[1])
223
+ y = np.arange(data.shape[0])
224
+ if cartopy:
225
+ fig, ax = plt.subplots(subplot_kw={'projection': ccrs.PlateCarree()})
226
+ add_cartopy(ax, lon=x, lat=y)
227
+ ax.contourf(x, y, data, transform=ccrs.PlateCarree(), cmap=cmap)
253
228
  else:
254
- value_min, value_max = pic_data.nanmin(), pic_data.nanmax()
255
- v_bry = max(abs(value_min), abs(value_max))
256
- flag = (value_min < 0) and (value_max > 0)
257
- 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)
258
- 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
259
- 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)
260
-
261
- shape = np.array(pic_data).shape
262
- x, y = np.meshgrid(np.arange(shape[1]), np.arange(shape[0]))
263
-
264
- fig, ax = plt.subplots(figsize=figsize)
265
- flag_lc = levels is not None and cticks is not None
266
- 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")
267
- 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")
268
- """%.3g采用的是自动调整格式,也可设置为%.3f,则改为3位小数"""
269
-
270
- # 将格式化器设置为自定义的函数
271
- class_cticks = np.array(cb.get_ticks())
272
- # print(class_cticks)
273
- cct = abs(class_cticks[class_cticks != 0])
274
- if (min(cct) < 1e-2) or max(cct) > 1e4: # 判断是否需要采用科学计数法
275
- cb.formatter = _MyFormatter(class_cticks)
276
- cb.update_ticks()
277
-
278
- if labels is not None:
279
- cb.set_label(labels["c"])
280
- plt.xlabel(labels["x"])
281
- plt.ylabel(labels["y"])
282
- if ticks_space is not None and ticks is not None:
283
- plt.xticks(np.arange(0, len(x[0, :]) + 1e-5, ticks_space["x"]), ticks["x"])
284
- plt.yticks(np.arange(0, len(y[:, 0]) + 1e-5, ticks_space["y"]), ticks["y"])
285
-
286
- plt.title("Min: {:.3g}, Max: {:.3g}".format(pic_data.min(), pic_data.max()))
287
-
288
- plt.savefig(picname, bbox_inches="tight") if picname is not None else plt.show()
289
- # plt.show()
290
- plt.clf()
291
- # 关闭当前figure
229
+ plt.contourf(x, y, data, cmap=cmap)
230
+ plt.colorbar()
231
+ plt.savefig(store, dpi=600, bbox_inches="tight") if store else plt.show()
292
232
  plt.close()
293
233
 
294
234
 
295
- # ** 画等高线图,带经纬度坐标轴
296
- def plot_contourf_lonlat(data, lon, lat, interval=5, picname=None, c_map="rainbow"):
235
+ # ** 绘制等值线图
236
+ def contour(data, x=None, y=None, cmap="coolwarm", show=True, store=None, cartopy=False):
297
237
  """
298
- param {*} data : 二维数据
299
- param {*} lon : 经度
300
- param {*} lat : 纬度
301
- param {*} interval : 经纬度间隔
302
- param {*} picname : 图片保存的文件名(含路径)
303
- param {*} c_map : 颜色映射,默认rainbow
304
- return {*} 无返回值
238
+ Description: 绘制等值线图
239
+
240
+ param {*} data : 二维数据
241
+ param {*} x : x轴坐标
242
+ param {*} y : y轴坐标
243
+ param {*} cmap : 颜色映射
244
+ param {*} show : 是否显示
245
+ param {*} store : 是否保存
246
+ param {*} cartopy : 是否使用cartopy
247
+
248
+ return {*}
305
249
  """
306
- if len(lon.shape) == 2:
307
- lon = lon[0, :]
308
- if len(lat.shape) == 2:
309
- lat = lat[:, 0]
310
- # interval是经纬度间隔,单位为°
311
- # 将lon,lat作为坐标轴刻度显示
312
-
313
- def format_longitude(x):
314
- if x > 180:
315
- x -= 360
316
- degrees = int(abs(x))
317
- direction = "E" if x >= 0 else "W"
318
- return f"{degrees}°{direction}" if x != 0 and x != 180 else f"{degrees}°"
319
-
320
- def format_latitude(y):
321
- if y > 90:
322
- y -= 180
323
- degrees = int(abs(y))
324
- direction = "N" if y >= 0 else "S"
325
- return f"{degrees}°{direction}" if y != 0 else f"{degrees}°"
326
-
327
- plt.contourf(data, cmap=c_map)
328
- x_space = int(len(lon) * interval / (lon[-1] - lon[0]))
329
- y_space = int(len(lat) * interval / (lat[-1] - lat[0]))
330
- plt.xticks(np.arange(0, len(lon), x_space), [format_longitude(lon[i]) for i in range(0, len(lon), x_space)])
331
- plt.yticks(np.arange(0, len(lat), y_space), [format_latitude(lat[i]) for i in range(0, len(lat), y_space)])
332
- plt.colorbar()
333
- plt.savefig(picname, bbox_inches="tight") if picname is not None else plt.show()
250
+ data = np.array(data)
251
+ if x is None or y is None:
252
+ x = np.arange(data.shape[1])
253
+ y = np.arange(data.shape[0])
254
+ if cartopy:
255
+ fig, ax = plt.subplots(subplot_kw={"projection": ccrs.PlateCarree()})
256
+ add_cartopy(ax, lon=x, lat=y)
257
+ cr = ax.contour(x, y, data, transform=ccrs.PlateCarree(), cmap=cmap)
258
+ else:
259
+ cr = plt.contour(x, y, data, cmap=cmap)
260
+ plt.clabel(cr, inline=True, fontsize=10)
261
+ plt.savefig(store, dpi=600, bbox_inches="tight") if store else plt.show()
334
262
  plt.close()
335
263
 
336
264
 
337
265
  # ** 绘制矢量场
338
- def plot_quiver(u, v, lon, lat, picname=None, cmap="coolwarm", scale=0.25, width=0.002, x_space=5, y_space=5):
266
+ def quiver(u, v, lon, lat, picname=None, cmap="coolwarm", scale=0.25, width=0.002, x_space=5, y_space=5):
339
267
  """
340
268
  param {*} u : 二维数据
341
269
  param {*} v : 二维数据
@@ -392,122 +320,6 @@ def plot_quiver(u, v, lon, lat, picname=None, cmap="coolwarm", scale=0.25, width
392
320
  plt.close()
393
321
 
394
322
 
395
- # ** 绘制填色图(带经纬度)
396
- 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"):
397
- """
398
- param {*} data : 二维数据
399
- param {*} lon : 经度
400
- param {*} lat : 纬度
401
- param {*} picname : 图片保存的文件名(含路径)
402
- param {*} cmap : 颜色映射,默认rainbow
403
- param {*} cn_fill_num : 等值线数量
404
- param {*} fig_size : 图片大小,默认(12,9)
405
- param {*} title : 图片标题
406
- param {*} land_color : 陆地颜色
407
- param {*} ocean_color : 海洋颜色
408
- return {*} 无返回值
409
- """
410
- if len(lon.shape) == 2:
411
- lon = lon[0, :]
412
- if len(lat.shape) == 2:
413
- lat = lat[:, 0]
414
-
415
- data_max = np.nanmax(data)
416
- data_min = np.nanmin(data)
417
- levels = np.linspace(data_min, data_max, cn_fill_num)
418
- cbar_ticks = np.linspace(data_min, data_max, 9)
419
-
420
- fig = plt.figure(figsize=fig_size)
421
- proj = ccrs.PlateCarree()
422
- ax = fig.add_subplot(1, 1, 1, projection=proj)
423
-
424
- ax.set_extent([lon[0], lon[-1], lat[0], lat[-1]], crs=proj)
425
-
426
- ax.add_feature(cfeature.LAND, facecolor=land_color, edgecolor="k")
427
- ax.add_feature(cfeature.COASTLINE, linewidth=0.5)
428
- # ax.add_feature(cfeature.BORDERS, linewidth=0.5, linestyle=":") # 加载国界线
429
-
430
- ax.set_xticks(np.arange(lon[0], lon[-1] + 1e-5, 5), crs=proj)
431
- ax.set_yticks(np.arange(lat[0], lat[-1] + 1e-5, 5), crs=proj)
432
- lon_formatter = LongitudeFormatter(zero_direction_label=True)
433
- ax.xaxis.set_major_formatter(lon_formatter)
434
- lat_formatter = LatitudeFormatter()
435
- ax.yaxis.set_major_formatter(lat_formatter)
436
- # plt.title(title, fontsize=16)
437
-
438
- cmap = plt.get_cmap(cmap)
439
- X, Y = np.meshgrid(lon, lat)
440
-
441
- # Fill color for land and ocean
442
- # ax.background_patch.set_facecolor(ocean_color)
443
- ax.patch.set_facecolor(ocean_color)
444
- ax.add_feature(cfeature.LAND, facecolor=land_color)
445
-
446
- cticks = cbar_ticks
447
- norm = mpl.colors.BoundaryNorm(cticks, cmap.N)
448
-
449
- cnplot = ax.contourf(X, Y, data, levels=levels, cmap=cmap, norm=norm, transform=proj, extend="both", alpha=1, zorder=0)
450
- # cllevels = np.linspace(data_min, data_max, 9)
451
- # clplot = ax.contour(X, Y, data, levels=levels[9::10], colors='k', linewidths=0.5, transform=proj, zorder=1, alpha=0.8, linestyle='--')
452
- # 添加色标,并选择位置
453
- divider = make_axes_locatable(ax)
454
- location = 3
455
- if location == 1: # 左侧
456
- cax = divider.new_horizontal(size="5%", pad=1, axes_class=plt.Axes, pack_start=True)
457
- fig.add_axes(cax)
458
- cbar = plt.colorbar(cnplot, cax=cax, orientation="vertical", extend="both")
459
- elif location == 2: # 下方
460
- cax = divider.new_vertical(size="5%", pad=0.3, axes_class=plt.Axes, pack_start=True)
461
- fig.add_axes(cax)
462
- cbar = plt.colorbar(cnplot, cax=cax, orientation="horizontal", extend="both")
463
- elif location == 3: # 右侧
464
- cax = divider.new_horizontal(size="5%", pad=0.1, axes_class=plt.Axes)
465
- fig.add_axes(cax)
466
- # cbar = plt.colorbar(cnplot, cax=cax, orientation='vertical', extend='both', format='%.0f')
467
- cbar = fig.colorbar(mpl.cm.ScalarMappable(cmap=cmap, norm=norm), cax=cax, orientation="vertical", extend="both", format="%.3f")
468
- cax.yaxis.set_ticks_position("right")
469
- cax.yaxis.set_label_position("right")
470
- else: # 上方
471
- cax = divider.new_vertical(size="5%", pad=0.2, axes_class=plt.Axes)
472
- fig.add_axes(cax)
473
- cbar = plt.colorbar(cnplot, cax=cax, orientation="horizontal", extend="both")
474
- cbar.ax.tick_params(labelsize=10)
475
- cbar.ax.xaxis.set_tick_params(direction="in", width=1, length=2)
476
- # 添加cbar_ticks
477
- # cbar.set_ticks(np.arange(round(levels[0]), round(levels[-1]), round((levels[-1]-levels[0])/9))) # 设置色标刻度
478
- # cbar.set_ticks(cbar_ticks) # 设置色标刻度
479
-
480
- cbar.set_ticks(cticks)
481
- # cbar.ax.ticks = np.linspace(data_min, data_max, 8)
482
- # cbar.set_ticks(np.arange(round(levels[0]), round(levels[-1]), round((levels[-1]-levels[0])/9))) # 设置色标刻度
483
-
484
- # 单独设置label
485
- cbar.set_label(title, fontsize=10, weight="bold")
486
- # cax.set_position([0.1, 0.2, 0.02, 0.6]) # 调整色标位置
487
- fig.savefig(picname, bbox_inches="tight", dpi=600) if picname is not None else plt.show()
488
- plt.close()
489
-
490
-
491
323
 
492
324
  if __name__ == "__main__":
493
- # ** 绘制填色图
494
- data = np.random.randn(100, 100)
495
- picname = "test.png"
496
- plot_contourf(data, picname, c_map="rainbow", minmax=None, labels=None, ticks_space=None, ticks=None, figsize=(12, 9))
497
- # ** 绘制矢量场
498
- u = np.random.randn(100, 100)
499
- v = np.random.randn(100, 100)
500
- lon = np.linspace(0, 360, 100)
501
- lat = np.linspace(-90, 90, 100)
502
- picname = "test.png"
503
- plot_quiver(u, v, lon, lat, picname, cmap="coolwarm", scale=0.25, width=0.002, x_space=5, y_space=5)
504
- # ** 绘制经纬度填色图
505
- data = np.random.randn(100, 100)
506
- lon = np.linspace(0, 360, 100)
507
- lat = np.linspace(-90, 90, 100)
508
- picname = "test.png"
509
- plot_contourf_lonlat(data, lon, lat, interval=5, picname=picname, c_map="rainbow")
510
- # ** 制作动图
511
- image_list = ["test1.png", "test2.png", "test3.png"]
512
- gif_name = "test.gif"
513
- create_gif(image_list, gif_name, duration=0.2)
325
+ pass
oafuncs/oa_help.py CHANGED
@@ -4,7 +4,7 @@
4
4
  Author: Liu Kun && 16031215@qq.com
5
5
  Date: 2024-10-06 19:25:29
6
6
  LastEditors: Liu Kun && 16031215@qq.com
7
- LastEditTime: 2024-12-26 10:43:40
7
+ LastEditTime: 2025-01-01 21:09:58
8
8
  FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_help.py
9
9
  Description:
10
10
  EditPlatform: vscode
@@ -14,8 +14,11 @@ Python Version: 3.12
14
14
  """
15
15
 
16
16
  import oafuncs
17
+ import pkgutil
18
+ import importlib
19
+ from rich import print
17
20
 
18
- __all__ = ["query", "use"]
21
+ __all__ = ["query", "use", "log"]
19
22
 
20
23
 
21
24
  def query():
@@ -28,15 +31,93 @@ def query():
28
31
  print(len(funcs))
29
32
  print("函数列表:")
30
33
  print(funcs)
34
+
35
+ # 判断同名函数个数
36
+ func_dict = dict()
37
+ for func in funcs:
38
+ func_dict[func] = 0
39
+ for module_info in pkgutil.iter_modules(oafuncs.__path__, oafuncs.__name__ + "."):
40
+ module = importlib.import_module(module_info.name)
41
+ for func in funcs:
42
+ if hasattr(module, func):
43
+ func_dict[func] += 1
44
+ print("同名函数:")
45
+ for func, count in func_dict.items():
46
+ if count > 1:
47
+ print(f"{func} : {count}")
31
48
 
32
49
 
33
- def use(func="get_var"):
50
+ def _use_single(func="get_var", module="oafuncs"):
34
51
  """
35
52
  description: 查看函数的模块全路径和函数提示
36
53
  param {func} : 函数名
37
54
  example: use('get_var')
38
55
  """
56
+ module = importlib.import_module(module)
39
57
  print("模块全路径:")
40
- print(getattr(oafuncs, func).__module__ + "." + func)
58
+ print(getattr(module, func).__module__ + "." + func)
41
59
  print("函数提示:")
42
- print(getattr(oafuncs, func).__doc__)
60
+ print(getattr(module, func).__doc__)
61
+
62
+
63
+ def use(func_name='log'):
64
+ """
65
+ description: 查看本库指定函数的所有模块全路径和函数提示
66
+ param {func_name} : 函数名
67
+ example: use('get_var')
68
+ """
69
+ found = False
70
+ # 假设oafuncs是一个包
71
+ if hasattr(oafuncs, "__path__"):
72
+ print("-" * 40) # 分隔线
73
+ # 遍历包内的所有模块
74
+ for module_info in pkgutil.iter_modules(oafuncs.__path__, oafuncs.__name__ + "."):
75
+ module_name = module_info.name
76
+ module = importlib.import_module(module_name)
77
+ if hasattr(module, func_name):
78
+ found = True
79
+ func_obj = getattr(module, func_name)
80
+ print(f"[bold purple]模块全路径:\n[bold green]{func_obj.__module__}.{func_name}\n")
81
+ help(func_obj)
82
+ """ doc = func_obj.__doc__
83
+ print("函数提示:")
84
+ if doc:
85
+ print(doc)
86
+ else:
87
+ print("无文档字符串") """
88
+ print("-" * 40) # 分隔线
89
+ else:
90
+ # 如果oafuncs只是一个模块,直接查找
91
+ if hasattr(oafuncs, func_name):
92
+ found = True
93
+ func_obj = getattr(oafuncs, func_name)
94
+ print(f"模块全路径:\n{func_obj.__module__}.{func_name}\n")
95
+ help(func_obj)
96
+ """ doc = func_obj.__doc__
97
+ print("函数提示:")
98
+ if doc:
99
+ print(doc)
100
+ else:
101
+ print("无文档字符串") """
102
+ if not found:
103
+ print(f"在oafuncs中没有找到名为 '{func_name}' 的函数。")
104
+
105
+
106
+ def log():
107
+ """
108
+ description: 查看更新日志
109
+ example: log()
110
+ """
111
+ print("更新日志:")
112
+ print(
113
+ """
114
+ 2025-01-01
115
+ 1. 添加了log函数,可以查看更新日志。
116
+ 2. 修改部分函数名,尽可能简化函数名。
117
+ """
118
+ )
119
+
120
+
121
+ if __name__ == "__main__":
122
+ # use("find_file")
123
+ query()
oafuncs/oa_nc.py CHANGED
@@ -19,7 +19,7 @@ import netCDF4 as nc
19
19
  import numpy as np
20
20
  import xarray as xr
21
21
 
22
- __all__ = ["get_var", "extract5nc", "write2nc", "merge5nc", "modify_var_value", "modify_var_attr", "rename_var_or_dim", "check_ncfile", "convert_longitude", "nc_isel"]
22
+ __all__ = ["get_var", "extract", "save", "merge", "modify", "rename", "check_file", "convert_longitude", "isel"]
23
23
 
24
24
 
25
25
  def get_var(file, *vars):
@@ -38,7 +38,7 @@ def get_var(file, *vars):
38
38
  return datas
39
39
 
40
40
 
41
- def extract5nc(file, varname, only_value=True):
41
+ def extract(file, varname, only_value=True):
42
42
  """
43
43
  描述:
44
44
  1、提取nc文件中的变量
@@ -48,7 +48,7 @@ def extract5nc(file, varname, only_value=True):
48
48
  file: 文件路径
49
49
  varname: 变量名
50
50
  only_value: 变量和维度是否只保留数值
51
- example: data, dimdict = extract5nc(file_ecm, 'h')
51
+ example: data, dimdict = extract(file_ecm, 'h')
52
52
  """
53
53
  ds = xr.open_dataset(file)
54
54
  vardata = ds[varname]
@@ -101,7 +101,7 @@ def _calculate_scale_and_offset(data, n=16):
101
101
  return scale_factor, add_offset
102
102
 
103
103
 
104
- def write2nc(file, data, varname=None, coords=None, mode="w", scale_offset_switch=True, compile_switch=True):
104
+ def save(file, data, varname=None, coords=None, mode="w", scale_offset_switch=True, compile_switch=True):
105
105
  """
106
106
  description: 写入数据到nc文件
107
107
 
@@ -114,7 +114,7 @@ def write2nc(file, data, varname=None, coords=None, mode="w", scale_offset_switc
114
114
  scale_offset_switch: 是否使用scale_factor和add_offset,默认为True
115
115
  compile_switch: 是否使用压缩参数,默认为True
116
116
 
117
- example: write2nc(r'test.nc', data, 'data', {'time': np.linspace(0, 120, 100), 'lev': np.linspace(0, 120, 50)}, 'a')
117
+ example: save(r'test.nc', data, 'data', {'time': np.linspace(0, 120, 100), 'lev': np.linspace(0, 120, 50)}, 'a')
118
118
  """
119
119
  # 设置压缩参数
120
120
  kwargs = {"zlib": True, "complevel": 4} if compile_switch else {}
@@ -175,7 +175,7 @@ def write2nc(file, data, varname=None, coords=None, mode="w", scale_offset_switc
175
175
  var.setncattr(key, value)
176
176
 
177
177
 
178
- def merge5nc(file_list, var_name=None, dim_name=None, target_filename=None):
178
+ def merge(file_list, var_name=None, dim_name=None, target_filename=None):
179
179
  """
180
180
  批量提取 nc 文件中的变量,按照某一维度合并后写入新的 nc 文件。
181
181
  如果 var_name 是字符串,则认为是单变量;如果是列表,且只有一个元素,也是单变量;
@@ -188,9 +188,9 @@ def merge5nc(file_list, var_name=None, dim_name=None, target_filename=None):
188
188
  target_filename:合并后的目标文件名
189
189
 
190
190
  example:
191
- merge5nc(file_list, var_name='data', dim_name='time', target_filename='merged.nc')
192
- merge5nc(file_list, var_name=['data1', 'data2'], dim_name='time', target_filename='merged.nc')
193
- merge5nc(file_list, var_name=None, dim_name='time', target_filename='merged.nc')
191
+ merge(file_list, var_name='data', dim_name='time', target_filename='merged.nc')
192
+ merge(file_list, var_name=['data1', 'data2'], dim_name='time', target_filename='merged.nc')
193
+ merge(file_list, var_name=None, dim_name='time', target_filename='merged.nc')
194
194
  """
195
195
  if isinstance(file_list, str):
196
196
  file_list = [file_list]
@@ -248,7 +248,7 @@ def merge5nc(file_list, var_name=None, dim_name=None, target_filename=None):
248
248
  print(f'File "{target_filename}" has been created.')
249
249
 
250
250
 
251
- def modify_var_value(nc_file_path, variable_name, new_value):
251
+ def _modify_var(nc_file_path, variable_name, new_value):
252
252
  """
253
253
  使用 netCDF4 库修改 NetCDF 文件中特定变量的值
254
254
 
@@ -257,7 +257,7 @@ def modify_var_value(nc_file_path, variable_name, new_value):
257
257
  variable_name (str): 要修改的变量名
258
258
  new_value (numpy.ndarray): 新的变量值
259
259
 
260
- example: modify_var_value('test.nc', 'data', np.random.rand(100, 50))
260
+ example: modify_var('test.nc', 'data', np.random.rand(100, 50))
261
261
  """
262
262
  try:
263
263
  # Open the NetCDF file
@@ -272,7 +272,7 @@ def modify_var_value(nc_file_path, variable_name, new_value):
272
272
  print(f"An error occurred while modifying variable {variable_name} in {nc_file_path}: {e}")
273
273
 
274
274
 
275
- def modify_var_attr(nc_file_path, variable_name, attribute_name, attribute_value):
275
+ def _modify_attr(nc_file_path, variable_name, attribute_name, attribute_value):
276
276
  """
277
277
  使用 netCDF4 库添加或修改 NetCDF 文件中特定变量的属性。
278
278
 
@@ -281,7 +281,7 @@ def modify_var_attr(nc_file_path, variable_name, attribute_name, attribute_value
281
281
  variable_name (str): 要操作的变量名
282
282
  attribute_name (str): 属性名
283
283
  attribute_value (任意类型): 属性值
284
- example: modify_var_attr('test.nc', 'data', 'long_name', 'This is a test variable.')
284
+ example: modify_attr('test.nc', 'temperature', 'long_name', 'Temperature in Celsius')
285
285
  """
286
286
  try:
287
287
  ds = nc.Dataset(nc_file_path, "r+")
@@ -301,7 +301,25 @@ def modify_var_attr(nc_file_path, variable_name, attribute_name, attribute_value
301
301
  raise RuntimeError(f"An error occurred: {e}")
302
302
 
303
303
 
304
- def rename_var_or_dim(ncfile_path, old_name, new_name):
304
+ def modify(nc_file,var_name,attr_name=None,new_value=None):
305
+ """
306
+ description: 修改nc文件中的变量值或属性值
307
+ parameters:
308
+ nc_file: str, nc文件路径
309
+ var_name: str, 变量名
310
+ attr_name: str, 属性名; None表示修改变量值
311
+ new_value: 任意类型, 新的变量值或属性值
312
+ example:
313
+ modify(nc_file, 'h', 'long_name', 'Height')
314
+ modify(nc_file, 'h', None, np.random.rand(100, 50))
315
+ """
316
+ if attr_name is None:
317
+ _modify_var(nc_file, var_name, new_value)
318
+ else:
319
+ _modify_attr(nc_file, var_name, attr_name, new_value)
320
+
321
+
322
+ def rename(ncfile_path, old_name, new_name):
305
323
  """
306
324
  Rename a variable and/or dimension in a NetCDF file.
307
325
 
@@ -310,7 +328,7 @@ def rename_var_or_dim(ncfile_path, old_name, new_name):
310
328
  old_name (str): The name of the variable or dimension to be renamed.
311
329
  new_name (str): The new name for the variable or dimension.
312
330
 
313
- example: rename_var_or_dim('test.nc', 'time', 'ocean_time')
331
+ example: rename('test.nc', 'time', 'ocean_time')
314
332
  """
315
333
  try:
316
334
  with nc.Dataset(ncfile_path, "r+") as dataset:
@@ -335,7 +353,17 @@ def rename_var_or_dim(ncfile_path, old_name, new_name):
335
353
  print(f"An error occurred: {e}")
336
354
 
337
355
 
338
- def check_ncfile(ncfile, if_delete=False):
356
+ def check_file(ncfile, if_delete=False):
357
+ '''
358
+ Description: 检查nc文件是否损坏
359
+
360
+ Parameters:
361
+ ncfile: str, nc文件路径
362
+ if_delete: bool, 是否删除损坏的文件,默认为False
363
+
364
+ Example:
365
+ check_file(ncfile, if_delete=True)
366
+ '''
339
367
  if not os.path.exists(ncfile):
340
368
  return False
341
369
 
@@ -377,7 +405,7 @@ def convert_longitude(ds, lon_name="longitude", convert=180):
377
405
  """
378
406
  to_which = int(convert)
379
407
  if to_which not in [180, 360]:
380
- raise ValueError("to_which must be '180' or '360'")
408
+ raise ValueError("convert value must be '180' or '360'")
381
409
 
382
410
  if to_which == 180:
383
411
  ds = ds.assign_coords({lon_name: (ds[lon_name] + 180) % 360 - 180})
@@ -387,7 +415,7 @@ def convert_longitude(ds, lon_name="longitude", convert=180):
387
415
  return ds.sortby(lon_name)
388
416
 
389
417
 
390
- def nc_isel(ncfile, dim_name, slice_list):
418
+ def isel(ncfile, dim_name, slice_list):
391
419
  """
392
420
  Description: Choose the data by the index of the dimension
393
421
 
@@ -399,6 +427,9 @@ def nc_isel(ncfile, dim_name, slice_list):
399
427
  slice_list example: slice_list = [[y*12+m for m in range(11,14)] for y in range(84)]
400
428
  or
401
429
  slice_list = [y * 12 + m for y in range(84) for m in range(11, 14)]
430
+
431
+ Example:
432
+ isel(ncfile, 'time', slice_list)
402
433
  """
403
434
  ds = xr.open_dataset(ncfile)
404
435
  slice_list = np.array(slice_list).flatten()
@@ -410,4 +441,4 @@ def nc_isel(ncfile, dim_name, slice_list):
410
441
 
411
442
  if __name__ == "__main__":
412
443
  data = np.random.rand(100, 50)
413
- write2nc(r"test.nc", data, "data", {"time": np.linspace(0, 120, 100), "lev": np.linspace(0, 120, 50)}, "a")
444
+ save(r"test.nc", data, "data", {"time": np.linspace(0, 120, 100), "lev": np.linspace(0, 120, 50)}, "a")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: oafuncs
3
- Version: 0.0.84
3
+ Version: 0.0.86
4
4
  Summary: My short description for my project.
5
5
  Home-page: https://github.com/Industry-Pays/OAFuncs
6
6
  Author: Kun Liu
@@ -1,12 +1,12 @@
1
1
  oafuncs/__init__.py,sha256=glcIlhQ9xSK4WtL58dq7Od2S3JPqsuEyhUQ-VWO8hOc,1426
2
- oafuncs/oa_cmap.py,sha256=rURQujDWzydNVtXOanDtChD248_bapubNsO2dX3Nb-E,6466
3
- oafuncs/oa_data.py,sha256=DUKc--EyQfIcxAwy2Rv_oDMuE5uw9CVrt0bMAfVog98,12482
4
- oafuncs/oa_draw.py,sha256=cZG4XfHEk2IoyBEQqkWat2CWbuyI7utFU9X4NGFEhuA,21250
2
+ oafuncs/oa_cmap.py,sha256=azVg9QR_IlG9lXCCXXVs1LS1kFci8yjxDmb_VA_TdTQ,7408
3
+ oafuncs/oa_data.py,sha256=2MkWCsESVPjZPnLnbQIwrBJUhcF9x-WXbZhni3I44ss,15617
4
+ oafuncs/oa_draw.py,sha256=PUk8DdGBUapCXrOVQ-d_DD6EccB_eHAX3r6jwrnQTk8,11126
5
5
  oafuncs/oa_file.py,sha256=-AdRnFEtRTpIMXr5geYe5fEhyiMOFad5ethi_lF-Ogo,12277
6
- oafuncs/oa_help.py,sha256=BFLoOyD5uVeOc8qQ3yAyzIR1q3JAj4GhqQfetd3KML4,1034
7
- oafuncs/oa_nc.py,sha256=Gj0xLfqgQI3hNnr9SED1WFj2JU4GsJj2on_8EVdSk20,15595
6
+ oafuncs/oa_help.py,sha256=zQEYXFn6eCiEgzSy_gSjhdP3u-KRK4Hl-iGIvPC8EAs,3729
7
+ oafuncs/oa_nc.py,sha256=OeWtv__oPsLNLBS6mOIUCvb8X9GEj4qjjc10lJE-IHE,16432
8
8
  oafuncs/oa_python.py,sha256=XPTP3o7zTFzfJR_YhsKfQksa3bSYwXsne9YxlJplCEA,3994
9
- oafuncs/data_store/OAFuncs.png,sha256=C6_1718zWoEvs3QRSt8eWhRedDV4QIhQUKk3LWb1Z6Y,3298028
9
+ oafuncs/data_store/OAFuncs.png,sha256=w2pR7MUyeeWrT8BVTSy40EIRDIrfpdo1QvWvvjLOgjM,3258809
10
10
  oafuncs/oa_down/User_Agent-list.txt,sha256=pazxSip8_lphEBOPHG902zmIBUg8sBKXgmqp_g6j_E4,661062
11
11
  oafuncs/oa_down/__init__.py,sha256=pKPqxD0z09NEXWCemuemfgTct7Kcu3APPJqqB1FPXRM,565
12
12
  oafuncs/oa_down/hycom_3hourly.py,sha256=wYOZrV5mZVSTfx6a5QLay8Jg2sL2x3sWKWmxwidRzMo,62928
@@ -19,8 +19,8 @@ oafuncs/oa_sign/ocean.py,sha256=xrW-rWD7xBWsB5PuCyEwQ1Q_RDKq2KCLz-LOONHgldU,5932
19
19
  oafuncs/oa_sign/scientific.py,sha256=a4JxOBgm9vzNZKpJ_GQIQf7cokkraV5nh23HGbmTYKw,5064
20
20
  oafuncs/oa_tool/__init__.py,sha256=IKOlqpWlb4cMDCtq2VKR_RTxQHDNqR_vfqqsOsp_lKQ,466
21
21
  oafuncs/oa_tool/email.py,sha256=4lJxV_KUzhxgLYfVwYTqp0qxRugD7fvsZkXDe5WkUKo,3052
22
- oafuncs-0.0.84.dist-info/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
23
- oafuncs-0.0.84.dist-info/METADATA,sha256=2RgGeH47uDoGAB9Ql0I8CT7AzG3DoMb6xDPDp7NxyCE,3303
24
- oafuncs-0.0.84.dist-info/WHEEL,sha256=pxeNX5JdtCe58PUSYP9upmc7jdRPgvT0Gm9kb1SHlVw,109
25
- oafuncs-0.0.84.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
26
- oafuncs-0.0.84.dist-info/RECORD,,
22
+ oafuncs-0.0.86.dist-info/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
23
+ oafuncs-0.0.86.dist-info/METADATA,sha256=Bg1Cg7-c-UUc0gGBDqR3HsrbnK6Sz5JgEKz3vdz9SzA,3303
24
+ oafuncs-0.0.86.dist-info/WHEEL,sha256=pxeNX5JdtCe58PUSYP9upmc7jdRPgvT0Gm9kb1SHlVw,109
25
+ oafuncs-0.0.86.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
26
+ oafuncs-0.0.86.dist-info/RECORD,,