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.
Files changed (41) hide show
  1. oafuncs/__init__.py +27 -12
  2. oafuncs/oa_cmap.py +31 -52
  3. oafuncs/oa_data.py +107 -28
  4. oafuncs/oa_down/hycom_3hourly.py +151 -34
  5. oafuncs/oa_draw.py +148 -96
  6. oafuncs/oa_file.py +61 -50
  7. oafuncs/oa_nc.py +131 -53
  8. {oafuncs-0.0.80.dist-info → oafuncs-0.0.82.dist-info}/METADATA +1 -2
  9. oafuncs-0.0.82.dist-info/RECORD +24 -0
  10. oafuncs-0.0.82.dist-info/top_level.txt +1 -0
  11. oafuncs/oa_down/test.py +0 -151
  12. oafuncs/oa_s/__init__.py +0 -23
  13. oafuncs/oa_s/oa_cmap.py +0 -163
  14. oafuncs/oa_s/oa_data.py +0 -187
  15. oafuncs/oa_s/oa_draw.py +0 -451
  16. oafuncs/oa_s/oa_file.py +0 -332
  17. oafuncs/oa_s/oa_help.py +0 -39
  18. oafuncs/oa_s/oa_nc.py +0 -410
  19. oafuncs/oa_s/oa_python.py +0 -107
  20. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/__init__.py" +0 -26
  21. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_cmap.py" +0 -163
  22. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_data.py" +0 -187
  23. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/__init__.py" +0 -20
  24. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/hycom_3hourly.py" +0 -1176
  25. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/literature.py" +0 -332
  26. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_down/test_ua.py" +0 -151
  27. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_draw.py" +0 -451
  28. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_file.py" +0 -332
  29. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_help.py" +0 -39
  30. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_nc.py" +0 -410
  31. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_python.py" +0 -107
  32. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/__init__.py" +0 -21
  33. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/meteorological.py" +0 -168
  34. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/ocean.py" +0 -158
  35. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_sign/scientific.py" +0 -139
  36. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/__init__.py" +0 -18
  37. oafuncs - /321/205/320/231/320/277/321/206/320/254/320/274/oa_tool/email.py" +0 -114
  38. oafuncs-0.0.80.dist-info/RECORD +0 -51
  39. oafuncs-0.0.80.dist-info/top_level.txt +0 -2
  40. {oafuncs-0.0.80.dist-info → oafuncs-0.0.82.dist-info}/LICENSE.txt +0 -0
  41. {oafuncs-0.0.80.dist-info → oafuncs-0.0.82.dist-info}/WHEEL +0 -0
@@ -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": "20300904"}
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, 2030):
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 _get_file_size(file_path, unit="KB"):
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
- def check_existing_file(file_full_path):
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 = _get_file_size(file_full_path)
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} may be incomplete\nFile size: {fsize:.2f} KB")
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
- varlist = [_ for _ in var]
823
- for key, value in var_group.items():
824
- current_group = []
825
- for v in varlist:
826
- if v in value:
827
- current_group.append(v)
828
- if len(current_group) == 0:
829
- continue
830
-
831
- var = current_group[0]
832
- 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)
833
- file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}.nc"
834
- old_str = f'var={variable_info[var]["var_name"]}'
835
- new_str = f'var={variable_info[var]["var_name"]}'
836
- if len(current_group) > 1:
837
- for v in current_group[1:]:
838
- new_str = f'{new_str}&var={variable_info[v]["var_name"]}'
839
- submit_url = submit_url.replace(old_str, new_str)
840
- # file_name = f'HYCOM_{'-'.join([variable_info[v]["var_name"] for v in current_group])}_{download_time}.nc'
841
- file_name = f"HYCOM_{key}_{download_time}.nc"
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_{key}_{download_time}_{download_time_end}.nc"
844
- download_file(submit_url, store_path, file_name, check)
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 = "2023010100", "2023123121"
1229
+ time_s, time_e = "2024081012", "2024081115"
1115
1230
  merge_name = f"{time_s}_{time_e}" # 合并后的文件名
1116
- root_path = r"G:\Data\HYCOM\3hourly"
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: