oafuncs 0.0.97.12__py3-none-any.whl → 0.0.97.14__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/_script/cprogressbar.py +350 -57
- oafuncs/{oa_tool → _script}/email.py +26 -24
- oafuncs/_script/netcdf_merge.py +83 -330
- oafuncs/{oa_tool → _script}/parallel.py +5 -3
- oafuncs/oa_data.py +3 -24
- oafuncs/oa_date.py +24 -2
- oafuncs/oa_down/hycom_3hourly.py +39 -25
- oafuncs/oa_down/idm.py +5 -3
- oafuncs/oa_draw.py +8 -2
- oafuncs/oa_nc.py +35 -38
- oafuncs/oa_tool.py +83 -0
- {oafuncs-0.0.97.12.dist-info → oafuncs-0.0.97.14.dist-info}/METADATA +1 -1
- {oafuncs-0.0.97.12.dist-info → oafuncs-0.0.97.14.dist-info}/RECORD +16 -17
- oafuncs/_script/auto_optimized_parallel_executor.py +0 -459
- oafuncs/oa_tool/__init__.py +0 -7
- {oafuncs-0.0.97.12.dist-info → oafuncs-0.0.97.14.dist-info}/WHEEL +0 -0
- {oafuncs-0.0.97.12.dist-info → oafuncs-0.0.97.14.dist-info}/licenses/LICENSE.txt +0 -0
- {oafuncs-0.0.97.12.dist-info → oafuncs-0.0.97.14.dist-info}/top_level.txt +0 -0
oafuncs/oa_down/hycom_3hourly.py
CHANGED
@@ -13,9 +13,6 @@ SystemInfo: Windows 11
|
|
13
13
|
Python Version: 3.12
|
14
14
|
"""
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
16
|
import datetime
|
20
17
|
import os
|
21
18
|
import random
|
@@ -711,13 +708,13 @@ def _download_file(target_url, store_path, file_name, check=False):
|
|
711
708
|
file_name_split = file_name_split[:-1]
|
712
709
|
# same_file = f"{file_name_split[0]}_{file_name_split[1]}*nc"
|
713
710
|
same_file = "_".join(file_name_split) + "*nc"
|
714
|
-
|
711
|
+
|
715
712
|
if match_time is not None:
|
716
713
|
if check_nc(fname):
|
717
714
|
if not _check_ftime(fname, if_print=True):
|
718
715
|
if match_time:
|
719
716
|
_correct_time(fname)
|
720
|
-
count_dict[
|
717
|
+
count_dict["skip"] += 1
|
721
718
|
else:
|
722
719
|
_clear_existing_file(fname)
|
723
720
|
# print(f"[bold #ffe5c0]File time error, {fname}")
|
@@ -997,7 +994,7 @@ def _done_callback(future, progress, task, total, counter_lock):
|
|
997
994
|
global parallel_counter
|
998
995
|
with counter_lock:
|
999
996
|
parallel_counter += 1
|
1000
|
-
progress.update(task, advance=1, description=f"[cyan]
|
997
|
+
progress.update(task, advance=1, description=f"[cyan]{bar_desc} {parallel_counter}/{total}")
|
1001
998
|
|
1002
999
|
|
1003
1000
|
def _download_hourly_func(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_min=-80, lat_max=90, depth=None, level=None, store_path=None, dataset_name=None, version_name=None, num_workers=None, check=False, ftimes=1, interval_hour=3):
|
@@ -1034,19 +1031,19 @@ def _download_hourly_func(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_mi
|
|
1034
1031
|
print("Downloading a series of files...")
|
1035
1032
|
time_list = get_time_list(ymdh_time_s, ymdh_time_e, interval_hour, "hour")
|
1036
1033
|
with Progress() as progress:
|
1037
|
-
task = progress.add_task("[cyan]
|
1034
|
+
task = progress.add_task(f"[cyan]{bar_desc}", total=len(time_list))
|
1038
1035
|
if ftimes == 1:
|
1039
1036
|
if num_workers is None or num_workers <= 1:
|
1040
1037
|
# 串行方式
|
1041
1038
|
for i, time_str in enumerate(time_list):
|
1042
1039
|
_prepare_url_to_download(var, lon_min, lon_max, lat_min, lat_max, time_str, None, depth, level, store_path, dataset_name, version_name, check)
|
1043
|
-
progress.update(task, advance=1, description=f"[cyan]
|
1040
|
+
progress.update(task, advance=1, description=f"[cyan]{bar_desc} {i + 1}/{len(time_list)}")
|
1044
1041
|
else:
|
1045
1042
|
# 并行方式
|
1046
1043
|
with ThreadPoolExecutor(max_workers=num_workers) as executor:
|
1047
1044
|
futures = [executor.submit(_download_task, var, time_str, None, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, check) for time_str in time_list]
|
1048
1045
|
""" for i, future in enumerate(futures):
|
1049
|
-
future.add_done_callback(lambda _: progress.update(task, advance=1, description=f"[cyan]
|
1046
|
+
future.add_done_callback(lambda _: progress.update(task, advance=1, description=f"[cyan]{bar_desc} {i+1}/{len(time_list)}")) """
|
1050
1047
|
for feature in as_completed(futures):
|
1051
1048
|
_done_callback(feature, progress, task, len(time_list), counter_lock)
|
1052
1049
|
else:
|
@@ -1059,13 +1056,13 @@ def _download_hourly_func(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_mi
|
|
1059
1056
|
time_str_end_index = int(min(len(time_list) - 1, int(i * ftimes + ftimes - 1)))
|
1060
1057
|
time_str_end = time_list[time_str_end_index]
|
1061
1058
|
_prepare_url_to_download(var, lon_min, lon_max, lat_min, lat_max, time_str, time_str_end, depth, level, store_path, dataset_name, version_name, check)
|
1062
|
-
progress.update(task, advance=1, description=f"[cyan]
|
1059
|
+
progress.update(task, advance=1, description=f"[cyan]{bar_desc} {i + 1}/{total_num}")
|
1063
1060
|
else:
|
1064
1061
|
# 并行方式
|
1065
1062
|
with ThreadPoolExecutor(max_workers=num_workers) as executor:
|
1066
1063
|
futures = [executor.submit(_download_task, var, new_time_list[i], time_list[int(min(len(time_list) - 1, int(i * ftimes + ftimes - 1)))], lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, check) for i in range(total_num)]
|
1067
1064
|
""" for i, future in enumerate(futures):
|
1068
|
-
future.add_done_callback(lambda _: progress.update(task, advance=1, description=f"[cyan]
|
1065
|
+
future.add_done_callback(lambda _: progress.update(task, advance=1, description=f"[cyan]{bar_desc} {i+1}/{total_num}")) """
|
1069
1066
|
for feature in as_completed(futures):
|
1070
1067
|
_done_callback(feature, progress, task, len(time_list), counter_lock)
|
1071
1068
|
else:
|
@@ -1100,6 +1097,9 @@ def download(var, time_s, time_e=None, lon_min=0, lon_max=359.92, lat_min=-80, l
|
|
1100
1097
|
Returns:
|
1101
1098
|
None
|
1102
1099
|
"""
|
1100
|
+
from oafuncs.oa_data import pbar
|
1101
|
+
from oafuncs.oa_cmap import get as get_cmap
|
1102
|
+
|
1103
1103
|
_get_initial_data()
|
1104
1104
|
|
1105
1105
|
# 打印信息并处理数据集和版本名称
|
@@ -1166,57 +1166,71 @@ def download(var, time_s, time_e=None, lon_min=0, lon_max=359.92, lat_min=-80, l
|
|
1166
1166
|
|
1167
1167
|
global fsize_dict_lock
|
1168
1168
|
fsize_dict_lock = Lock()
|
1169
|
-
|
1169
|
+
|
1170
1170
|
if fill_time is not None:
|
1171
1171
|
num_workers = 1
|
1172
1172
|
|
1173
|
-
global use_idm, given_idm_engine, idm_download_list
|
1173
|
+
global use_idm, given_idm_engine, idm_download_list, bar_desc
|
1174
1174
|
if idm_engine is not None:
|
1175
1175
|
use_idm = True
|
1176
1176
|
num_workers = 1
|
1177
1177
|
given_idm_engine = idm_engine
|
1178
1178
|
idm_download_list = []
|
1179
|
+
bar_desc = "Submitting to IDM ..."
|
1179
1180
|
else:
|
1180
1181
|
use_idm = False
|
1182
|
+
bar_desc = "Downloading ..."
|
1181
1183
|
|
1182
1184
|
global match_time
|
1183
1185
|
match_time = fill_time
|
1184
|
-
|
1186
|
+
|
1185
1187
|
global mark_len
|
1186
|
-
mark_len =
|
1188
|
+
mark_len = 100
|
1187
1189
|
|
1188
1190
|
_download_hourly_func(var, time_s, time_e, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, num_workers, check, ftimes, int(interval_hour))
|
1189
1191
|
|
1190
1192
|
if idm_engine is not None:
|
1191
1193
|
print("[bold #ecdbfe]*" * mark_len)
|
1192
|
-
|
1194
|
+
str_info = "All files have been submitted to IDM for downloading"
|
1195
|
+
str_info = str_info.center(mark_len, "*")
|
1196
|
+
print(f"[bold #3dfc40]{str_info}")
|
1193
1197
|
print("[bold #ecdbfe]*" * mark_len)
|
1194
1198
|
if idm_download_list:
|
1195
|
-
file_download_time = 60
|
1196
|
-
for f in idm_download_list:
|
1199
|
+
""" file_download_time = 60 # 预设下载时间为1分钟
|
1200
|
+
for f in pbar(idm_download_list,cmap='bwr',prefix='HYCOM: '):
|
1197
1201
|
file_download_start_time = time.time()
|
1198
1202
|
wait_success = 0
|
1199
1203
|
success = False
|
1200
1204
|
while not success:
|
1201
|
-
if check_nc(f):
|
1205
|
+
if check_nc(f,print_switch=False):
|
1202
1206
|
count_dict["success"] += 1
|
1203
1207
|
success = True
|
1204
|
-
print(f"[bold #3dfc40]File [bold #dfff73]{f} [#3dfc40]has been downloaded successfully")
|
1208
|
+
# print(f"[bold #3dfc40]File [bold #dfff73]{f} [#3dfc40]has been downloaded successfully")
|
1205
1209
|
file_download_end_time = time.time()
|
1206
1210
|
file_download_time = file_download_end_time - file_download_start_time
|
1207
1211
|
file_download_time = int(file_download_time)
|
1208
|
-
print(f"[bold #3dfc40]Time: {file_download_time} seconds")
|
1209
|
-
file_download_time = max(60, file_download_time)
|
1212
|
+
# print(f"[bold #3dfc40]Time: {file_download_time} seconds")
|
1213
|
+
file_download_time = max(60, file_download_time) # 预设下载时间为1分钟起步
|
1210
1214
|
else:
|
1211
1215
|
wait_success += 1
|
1212
|
-
print(f"[bold #ffe5c0]Waiting {file_download_time} seconds to check the file {f}...")
|
1216
|
+
# print(f"[bold #ffe5c0]Waiting {file_download_time} seconds to check the file {f}...")
|
1213
1217
|
time.sleep(file_download_time)
|
1214
1218
|
if wait_success >= 10:
|
1215
1219
|
success = True
|
1216
1220
|
# print(f'{f} download failed')
|
1217
|
-
print(f
|
1221
|
+
print(f"[bold #ffe5c0]Waiting for more than 10 times, skipping the file {f}...")
|
1218
1222
|
count_dict["fail"] += 1
|
1219
|
-
print(
|
1223
|
+
# print("[bold #ecdbfe]-" * mark_len) """
|
1224
|
+
remain_list = idm_download_list.copy()
|
1225
|
+
for f_count in pbar(range(len(idm_download_list)), cmap=get_cmap('diverging_1'), prefix="HYCOM: "):
|
1226
|
+
success = False
|
1227
|
+
while not success:
|
1228
|
+
for f in remain_list:
|
1229
|
+
if check_nc(f, print_switch=False):
|
1230
|
+
count_dict["success"] += 1
|
1231
|
+
success = True
|
1232
|
+
remain_list.remove(f)
|
1233
|
+
break
|
1220
1234
|
|
1221
1235
|
count_dict["total"] = count_dict["success"] + count_dict["fail"] + count_dict["skip"] + count_dict["no_data"]
|
1222
1236
|
print("[bold #ecdbfe]=" * mark_len)
|
oafuncs/oa_down/idm.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
Author: Liu Kun && 16031215@qq.com
|
5
5
|
Date: 2025-03-27 16:51:26
|
6
6
|
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
-
LastEditTime: 2025-04-01
|
7
|
+
LastEditTime: 2025-04-01 22:31:39
|
8
8
|
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_down\\idm.py
|
9
9
|
Description:
|
10
10
|
EditPlatform: vscode
|
@@ -13,9 +13,11 @@ SystemInfo: Windows 11
|
|
13
13
|
Python Version: 3.12
|
14
14
|
"""
|
15
15
|
|
16
|
+
|
16
17
|
import datetime
|
17
18
|
import os
|
18
19
|
from subprocess import call
|
20
|
+
|
19
21
|
from rich import print
|
20
22
|
|
21
23
|
__all__ = ["downloader"]
|
@@ -50,6 +52,6 @@ def downloader(task_url, folder_path, file_name, idm_engine=r"D:\Programs\Intern
|
|
50
52
|
time_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
51
53
|
time_str = time_str.center(100, " ")
|
52
54
|
print(f"[bold purple]{time_str}")
|
53
|
-
print(f"[green]IDM Downloader: {file_name} download task has been added to the queue...[/green]")
|
55
|
+
print(f"[green]IDM Downloader: {file_name} download task has been added to the queue ...[/green]")
|
54
56
|
print("[purple]*" * 100)
|
55
|
-
print(
|
57
|
+
print("\n")
|
oafuncs/oa_draw.py
CHANGED
@@ -165,13 +165,19 @@ def add_lonlat_unit(lon=None, lat=None, decimal=2):
|
|
165
165
|
|
166
166
|
|
167
167
|
# ** 添加网格线
|
168
|
-
def add_gridlines(ax, projection=ccrs.PlateCarree(), color="k", alpha=0.5, linestyle="--", linewidth=0.5):
|
168
|
+
def add_gridlines(ax, xline=None, yline=None, projection=ccrs.PlateCarree(), color="k", alpha=0.5, linestyle="--", linewidth=0.5):
|
169
|
+
from matplotlib import ticker as mticker
|
169
170
|
# add gridlines
|
170
171
|
gl = ax.gridlines(crs=projection, draw_labels=True, linewidth=linewidth, color=color, alpha=alpha, linestyle=linestyle)
|
171
172
|
gl.right_labels = False
|
172
173
|
gl.top_labels = False
|
173
174
|
gl.xformatter = LongitudeFormatter(zero_direction_label=False)
|
174
175
|
gl.yformatter = LatitudeFormatter()
|
176
|
+
|
177
|
+
if xline is not None:
|
178
|
+
gl.xlocator = mticker.FixedLocator(np.array(xline))
|
179
|
+
if yline is not None:
|
180
|
+
gl.ylocator = mticker.FixedLocator(np.array(yline))
|
175
181
|
|
176
182
|
return ax, gl
|
177
183
|
|
@@ -186,7 +192,7 @@ def add_cartopy(ax, lon=None, lat=None, projection=ccrs.PlateCarree(), gridlines
|
|
186
192
|
|
187
193
|
# add gridlines
|
188
194
|
if gridlines:
|
189
|
-
ax, gl = add_gridlines(ax, projection)
|
195
|
+
ax, gl = add_gridlines(ax, projection=projection)
|
190
196
|
|
191
197
|
# set longitude and latitude format
|
192
198
|
lon_formatter = LongitudeFormatter(zero_direction_label=False)
|
oafuncs/oa_nc.py
CHANGED
@@ -14,12 +14,12 @@ Python Version: 3.11
|
|
14
14
|
"""
|
15
15
|
|
16
16
|
import os
|
17
|
+
from typing import List, Optional, Union
|
17
18
|
|
18
19
|
import netCDF4 as nc
|
19
20
|
import numpy as np
|
20
21
|
import xarray as xr
|
21
22
|
from rich import print
|
22
|
-
from typing import Dict, List, Union
|
23
23
|
|
24
24
|
__all__ = ["get_var", "extract", "save", "merge", "modify", "rename", "check", "convert_longitude", "isel", "draw"]
|
25
25
|
|
@@ -136,7 +136,18 @@ def save(file, data, varname=None, coords=None, mode="w", scale_offset_switch=Tr
|
|
136
136
|
with nc.Dataset(file, mode, format="NETCDF4") as ncfile:
|
137
137
|
# 如果 data 是 DataArray 并且没有提供 varname 和 coords
|
138
138
|
if varname is None and coords is None and isinstance(data, xr.DataArray):
|
139
|
-
|
139
|
+
encoding = {}
|
140
|
+
for var in data.data_vars:
|
141
|
+
scale_factor, add_offset = _calculate_scale_and_offset(data[var].values)
|
142
|
+
encoding[var] = {
|
143
|
+
"zlib": True,
|
144
|
+
"complevel": 4,
|
145
|
+
"dtype": "int16",
|
146
|
+
"scale_factor": scale_factor,
|
147
|
+
"add_offset": add_offset,
|
148
|
+
"_FillValue": -32767,
|
149
|
+
}
|
150
|
+
data.to_netcdf(file, mode=mode, encoding=encoding)
|
140
151
|
return
|
141
152
|
|
142
153
|
# 添加坐标
|
@@ -182,29 +193,10 @@ def save(file, data, varname=None, coords=None, mode="w", scale_offset_switch=Tr
|
|
182
193
|
var.setncattr(key, value)
|
183
194
|
|
184
195
|
|
185
|
-
def merge(file_list: Union[str, List[str]], var_name: Union[str, List[str]
|
186
|
-
|
187
|
-
NetCDF合并函数
|
188
|
-
|
189
|
-
Parameters:
|
190
|
-
file_list: 文件路径列表或单个文件路径
|
191
|
-
var_name: 需要合并的变量(单个变量名/变量列表/None表示全部)
|
192
|
-
dim_name: 合并维度,默认为'time'
|
193
|
-
target_filename: 输出文件路径
|
194
|
-
chunk_config: Dask分块配置,如{"time": 1000}
|
195
|
-
compression: 压缩配置(True启用默认压缩,或自定义编码字典)
|
196
|
-
sanity_check: 是否执行数据完整性校验
|
197
|
-
overwrite: 是否覆盖已存在文件
|
198
|
-
parallel: 是否启用并行处理
|
196
|
+
def merge(file_list: Union[str, List[str]], var_name: Optional[Union[str, List[str]]] = None, dim_name: Optional[str] = None, target_filename: Optional[str] = None) -> None:
|
197
|
+
from ._script.netcdf_merge import merge_nc
|
199
198
|
|
200
|
-
|
201
|
-
merge(["data1.nc", "data2.nc"],
|
202
|
-
var_name=["temp", "salt"],
|
203
|
-
target_filename="result.nc",
|
204
|
-
chunk_config={"time": 500})
|
205
|
-
"""
|
206
|
-
from ._script.netcdf_merge import merge as nc_merge
|
207
|
-
nc_merge(file_list, var_name, dim_name, target_filename, chunk_config, compression, sanity_check, overwrite, parallel)
|
199
|
+
merge_nc(file_list, var_name, dim_name, target_filename)
|
208
200
|
|
209
201
|
|
210
202
|
def _modify_var(nc_file_path, variable_name, new_value):
|
@@ -230,8 +222,7 @@ def _modify_var(nc_file_path, variable_name, new_value):
|
|
230
222
|
variable = dataset.variables[variable_name]
|
231
223
|
# Check if the shape of the new value matches the variable's shape
|
232
224
|
if variable.shape != new_value.shape:
|
233
|
-
raise ValueError(f"Shape mismatch: Variable '{variable_name}' has shape {variable.shape}, "
|
234
|
-
f"but new value has shape {new_value.shape}.")
|
225
|
+
raise ValueError(f"Shape mismatch: Variable '{variable_name}' has shape {variable.shape}, but new value has shape {new_value.shape}.")
|
235
226
|
# Modify the value of the variable
|
236
227
|
variable[:] = new_value
|
237
228
|
print(f"Successfully modified variable '{variable_name}' in '{nc_file_path}'.")
|
@@ -264,8 +255,7 @@ def _modify_attr(nc_file_path, variable_name, attribute_name, attribute_value):
|
|
264
255
|
variable.setncattr(attribute_name, attribute_value)
|
265
256
|
print(f"Successfully modified attribute '{attribute_name}' of variable '{variable_name}' in '{nc_file_path}'.")
|
266
257
|
except Exception as e:
|
267
|
-
print(f"[red]Error:[/red] Failed to modify attribute '{attribute_name}' of variable '{variable_name}' "
|
268
|
-
f"in file '{nc_file_path}'. [bold]Details:[/bold] {e}")
|
258
|
+
print(f"[red]Error:[/red] Failed to modify attribute '{attribute_name}' of variable '{variable_name}' in file '{nc_file_path}'. [bold]Details:[/bold] {e}")
|
269
259
|
|
270
260
|
|
271
261
|
def modify(nc_file, var_name, attr_name=None, new_value=None):
|
@@ -328,7 +318,7 @@ def rename(ncfile_path, old_name, new_name):
|
|
328
318
|
print(f"An error occurred: {e}")
|
329
319
|
|
330
320
|
|
331
|
-
def check(ncfile: str, delete_switch: bool = False) -> bool:
|
321
|
+
def check(ncfile: str, delete_switch: bool = False, print_switch: bool = True) -> bool:
|
332
322
|
"""
|
333
323
|
Check if a NetCDF file is corrupted with enhanced error handling.
|
334
324
|
|
@@ -337,9 +327,10 @@ def check(ncfile: str, delete_switch: bool = False) -> bool:
|
|
337
327
|
is_valid = False
|
338
328
|
|
339
329
|
if not os.path.exists(ncfile):
|
340
|
-
|
341
|
-
|
342
|
-
|
330
|
+
if print_switch:
|
331
|
+
print(f"[#ffeac5]Local file missing: [#009d88]{ncfile}")
|
332
|
+
# 提示:提示文件缺失也许是正常的,这只是检查文件是否存在于本地
|
333
|
+
print("[#d6d9fd]Note: File missing may be normal, this is just to check if the file exists locally.")
|
343
334
|
return False
|
344
335
|
|
345
336
|
try:
|
@@ -352,7 +343,8 @@ def check(ncfile: str, delete_switch: bool = False) -> bool:
|
|
352
343
|
# 二次验证确保变量可访问
|
353
344
|
with nc.Dataset(ncfile, "r") as ds_verify:
|
354
345
|
if not ds_verify.variables:
|
355
|
-
|
346
|
+
if print_switch:
|
347
|
+
print(f"[red]Empty variables: {ncfile}[/red]")
|
356
348
|
else:
|
357
349
|
# 尝试访问元数据
|
358
350
|
_ = ds_verify.__dict__
|
@@ -363,19 +355,23 @@ def check(ncfile: str, delete_switch: bool = False) -> bool:
|
|
363
355
|
is_valid = True
|
364
356
|
|
365
357
|
except Exception as e: # 捕获所有异常类型
|
366
|
-
|
358
|
+
if print_switch:
|
359
|
+
print(f"[red]HDF5 validation failed for {ncfile}: {str(e)}[/red]")
|
367
360
|
error_type = type(e).__name__
|
368
361
|
if "HDF5" in error_type or "h5" in error_type.lower():
|
369
|
-
|
362
|
+
if print_switch:
|
363
|
+
print(f"[red]Critical HDF5 structure error detected in {ncfile}[/red]")
|
370
364
|
|
371
365
|
# 安全删除流程
|
372
366
|
if not is_valid:
|
373
367
|
if delete_switch:
|
374
368
|
try:
|
375
369
|
os.remove(ncfile)
|
376
|
-
|
370
|
+
if print_switch:
|
371
|
+
print(f"[red]Removed corrupted file: {ncfile}[/red]")
|
377
372
|
except Exception as del_error:
|
378
|
-
|
373
|
+
if print_switch:
|
374
|
+
print(f"[red]Failed to delete corrupted file: {ncfile} - {str(del_error)}[/red]")
|
379
375
|
return False
|
380
376
|
|
381
377
|
return True
|
@@ -429,7 +425,7 @@ def isel(ncfile, dim_name, slice_list):
|
|
429
425
|
return ds_new
|
430
426
|
|
431
427
|
|
432
|
-
def draw(output_dir=None, dataset=None, ncfile=None, xyzt_dims=("longitude", "latitude", "level", "time"), plot_type="contourf",fixed_colorscale=False):
|
428
|
+
def draw(output_dir=None, dataset=None, ncfile=None, xyzt_dims=("longitude", "latitude", "level", "time"), plot_type="contourf", fixed_colorscale=False):
|
433
429
|
"""
|
434
430
|
Description:
|
435
431
|
Draw the data in the netCDF file
|
@@ -448,6 +444,7 @@ def draw(output_dir=None, dataset=None, ncfile=None, xyzt_dims=("longitude", "la
|
|
448
444
|
draw(ncfile, output_dir, x_dim="longitude", y_dim="latitude", z_dim="level", t_dim="time", fixed_colorscale=False)
|
449
445
|
"""
|
450
446
|
from ._script.plot_dataset import func_plot_dataset
|
447
|
+
|
451
448
|
if output_dir is None:
|
452
449
|
output_dir = str(os.getcwd())
|
453
450
|
if isinstance(xyzt_dims, (list, tuple)):
|
oafuncs/oa_tool.py
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env python
|
2
|
+
# coding=utf-8
|
3
|
+
"""
|
4
|
+
Author: Liu Kun && 16031215@qq.com
|
5
|
+
Date: 2025-04-04 20:17:42
|
6
|
+
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
+
LastEditTime: 2025-04-04 20:17:45
|
8
|
+
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_tool.py
|
9
|
+
Description:
|
10
|
+
EditPlatform: vscode
|
11
|
+
ComputerInfo: XPS 15 9510
|
12
|
+
SystemInfo: Windows 11
|
13
|
+
Python Version: 3.12
|
14
|
+
"""
|
15
|
+
from typing import Iterable
|
16
|
+
|
17
|
+
__all__ = ["PEx", "email", "pbar"]
|
18
|
+
|
19
|
+
class PEx:
|
20
|
+
"""
|
21
|
+
PEx 封装了 ParallelExecutor,
|
22
|
+
并将其方法全部委托,使得直接调用 PEx 的方法能够达到与 ParallelExecutor 相同的效果。
|
23
|
+
|
24
|
+
示例:
|
25
|
+
# 创建 PEx 实例
|
26
|
+
executor = PEx(max_workers=4)
|
27
|
+
|
28
|
+
# 使用 run 方法执行并行任务
|
29
|
+
result = executor.run(lambda x: x * x, [(i,) for i in range(5)])
|
30
|
+
print(result) # 输出: [0, 1, 4, 9, 16]
|
31
|
+
"""
|
32
|
+
|
33
|
+
try:
|
34
|
+
from ._script.parallel import ParallelExecutor
|
35
|
+
except ImportError:
|
36
|
+
raise ImportError("ParallelExecutor could not be imported. Ensure the module '_script.parallel' exists and is accessible.")
|
37
|
+
|
38
|
+
def __init__(self, *args, **kwargs):
|
39
|
+
"""
|
40
|
+
初始化 PEx 实例,内部创建一个 ParallelExecutor 实例。
|
41
|
+
|
42
|
+
参数:
|
43
|
+
*args: 传递给 ParallelExecutor 的位置参数。
|
44
|
+
**kwargs: 传递给 ParallelExecutor 的关键字参数。
|
45
|
+
"""
|
46
|
+
self.executor = self.ParallelExecutor(*args, **kwargs)
|
47
|
+
|
48
|
+
def __getattr__(self, attr):
|
49
|
+
"""
|
50
|
+
将所有未定义的属性访问委托给内部的 ParallelExecutor 实例。
|
51
|
+
|
52
|
+
参数:
|
53
|
+
attr (str): 要访问的属性名称。
|
54
|
+
|
55
|
+
返回:
|
56
|
+
对应属性的值。
|
57
|
+
"""
|
58
|
+
return getattr(self.executor, attr)
|
59
|
+
|
60
|
+
|
61
|
+
def email(title="Title", content=None, send_to="16031215@qq.com"):
|
62
|
+
from ._script.email import send
|
63
|
+
send(title, content, send_to)
|
64
|
+
|
65
|
+
|
66
|
+
def pbar(iterable: Iterable, description: str = "Working ...", color: str = "cyan", cmap: str = None, lupdate_interval: float = 0.1, bar_length: int = None, **kwargs) -> Iterable:
|
67
|
+
"""
|
68
|
+
快速创建进度条的封装函数
|
69
|
+
:param iterable: 可迭代对象
|
70
|
+
:param prefix: 进度条前缀
|
71
|
+
:param color: 基础颜色
|
72
|
+
:param cmap: 渐变色名称
|
73
|
+
:param kwargs: 其他ColorProgressBar支持的参数
|
74
|
+
|
75
|
+
example:
|
76
|
+
from oafuncs.oa_data import pbar
|
77
|
+
from time import sleep
|
78
|
+
for i in pbar(range(100), prefix="Processing", color="green", cmap="viridis"):
|
79
|
+
sleep(0.1)
|
80
|
+
"""
|
81
|
+
from ._script.cprogressbar import ColorProgressBar
|
82
|
+
|
83
|
+
return ColorProgressBar(iterable=iterable, description=description, color=color, cmap=cmap, update_interval=lupdate_interval, bar_length=bar_length, **kwargs)
|
@@ -1,24 +1,26 @@
|
|
1
1
|
oafuncs/__init__.py,sha256=T_-VtnWWllV3Q91twT5Yt2sUapeA051QbPNnBxmg9nw,1456
|
2
2
|
oafuncs/oa_cmap.py,sha256=OfJ2DOBOGX5X1GihE6CPcTV8bAFdDqJSXV7vbqUgV9s,7552
|
3
|
-
oafuncs/oa_data.py,sha256=
|
4
|
-
oafuncs/oa_date.py,sha256
|
5
|
-
oafuncs/oa_draw.py,sha256=
|
3
|
+
oafuncs/oa_data.py,sha256=j_z4dOgugqyxc9STMTMZ0hKA46RyWgNtJeVWFaC8LPc,12141
|
4
|
+
oafuncs/oa_date.py,sha256=JnXZV1_kb0NO9vRHBOPJBDGV67JkYfMalavGfCGyr0I,3826
|
5
|
+
oafuncs/oa_draw.py,sha256=mpDiyVMi8-CDfbWWnuE8uXt0aShpW_7AgiBDkb1Mrvk,12571
|
6
6
|
oafuncs/oa_file.py,sha256=nYTsMataaC790lSqxjuMB4uVqUJz_tMm_kRve4CHql4,17235
|
7
7
|
oafuncs/oa_help.py,sha256=loyzTbjU_0VpSIBvAEUA_tqxG8MVsO0xFE_2hgQ3zMw,4188
|
8
|
-
oafuncs/oa_nc.py,sha256=
|
8
|
+
oafuncs/oa_nc.py,sha256=Ba1weu1lA6YUkmZ676z2iK1WAwX95cr4_DRrskoDTjo,18477
|
9
9
|
oafuncs/oa_python.py,sha256=Q-6UGGw_dJff7Ef8i87fsLPoGeHV5jBzfb-7HP4THR0,4018
|
10
|
+
oafuncs/oa_tool.py,sha256=8B2cyZ4l3XrWbDMkMKAlvWaiQGP_FKLKVJaqbu6G4uU,2782
|
10
11
|
oafuncs/_data/OAFuncs.png,sha256=y1_x-mUP3gFjcy6m8FqfvQO_HgjzPhQKfXjnSHjslZE,3436152
|
11
12
|
oafuncs/_data/hycom_3hourly.png,sha256=azt_uPcXtl_8CSKRLLPCIf5pPrcxMiOzvoFQnwb0zUo,12411415
|
12
|
-
oafuncs/_script/
|
13
|
-
oafuncs/_script/
|
14
|
-
oafuncs/_script/netcdf_merge.py,sha256=
|
13
|
+
oafuncs/_script/cprogressbar.py,sha256=bDIb99JqCHwIZKsrRXLfqiArTuNUuG9GyestphJM43I,15491
|
14
|
+
oafuncs/_script/email.py,sha256=lL4HGKrr524-g0xLlgs-4u7x4-u7DtgNoD9AL8XJKj4,3058
|
15
|
+
oafuncs/_script/netcdf_merge.py,sha256=KYQ6ulXSjYEmcH5EhGRRZjNrU2uqyQPIaAWljKJdUsk,5088
|
16
|
+
oafuncs/_script/parallel.py,sha256=FS9FgaByq2yb9j6nL-Y0xP1VLvp4USMLBFMRsJDoqeQ,21848
|
15
17
|
oafuncs/_script/parallel_example_usage.py,sha256=uLvE7iwkMn9Cyq6-wk5_RpbQk7PXM9d16-26lTknW9s,2646
|
16
18
|
oafuncs/_script/plot_dataset.py,sha256=zkSEnO_-biyagorwWXPoihts_cwuvripzEt-l9bHJ2E,13989
|
17
19
|
oafuncs/_script/replace_file_concent.py,sha256=eCFZjnZcwyRvy6b4mmIfBna-kylSZTyJRfgXd6DdCjk,5982
|
18
20
|
oafuncs/oa_down/User_Agent-list.txt,sha256=pazxSip8_lphEBOPHG902zmIBUg8sBKXgmqp_g6j_E4,661062
|
19
21
|
oafuncs/oa_down/__init__.py,sha256=kRX5eTUCbAiz3zTaQM1501paOYS_3fizDN4Pa0mtNUA,585
|
20
|
-
oafuncs/oa_down/hycom_3hourly.py,sha256=
|
21
|
-
oafuncs/oa_down/idm.py,sha256=
|
22
|
+
oafuncs/oa_down/hycom_3hourly.py,sha256=uLXKioUQO_UtXtXFa4MWolr4a6AQiI1bf-s7NuQGA-U,67661
|
23
|
+
oafuncs/oa_down/idm.py,sha256=6eKsbGZ91_187_jJawUc6lqKRdUTse6EfUJnlaSl5mo,1903
|
22
24
|
oafuncs/oa_down/literature.py,sha256=2bF9gSKQbzcci9LcKE81j8JEjIJwON7jbwQB3gDDA3E,11331
|
23
25
|
oafuncs/oa_down/test_ua.py,sha256=0IQq3NjqfNr7KkyjS_U-a4mYu-r-E7gzawwo4IfEa6Y,10851
|
24
26
|
oafuncs/oa_down/user_agent.py,sha256=TsPcAxFmMTYAEHRFjurI1bQBJfDhcA70MdHoUPwQmks,785
|
@@ -31,11 +33,8 @@ oafuncs/oa_sign/__init__.py,sha256=QKqTFrJDFK40C5uvk48GlRRbGFzO40rgkYwu6dYxatM,5
|
|
31
33
|
oafuncs/oa_sign/meteorological.py,sha256=mLbupsZSq427HTfVbZMvIlFzDHwSzQAbK3X19o8anFY,6525
|
32
34
|
oafuncs/oa_sign/ocean.py,sha256=xrW-rWD7xBWsB5PuCyEwQ1Q_RDKq2KCLz-LOONHgldU,5932
|
33
35
|
oafuncs/oa_sign/scientific.py,sha256=a4JxOBgm9vzNZKpJ_GQIQf7cokkraV5nh23HGbmTYKw,5064
|
34
|
-
oafuncs/
|
35
|
-
oafuncs/
|
36
|
-
oafuncs/
|
37
|
-
oafuncs-0.0.97.
|
38
|
-
oafuncs-0.0.97.
|
39
|
-
oafuncs-0.0.97.12.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
40
|
-
oafuncs-0.0.97.12.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
|
41
|
-
oafuncs-0.0.97.12.dist-info/RECORD,,
|
36
|
+
oafuncs-0.0.97.14.dist-info/licenses/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
|
37
|
+
oafuncs-0.0.97.14.dist-info/METADATA,sha256=qMRlMGKHZEVI507q3lCtUN_e2rEOohFvXqCeReL6pf0,4226
|
38
|
+
oafuncs-0.0.97.14.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
39
|
+
oafuncs-0.0.97.14.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
|
40
|
+
oafuncs-0.0.97.14.dist-info/RECORD,,
|