oafuncs 0.0.80__py2.py3-none-any.whl → 0.0.82__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oafuncs/__init__.py +27 -12
- oafuncs/oa_cmap.py +31 -52
- oafuncs/oa_data.py +107 -28
- oafuncs/oa_down/hycom_3hourly.py +151 -34
- oafuncs/oa_draw.py +148 -96
- oafuncs/oa_file.py +61 -50
- oafuncs/oa_nc.py +131 -53
- {oafuncs-0.0.80.dist-info → oafuncs-0.0.82.dist-info}/METADATA +1 -2
- oafuncs-0.0.82.dist-info/RECORD +24 -0
- oafuncs-0.0.82.dist-info/top_level.txt +1 -0
- oafuncs/oa_down/test.py +0 -151
- oafuncs/oa_s/__init__.py +0 -23
- oafuncs/oa_s/oa_cmap.py +0 -163
- oafuncs/oa_s/oa_data.py +0 -187
- oafuncs/oa_s/oa_draw.py +0 -451
- oafuncs/oa_s/oa_file.py +0 -332
- oafuncs/oa_s/oa_help.py +0 -39
- oafuncs/oa_s/oa_nc.py +0 -410
- oafuncs/oa_s/oa_python.py +0 -107
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/__init__.py" +0 -26
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_cmap.py" +0 -163
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_data.py" +0 -187
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/__init__.py" +0 -20
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/hycom_3hourly.py" +0 -1176
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/literature.py" +0 -332
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/test_ua.py" +0 -151
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_draw.py" +0 -451
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_file.py" +0 -332
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_help.py" +0 -39
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_nc.py" +0 -410
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_python.py" +0 -107
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/__init__.py" +0 -21
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/meteorological.py" +0 -168
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/ocean.py" +0 -158
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/scientific.py" +0 -139
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/__init__.py" +0 -18
- oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/email.py" +0 -114
- oafuncs-0.0.80.dist-info/RECORD +0 -51
- oafuncs-0.0.80.dist-info/top_level.txt +0 -2
- {oafuncs-0.0.80.dist-info → oafuncs-0.0.82.dist-info}/LICENSE.txt +0 -0
- {oafuncs-0.0.80.dist-info → oafuncs-0.0.82.dist-info}/WHEEL +0 -0
oafuncs/oa_down/hycom_3hourly.py
CHANGED
@@ -21,6 +21,7 @@ import warnings
|
|
21
21
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
22
22
|
from pathlib import Path
|
23
23
|
from threading import Lock
|
24
|
+
import re
|
24
25
|
|
25
26
|
import matplotlib.pyplot as plt
|
26
27
|
import numpy as np
|
@@ -29,6 +30,7 @@ import requests
|
|
29
30
|
from bs4 import BeautifulSoup
|
30
31
|
from rich import print
|
31
32
|
from rich.progress import Progress
|
33
|
+
import glob
|
32
34
|
|
33
35
|
warnings.filterwarnings("ignore", category=RuntimeWarning, message="Engine '.*' loading failed:.*")
|
34
36
|
|
@@ -39,7 +41,7 @@ data_info = {"yearly": {}, "monthly": {}, "daily": {}, "hourly": {}}
|
|
39
41
|
|
40
42
|
# hourly data
|
41
43
|
# dataset: GLBv0.08, GLBu0.08, GLBy0.08
|
42
|
-
data_info["hourly"]["dataset"] = {"GLBv0.08": {}, "GLBu0.08": {}, "GLBy0.08": {}}
|
44
|
+
data_info["hourly"]["dataset"] = {"GLBv0.08": {}, "GLBu0.08": {}, "GLBy0.08": {}, "ESPC_D": {}}
|
43
45
|
|
44
46
|
# version
|
45
47
|
# version of GLBv0.08: 53.X, 56.3, 57.2, 92.8, 57.7, 92.9, 93.0
|
@@ -48,6 +50,8 @@ data_info["hourly"]["dataset"]["GLBv0.08"]["version"] = {"53.X": {}, "56.3": {},
|
|
48
50
|
data_info["hourly"]["dataset"]["GLBu0.08"]["version"] = {"93.0": {}}
|
49
51
|
# version of GLBy0.08: 93.0
|
50
52
|
data_info["hourly"]["dataset"]["GLBy0.08"]["version"] = {"93.0": {}}
|
53
|
+
# version of ESPC_D: V02
|
54
|
+
data_info["hourly"]["dataset"]["ESPC_D"]["version"] = {"V02": {}}
|
51
55
|
|
52
56
|
# info details
|
53
57
|
# time range
|
@@ -65,7 +69,9 @@ data_info["hourly"]["dataset"]["GLBv0.08"]["version"]["93.0"]["time_range"] = {"
|
|
65
69
|
# GLBu0.08
|
66
70
|
data_info["hourly"]["dataset"]["GLBu0.08"]["version"]["93.0"]["time_range"] = {"time_start": "2018091912", "time_end": "2018120909"}
|
67
71
|
# GLBy0.08
|
68
|
-
data_info["hourly"]["dataset"]["GLBy0.08"]["version"]["93.0"]["time_range"] = {"time_start": "2018120412", "time_end": "
|
72
|
+
data_info["hourly"]["dataset"]["GLBy0.08"]["version"]["93.0"]["time_range"] = {"time_start": "2018120412", "time_end": "2024090509"}
|
73
|
+
# ESPC-D
|
74
|
+
data_info["hourly"]["dataset"]["ESPC_D"]["version"]["V02"]["time_range"] = {"time_start": "2024081012", "time_end": "2030010100"}
|
69
75
|
|
70
76
|
# variable
|
71
77
|
variable_info = {
|
@@ -94,6 +100,7 @@ data_info["hourly"]["dataset"]["GLBv0.08"]["version"]["92.9"]["classification"]
|
|
94
100
|
data_info["hourly"]["dataset"]["GLBv0.08"]["version"]["93.0"]["classification"] = "var_different"
|
95
101
|
data_info["hourly"]["dataset"]["GLBu0.08"]["version"]["93.0"]["classification"] = "var_different"
|
96
102
|
data_info["hourly"]["dataset"]["GLBy0.08"]["version"]["93.0"]["classification"] = "var_year_different"
|
103
|
+
data_info["hourly"]["dataset"]["ESPC_D"]["version"]["V02"]["classification"] = "single_var_year_different"
|
97
104
|
|
98
105
|
# download info
|
99
106
|
# base url
|
@@ -141,7 +148,7 @@ data_info["hourly"]["dataset"]["GLBu0.08"]["version"]["93.0"]["url"] = url_930_u
|
|
141
148
|
uv3z_930_y = {}
|
142
149
|
ts3z_930_y = {}
|
143
150
|
ssh_930_y = {}
|
144
|
-
for y_930_y in range(2018,
|
151
|
+
for y_930_y in range(2018, 2025):
|
145
152
|
uv3z_930_y[str(y_930_y)] = rf"https://ncss.hycom.org/thredds/ncss/GLBy0.08/expt_93.0/uv3z/{y_930_y}?"
|
146
153
|
ts3z_930_y[str(y_930_y)] = rf"https://ncss.hycom.org/thredds/ncss/GLBy0.08/expt_93.0/ts3z/{y_930_y}?"
|
147
154
|
ssh_930_y[str(y_930_y)] = rf"https://ncss.hycom.org/thredds/ncss/GLBy0.08/expt_93.0/ssh/{y_930_y}?"
|
@@ -152,12 +159,39 @@ url_930_y = {
|
|
152
159
|
"ssh": ssh_930_y,
|
153
160
|
}
|
154
161
|
data_info["hourly"]["dataset"]["GLBy0.08"]["version"]["93.0"]["url"] = url_930_y
|
162
|
+
# ESPC-D-V02
|
163
|
+
u3z_espc_d_v02_y = {}
|
164
|
+
v3z_espc_d_v02_y = {}
|
165
|
+
t3z_espc_d_v02_y = {}
|
166
|
+
s3z_espc_d_v02_y = {}
|
167
|
+
ssh_espc_d_v02_y = {}
|
168
|
+
for y_espc_d_v02 in range(2024, 2030):
|
169
|
+
u3z_espc_d_v02_y[str(y_espc_d_v02)] = rf"https://ncss.hycom.org/thredds/ncss/ESPC-D-V02/u3z/{y_espc_d_v02}?"
|
170
|
+
v3z_espc_d_v02_y[str(y_espc_d_v02)] = rf"https://ncss.hycom.org/thredds/ncss/ESPC-D-V02/v3z/{y_espc_d_v02}?"
|
171
|
+
t3z_espc_d_v02_y[str(y_espc_d_v02)] = rf"https://ncss.hycom.org/thredds/ncss/ESPC-D-V02/t3z/{y_espc_d_v02}?"
|
172
|
+
s3z_espc_d_v02_y[str(y_espc_d_v02)] = rf"https://ncss.hycom.org/thredds/ncss/ESPC-D-V02/s3z/{y_espc_d_v02}?"
|
173
|
+
ssh_espc_d_v02_y[str(y_espc_d_v02)] = rf"https://ncss.hycom.org/thredds/ncss/ESPC-D-V02/ssh/{y_espc_d_v02}?"
|
174
|
+
url_espc_d_v02_y = {
|
175
|
+
"u3z": u3z_espc_d_v02_y,
|
176
|
+
"v3z": v3z_espc_d_v02_y,
|
177
|
+
"t3z": t3z_espc_d_v02_y,
|
178
|
+
"s3z": s3z_espc_d_v02_y,
|
179
|
+
"ssh": ssh_espc_d_v02_y,
|
180
|
+
}
|
181
|
+
data_info['hourly']['dataset']['ESPC_D']['version']['V02']['url'] = url_espc_d_v02_y
|
155
182
|
|
156
183
|
var_group = {
|
157
184
|
"uv3z": ["u", "v", "u_b", "v_b"],
|
158
185
|
"ts3z": ["temp", "salt", "temp_b", "salt_b"],
|
159
186
|
"ssh": ["ssh"],
|
160
187
|
}
|
188
|
+
single_var_group = {
|
189
|
+
"u3z": ["u"],
|
190
|
+
"v3z": ["v"],
|
191
|
+
"t3z": ["temp"],
|
192
|
+
"s3z": ["salt"],
|
193
|
+
"ssh": ["ssh"],
|
194
|
+
}
|
161
195
|
|
162
196
|
|
163
197
|
def draw_time_range(pic_save_folder=None):
|
@@ -205,7 +239,8 @@ def draw_time_range(pic_save_folder=None):
|
|
205
239
|
# f"{row['version']}", ha='right', color='black')
|
206
240
|
ymdh_s = row["start_date"].strftime("%Y-%m-%d %H")
|
207
241
|
ymdh_e = row["end_date"].strftime("%Y-%m-%d %H")
|
208
|
-
if k == 1 or k == len(combined_labels):
|
242
|
+
# if k == 1 or k == len(combined_labels):
|
243
|
+
if k == 1:
|
209
244
|
plt.text(row["start_date"], k + 0.125, f"{ymdh_s}", ha="left", color="black")
|
210
245
|
plt.text(row["end_date"], k + 0.125, f"{ymdh_e}", ha="right", color="black")
|
211
246
|
else:
|
@@ -496,6 +531,14 @@ def get_base_url(dataset_name, version_name, var, ymdh_str):
|
|
496
531
|
break
|
497
532
|
if base_url is None:
|
498
533
|
print("Please ensure the var is in [u,v,temp,salt,ssh,u_b,v_b,temp_b,salt_b]")
|
534
|
+
elif classification_method == "single_var_year_different":
|
535
|
+
base_url = None
|
536
|
+
for key, value in single_var_group.items():
|
537
|
+
if var in value:
|
538
|
+
base_url = url_dict[key][str(year_str)]
|
539
|
+
break
|
540
|
+
if base_url is None:
|
541
|
+
print("Please ensure the var is in [u,v,temp,salt,ssh]")
|
499
542
|
return base_url
|
500
543
|
|
501
544
|
|
@@ -513,7 +556,44 @@ def clear_existing_file(file_full_path):
|
|
513
556
|
print(f"{file_full_path} has been removed")
|
514
557
|
|
515
558
|
|
516
|
-
def
|
559
|
+
def find_file(parent_path, fname, mode="path"):
|
560
|
+
"""
|
561
|
+
description:
|
562
|
+
param {*} parent_path: The parent path where the files are located
|
563
|
+
param {*} fname: The file name pattern to search for
|
564
|
+
param {*} mode: 'path' to return the full path of the files, 'file' to return only the file names
|
565
|
+
return {*} A list of file paths or file names if files are found, None otherwise
|
566
|
+
"""
|
567
|
+
|
568
|
+
def natural_sort_key(s):
|
569
|
+
"""生成一个用于自然排序的键"""
|
570
|
+
return [int(text) if text.isdigit() else text.lower() for text in re.split("([0-9]+)", s)]
|
571
|
+
|
572
|
+
# 将parent_path和fname结合成完整的搜索路径
|
573
|
+
search_pattern = os.path.join(str(parent_path), fname)
|
574
|
+
|
575
|
+
# 使用glob模块查找所有匹配的文件
|
576
|
+
matched_files = glob.glob(search_pattern)
|
577
|
+
|
578
|
+
# 如果没有找到任何文件,则返回False
|
579
|
+
if not matched_files:
|
580
|
+
return None
|
581
|
+
|
582
|
+
# 在find_files函数中替换natsorted调用
|
583
|
+
matched_files = sorted(matched_files, key=natural_sort_key)
|
584
|
+
|
585
|
+
# 根据mode参数决定返回的内容
|
586
|
+
if mode == "file":
|
587
|
+
# 只返回文件名
|
588
|
+
result = [os.path.basename(file) for file in matched_files]
|
589
|
+
else: # 默认为'path'
|
590
|
+
# 返回文件的绝对路径
|
591
|
+
result = [os.path.abspath(file) for file in matched_files]
|
592
|
+
|
593
|
+
return result
|
594
|
+
|
595
|
+
|
596
|
+
def file_size(file_path, unit="KB"):
|
517
597
|
# 检查文件是否存在
|
518
598
|
if not os.path.exists(file_path):
|
519
599
|
return "文件不存在"
|
@@ -534,12 +614,34 @@ def _get_file_size(file_path, unit="KB"):
|
|
534
614
|
return converted_size
|
535
615
|
|
536
616
|
|
537
|
-
|
617
|
+
# ** 计算文件夹下指定相关文件的平均大小
|
618
|
+
def mean_size(parent_path, fname):
|
619
|
+
flist = find_file(parent_path, fname)
|
620
|
+
if flist:
|
621
|
+
size_list = [file_size(f) for f in flist if file_size(f) != 0]
|
622
|
+
else:
|
623
|
+
size_list = []
|
624
|
+
if size_list:
|
625
|
+
min_size, max_size = min(size_list), max(size_list)
|
626
|
+
mean_size = sum(size_list) / len(size_list)
|
627
|
+
else:
|
628
|
+
mean_size, min_size, max_size = 0, 0, 0
|
629
|
+
return mean_size, min_size, max_size
|
630
|
+
|
631
|
+
|
632
|
+
def check_existing_file(file_full_path, min_size):
|
538
633
|
if os.path.exists(file_full_path):
|
539
634
|
print(f"[bold #FFA54F]{file_full_path} exists")
|
540
|
-
fsize =
|
635
|
+
fsize = file_size(file_full_path)
|
636
|
+
if min_size:
|
637
|
+
if fsize < min_size:
|
638
|
+
print(f"[bold #FFA54F]{file_full_path} ({fsize:.2f} KB) may be incomplete")
|
639
|
+
# clear_existing_file(file_full_path)
|
640
|
+
return False
|
641
|
+
else:
|
642
|
+
return True
|
541
643
|
if fsize < 5:
|
542
|
-
print(f"[bold #FFA54F]{file_full_path}
|
644
|
+
print(f"[bold #FFA54F]{file_full_path} ({fsize:.2f} KB) may be incomplete")
|
543
645
|
# clear_existing_file(file_full_path)
|
544
646
|
return False
|
545
647
|
else:
|
@@ -623,8 +725,13 @@ def get_proxy():
|
|
623
725
|
def download_file(target_url, store_path, file_name, check=False):
|
624
726
|
# Check if the file exists
|
625
727
|
fname = Path(store_path) / file_name
|
728
|
+
file_name_split = file_name.split("_")
|
729
|
+
same_file = f'{file_name_split[0]}_{file_name_split[1]}*nc'
|
730
|
+
fsize_mean, fsize_min, fsize_max = mean_size(store_path, same_file)
|
731
|
+
set_min_size = fsize_mean - 0.5 * (fsize_max - fsize_min)
|
732
|
+
set_min_size = set_min_size if set_min_size > 0 else fsize_min
|
626
733
|
if check:
|
627
|
-
if check_existing_file(fname):
|
734
|
+
if check_existing_file(fname, set_min_size*0.8):
|
628
735
|
count_dict["skip"] += 1
|
629
736
|
return
|
630
737
|
clear_existing_file(fname)
|
@@ -819,29 +926,37 @@ def prepare_url_to_download(var, lon_min=0, lon_max=359.92, lat_min=-80, lat_max
|
|
819
926
|
file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}_{download_time_end}.nc"
|
820
927
|
download_file(submit_url, store_path, file_name, check)
|
821
928
|
else:
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
826
|
-
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
929
|
+
if download_time < "2024081012":
|
930
|
+
varlist = [_ for _ in var]
|
931
|
+
for key, value in var_group.items():
|
932
|
+
current_group = []
|
933
|
+
for v in varlist:
|
934
|
+
if v in value:
|
935
|
+
current_group.append(v)
|
936
|
+
if len(current_group) == 0:
|
937
|
+
continue
|
938
|
+
|
939
|
+
var = current_group[0]
|
940
|
+
submit_url = get_submit_url_var(var, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time, download_time_end)
|
941
|
+
file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}.nc"
|
942
|
+
old_str = f'var={variable_info[var]["var_name"]}'
|
943
|
+
new_str = f'var={variable_info[var]["var_name"]}'
|
944
|
+
if len(current_group) > 1:
|
945
|
+
for v in current_group[1:]:
|
946
|
+
new_str = f'{new_str}&var={variable_info[v]["var_name"]}'
|
947
|
+
submit_url = submit_url.replace(old_str, new_str)
|
948
|
+
# file_name = f'HYCOM_{'-'.join([variable_info[v]["var_name"] for v in current_group])}_{download_time}.nc'
|
949
|
+
file_name = f"HYCOM_{key}_{download_time}.nc"
|
950
|
+
if download_time_end is not None:
|
951
|
+
file_name = f"HYCOM_{key}_{download_time}_{download_time_end}.nc"
|
952
|
+
download_file(submit_url, store_path, file_name, check)
|
953
|
+
else:
|
954
|
+
for v in var:
|
955
|
+
submit_url = get_submit_url_var(v, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time, download_time_end)
|
956
|
+
file_name = f"HYCOM_{variable_info[v]['var_name']}_{download_time}.nc"
|
842
957
|
if download_time_end is not None:
|
843
|
-
file_name = f"HYCOM_{
|
844
|
-
|
958
|
+
file_name = f"HYCOM_{variable_info[v]['var_name']}_{download_time}_{download_time_end}.nc"
|
959
|
+
download_file(submit_url, store_path, file_name, check)
|
845
960
|
|
846
961
|
|
847
962
|
def convert_full_name_to_short_name(full_name):
|
@@ -913,7 +1028,7 @@ def download_hourly_func(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_min
|
|
913
1028
|
parallel_counter = 0
|
914
1029
|
counter_lock = Lock() # 创建一个锁,线程安全的计数器
|
915
1030
|
if ymdh_time_s == ymdh_time_e:
|
916
|
-
prepare_url_to_download(var, lon_min, lon_max, lat_min, lat_max, ymdh_time_s, None, depth, level, store_path, dataset_name, version_name)
|
1031
|
+
prepare_url_to_download(var, lon_min, lon_max, lat_min, lat_max, ymdh_time_s, None, depth, level, store_path, dataset_name, version_name, check)
|
917
1032
|
elif int(ymdh_time_s) < int(ymdh_time_e):
|
918
1033
|
print("Downloading a series of files...")
|
919
1034
|
time_list = get_time_list(ymdh_time_s, ymdh_time_e, 3, "hour")
|
@@ -1111,9 +1226,9 @@ def how_to_use():
|
|
1111
1226
|
|
1112
1227
|
if __name__ == "__main__":
|
1113
1228
|
# help(hycom3h.download)
|
1114
|
-
time_s, time_e = "
|
1229
|
+
time_s, time_e = "2024081012", "2024081115"
|
1115
1230
|
merge_name = f"{time_s}_{time_e}" # 合并后的文件名
|
1116
|
-
root_path = r"G:\Data\HYCOM\
|
1231
|
+
root_path = r"G:\Data\HYCOM\3hourly_test"
|
1117
1232
|
location_dict = {"west": 105, "east": 130, "south": 15, "north": 45}
|
1118
1233
|
download_dict = {
|
1119
1234
|
"water_u": {"simple_name": "u", "download": 1},
|
@@ -1141,6 +1256,8 @@ if __name__ == "__main__":
|
|
1141
1256
|
download_switch, single_var = True, False
|
1142
1257
|
combine_switch = False
|
1143
1258
|
copy_switch, copy_dir = False, r"G:\Data\HYCOM\3hourly"
|
1259
|
+
|
1260
|
+
# draw_time_range(pic_save_folder=r'I:\Delete')
|
1144
1261
|
|
1145
1262
|
if download_switch:
|
1146
1263
|
if single_var:
|