oafuncs 0.0.85__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.
- oafuncs/data_store/OAFuncs.png +0 -0
- oafuncs/oa_cmap.py +96 -47
- oafuncs/oa_data.py +88 -4
- oafuncs/oa_draw.py +64 -252
- oafuncs/oa_help.py +86 -5
- oafuncs/oa_nc.py +50 -19
- {oafuncs-0.0.85.dist-info → oafuncs-0.0.86.dist-info}/METADATA +1 -1
- {oafuncs-0.0.85.dist-info → oafuncs-0.0.86.dist-info}/RECORD +11 -11
- {oafuncs-0.0.85.dist-info → oafuncs-0.0.86.dist-info}/LICENSE.txt +0 -0
- {oafuncs-0.0.85.dist-info → oafuncs-0.0.86.dist-info}/WHEEL +0 -0
- {oafuncs-0.0.85.dist-info → oafuncs-0.0.86.dist-info}/top_level.txt +0 -0
oafuncs/data_store/OAFuncs.png
CHANGED
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", "
|
21
|
+
__all__ = ["show", "to_color", "create", "create_rgbtxt", "get"]
|
21
22
|
|
22
23
|
# ** 将cmap用填色图可视化(官网摘抄函数)
|
23
|
-
def show(colormaps
|
24
|
+
def show(colormaps):
|
24
25
|
"""
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
47
|
+
def to_color(cmap, n=256):
|
42
48
|
"""
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
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
|
65
|
+
def create(colors: list, nodes=None, under=None, over=None): # 利用颜色快速配色
|
55
66
|
"""
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
93
|
+
def create_rgbtxt(rgbtxt_file,split_mark=','): # 根据RGB的txt文档制作色卡/根据rgb值制作
|
77
94
|
"""
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
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: #
|
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
|
-
|
100
|
-
return
|
129
|
+
my_cmap = mpl.colors.ListedColormap(rgb, name="my_color")
|
130
|
+
return my_cmap
|
101
131
|
|
102
132
|
|
103
133
|
# ** 选择cmap
|
104
|
-
def
|
134
|
+
def get(cmap_name=None, query=False):
|
105
135
|
"""
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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":
|
114
|
-
"cold_1":
|
115
|
-
"warm_1":
|
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":
|
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 =
|
201
|
+
c_map = create(colors, nodes)
|
153
202
|
show([c_map])
|
154
203
|
|
155
204
|
# ** 测试自制diverging型cmap
|
156
|
-
diverging_cmap =
|
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 =
|
210
|
+
cmap_rgb = create_rgbtxt(file_path)
|
162
211
|
|
163
212
|
# ** 测试将cmap转为list
|
164
|
-
out_colors =
|
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
|
-
|
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
|
-
|
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", "
|
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
|
78
|
+
def gif(image_list: list, gif_name: str, duration=0.2): # 制作动图,默认间隔0.2
|
80
79
|
"""
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
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,7 +152,6 @@ 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)
|
@@ -201,141 +202,68 @@ class MidpointNormalize(mpl.colors.Normalize):
|
|
201
202
|
|
202
203
|
# -----------------------------------------------------------------------------------------------------------------------------------------------------------------
|
203
204
|
|
204
|
-
|
205
|
-
|
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
|
-
|
240
|
-
|
241
|
-
param
|
242
|
-
param
|
243
|
-
param
|
244
|
-
param
|
245
|
-
param
|
246
|
-
param
|
247
|
-
param
|
248
|
-
|
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
|
-
|
251
|
-
if
|
252
|
-
|
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
|
-
|
255
|
-
|
256
|
-
|
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
|
235
|
+
# ** 绘制等值线图
|
236
|
+
def contour(data, x=None, y=None, cmap="coolwarm", show=True, store=None, cartopy=False):
|
297
237
|
"""
|
298
|
-
|
299
|
-
|
300
|
-
param
|
301
|
-
param
|
302
|
-
param
|
303
|
-
param
|
304
|
-
|
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
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
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
|
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:
|
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
|
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(
|
58
|
+
print(getattr(module, func).__module__ + "." + func)
|
41
59
|
print("函数提示:")
|
42
|
-
print(getattr(
|
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", "
|
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
|
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 =
|
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
|
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:
|
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
|
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
|
-
|
192
|
-
|
193
|
-
|
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
|
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:
|
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
|
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:
|
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
|
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:
|
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
|
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("
|
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
|
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
|
-
|
444
|
+
save(r"test.nc", data, "data", {"time": np.linspace(0, 120, 100), "lev": np.linspace(0, 120, 50)}, "a")
|
@@ -1,12 +1,12 @@
|
|
1
1
|
oafuncs/__init__.py,sha256=glcIlhQ9xSK4WtL58dq7Od2S3JPqsuEyhUQ-VWO8hOc,1426
|
2
|
-
oafuncs/oa_cmap.py,sha256=
|
3
|
-
oafuncs/oa_data.py,sha256=
|
4
|
-
oafuncs/oa_draw.py,sha256=
|
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=
|
7
|
-
oafuncs/oa_nc.py,sha256=
|
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=
|
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.
|
23
|
-
oafuncs-0.0.
|
24
|
-
oafuncs-0.0.
|
25
|
-
oafuncs-0.0.
|
26
|
-
oafuncs-0.0.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|