oafuncs 0.0.63__py2.py3-none-any.whl → 0.0.65__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/oa_down/hycom_3hourly.py +467 -75
- oafuncs/oa_down/hycom_3hourly_wholeday.py +1173 -0
- {oafuncs-0.0.63.dist-info → oafuncs-0.0.65.dist-info}/METADATA +1 -1
- {oafuncs-0.0.63.dist-info → oafuncs-0.0.65.dist-info}/RECORD +7 -6
- {oafuncs-0.0.63.dist-info → oafuncs-0.0.65.dist-info}/LICENSE.txt +0 -0
- {oafuncs-0.0.63.dist-info → oafuncs-0.0.65.dist-info}/WHEEL +0 -0
- {oafuncs-0.0.63.dist-info → oafuncs-0.0.65.dist-info}/top_level.txt +0 -0
oafuncs/oa_down/hycom_3hourly.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
Author: Liu Kun && 16031215@qq.com
|
5
5
|
Date: 2024-11-01 10:31:09
|
6
6
|
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
-
LastEditTime: 2024-11-
|
7
|
+
LastEditTime: 2024-11-29 20:40:26
|
8
8
|
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_down\\hycom_3hourly.py
|
9
9
|
Description:
|
10
10
|
EditPlatform: vscode
|
@@ -29,7 +29,7 @@ from rich.progress import Progress
|
|
29
29
|
|
30
30
|
warnings.filterwarnings("ignore", category=RuntimeWarning, message="Engine '.*' loading failed:.*")
|
31
31
|
|
32
|
-
__all__ = ['draw_time_range', 'download', 'how_to_use', 'get_time_list']
|
32
|
+
__all__ = ['draw_time_range', 'download', 'how_to_use', 'get_time_list', 'get_hour_list', 'get_day_list']
|
33
33
|
|
34
34
|
# time resolution
|
35
35
|
data_info = {'yearly': {}, 'monthly': {}, 'daily': {}, 'hourly': {}}
|
@@ -152,6 +152,12 @@ url_930_y = {
|
|
152
152
|
}
|
153
153
|
data_info['hourly']['dataset']['GLBy0.08']['version']['93.0']['url'] = url_930_y
|
154
154
|
|
155
|
+
var_group = {
|
156
|
+
'uv3z': ['u', 'v', 'u_b', 'v_b'],
|
157
|
+
'ts3z': ['temp', 'salt', 'temp_b', 'salt_b'],
|
158
|
+
'ssh': ['ssh'],
|
159
|
+
}
|
160
|
+
|
155
161
|
|
156
162
|
def draw_time_range(pic_save_folder=None):
|
157
163
|
if pic_save_folder is not None:
|
@@ -248,6 +254,44 @@ def get_time_list(time_s, time_e, delta_hour):
|
|
248
254
|
return dt_list
|
249
255
|
|
250
256
|
|
257
|
+
def get_hour_list(time_s, time_e, delta_hour):
|
258
|
+
'''
|
259
|
+
Description: get a list of time strings from time_s to time_e with delta_hour
|
260
|
+
Args:
|
261
|
+
time_s: start time string, e.g. '2023080203'
|
262
|
+
time_e: end time string, e.g. '2023080303'
|
263
|
+
delta_hour: interval of hours
|
264
|
+
Returns:
|
265
|
+
dt_list: a list of time strings
|
266
|
+
'''
|
267
|
+
dt = datetime.datetime.strptime(time_s, '%Y%m%d%H')
|
268
|
+
dt_list = []
|
269
|
+
while dt.strftime('%Y%m%d%H') <= time_e:
|
270
|
+
dt_list.append(dt.strftime('%Y%m%d%H'))
|
271
|
+
dt = dt + datetime.timedelta(hours=delta_hour)
|
272
|
+
return dt_list
|
273
|
+
|
274
|
+
|
275
|
+
def get_day_list(time_s, time_e, delta_day):
|
276
|
+
'''
|
277
|
+
Description: get a list of time strings from time_s to time_e with delta_hour
|
278
|
+
Args:
|
279
|
+
time_s: start time string, e.g. '20230802'
|
280
|
+
time_e: end time string, e.g. '20230803'
|
281
|
+
delta_hour: interval of hours
|
282
|
+
Returns:
|
283
|
+
dt_list: a list of time strings
|
284
|
+
'''
|
285
|
+
time_s = time_s[:8]
|
286
|
+
time_e = time_e[:8]
|
287
|
+
dt = datetime.datetime.strptime(time_s, '%Y%m%d')
|
288
|
+
dt_list = []
|
289
|
+
while dt.strftime('%Y%m%d') <= time_e:
|
290
|
+
dt_list.append(dt.strftime('%Y%m%d'))
|
291
|
+
dt = dt + datetime.timedelta(days=delta_day)
|
292
|
+
return dt_list
|
293
|
+
|
294
|
+
|
251
295
|
def get_nearest_level_index(depth):
|
252
296
|
level_depth = [0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 125.0, 150.0, 200.0, 250.0, 300.0, 350.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0, 1250.0, 1500.0, 2000.0, 2500.0, 3000.0, 4000.0, 5000]
|
253
297
|
return min(range(len(level_depth)), key=lambda i: abs(level_depth[i]-depth))
|
@@ -345,7 +389,7 @@ def get_query_dict_full_depth(var, lon_min, lon_max, lat_min, lat_max, time_str_
|
|
345
389
|
return query_dict
|
346
390
|
|
347
391
|
|
348
|
-
def
|
392
|
+
def ymdh_in_which_dataset_and_version(time_ymdh):
|
349
393
|
time_ymdh = int(time_ymdh)
|
350
394
|
d_list = []
|
351
395
|
v_list = []
|
@@ -372,6 +416,33 @@ def ymd_in_which_dataset_and_version(time_ymdh):
|
|
372
416
|
raise ValueError(f'[bold red]{time_ymdh} is not in any dataset and version')
|
373
417
|
|
374
418
|
|
419
|
+
def ymd_in_which_dataset_and_version(time_ymd):
|
420
|
+
time_ymd = int(str(time_ymd)[:8])
|
421
|
+
d_list = []
|
422
|
+
v_list = []
|
423
|
+
trange_list = []
|
424
|
+
have_data = False
|
425
|
+
for dataset_name in data_info['hourly']['dataset'].keys():
|
426
|
+
for version_name in data_info['hourly']['dataset'][dataset_name]['version'].keys():
|
427
|
+
time_s, time_e = list(data_info['hourly']['dataset'][dataset_name]['version'][version_name]['time_range'].values())
|
428
|
+
time_s, time_e = str(time_s), str(time_e)
|
429
|
+
if len(time_s) == 8:
|
430
|
+
time_s = time_s + '00'
|
431
|
+
if len(time_e) == 8:
|
432
|
+
time_e = time_e + '21'
|
433
|
+
if time_ymd*100 >= int(time_s) and time_ymd*100+21 <= int(time_e):
|
434
|
+
d_list.append(dataset_name)
|
435
|
+
v_list.append(version_name)
|
436
|
+
trange_list.append(f'{time_s}-{time_e}')
|
437
|
+
have_data = True
|
438
|
+
print(f'[bold red]{time_ymd} is in the following dataset and version:')
|
439
|
+
if have_data:
|
440
|
+
for d, v, trange in zip(d_list, v_list, trange_list):
|
441
|
+
print(f'[bold blue]{d} {v} {trange}')
|
442
|
+
else:
|
443
|
+
raise ValueError(f'[bold red]{time_ymd} is not in any dataset and version')
|
444
|
+
|
445
|
+
|
375
446
|
def direct_choose_dataset_and_version(time_ymdh):
|
376
447
|
time_ymdh = int(time_ymdh)
|
377
448
|
for dataset_name in data_info['hourly']['dataset'].keys():
|
@@ -387,6 +458,21 @@ def direct_choose_dataset_and_version(time_ymdh):
|
|
387
458
|
return dataset_name, version_name
|
388
459
|
|
389
460
|
|
461
|
+
def direct_choose_dataset_and_version_whole_day(time_ymd):
|
462
|
+
time_ymd = int(str(time_ymd)[:8])
|
463
|
+
for dataset_name in data_info['hourly']['dataset'].keys():
|
464
|
+
for version_name in data_info['hourly']['dataset'][dataset_name]['version'].keys():
|
465
|
+
[time_s, time_e] = list(data_info['hourly']['dataset'][dataset_name]['version'][version_name]['time_range'].values())
|
466
|
+
time_s, time_e = str(time_s), str(time_e)
|
467
|
+
if len(time_s) == 8:
|
468
|
+
time_s = time_s + '00'
|
469
|
+
if len(time_e) == 8:
|
470
|
+
time_e = time_e + '21'
|
471
|
+
if time_ymd*100 >= int(time_s) and time_ymd*100+21 <= int(time_e):
|
472
|
+
print(f'[bold purple]dataset: {dataset_name}, version: {version_name} is chosen')
|
473
|
+
return dataset_name, version_name
|
474
|
+
|
475
|
+
|
390
476
|
def get_base_url(dataset_name, version_name, var, year_str):
|
391
477
|
url_dict = data_info['hourly']['dataset'][dataset_name]['version'][version_name]['url']
|
392
478
|
classification_method = data_info['hourly']['dataset'][dataset_name]['version'][version_name]['classification']
|
@@ -395,29 +481,28 @@ def get_base_url(dataset_name, version_name, var, year_str):
|
|
395
481
|
elif classification_method == 'same_path':
|
396
482
|
base_url = url_dict
|
397
483
|
elif classification_method == 'var_different':
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
else:
|
484
|
+
base_url = None
|
485
|
+
for key, value in var_group.items():
|
486
|
+
if var in value:
|
487
|
+
base_url = url_dict[key]
|
488
|
+
break
|
489
|
+
if base_url is None:
|
405
490
|
print('Please ensure the var is in [u,v,temp,salt,ssh,u_b,v_b,temp_b,salt_b]')
|
406
491
|
elif classification_method == 'var_year_different':
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
else:
|
492
|
+
base_url = None
|
493
|
+
for key, value in var_group.items():
|
494
|
+
if var in value:
|
495
|
+
base_url = url_dict[key][str(year_str)]
|
496
|
+
break
|
497
|
+
if base_url is None:
|
414
498
|
print('Please ensure the var is in [u,v,temp,salt,ssh,u_b,v_b,temp_b,salt_b]')
|
415
499
|
return base_url
|
416
500
|
|
417
501
|
|
418
502
|
def get_submit_url(dataset_name, version_name, var, year_str, query_dict):
|
419
503
|
base_url = get_base_url(dataset_name, version_name, var, year_str)
|
420
|
-
query_dict['var']
|
504
|
+
if isinstance(query_dict['var'], str):
|
505
|
+
query_dict['var'] = [query_dict['var']]
|
421
506
|
target_url = base_url + '&'.join(f"var={var}" for var in query_dict['var']) + '&' + '&'.join(f"{key}={value}" for key, value in query_dict.items() if key != 'var')
|
422
507
|
return target_url
|
423
508
|
|
@@ -430,7 +515,7 @@ def clear_existing_file(file_full_path):
|
|
430
515
|
|
431
516
|
def check_existing_file(file_full_path):
|
432
517
|
if os.path.exists(file_full_path):
|
433
|
-
print(f'{file_full_path} exists')
|
518
|
+
print(f'[bold #FFA54F]{file_full_path} exists')
|
434
519
|
return True
|
435
520
|
else:
|
436
521
|
print(f'{file_full_path} does not exist')
|
@@ -535,6 +620,7 @@ def dlownload_file(target_url, store_path, file_name, check=False):
|
|
535
620
|
download_success = False
|
536
621
|
request_times = 0
|
537
622
|
filename = Path(store_path) / file_name
|
623
|
+
|
538
624
|
if check:
|
539
625
|
if check_existing_file(filename):
|
540
626
|
return
|
@@ -554,9 +640,10 @@ def dlownload_file(target_url, store_path, file_name, check=False):
|
|
554
640
|
with open(filename, 'wb') as f:
|
555
641
|
f.write(response.content)
|
556
642
|
# print(f'\r文件 {filename} 下载成功', end="")
|
557
|
-
print(f'[bold green]文件 {filename} 下载成功')
|
558
643
|
# query_ncfile_time(filename) # 这个函数在linux上目前会出问题
|
559
|
-
|
644
|
+
if os.path.exists(filename):
|
645
|
+
download_success = True
|
646
|
+
print(f'[bold green]文件 {filename} 下载成功')
|
560
647
|
|
561
648
|
except requests.exceptions.HTTPError as errh:
|
562
649
|
print(f"Http Error: {errh}")
|
@@ -581,7 +668,7 @@ def check_hour_is_valid(ymdh_str):
|
|
581
668
|
return False
|
582
669
|
|
583
670
|
|
584
|
-
def
|
671
|
+
def check_dataset_version_single_time(dataset_name, version_name, download_time):
|
585
672
|
download_time = str(download_time)
|
586
673
|
if not check_hour_is_valid(download_time):
|
587
674
|
print('Please ensure the hour is 00, 03, 06, 09, 12, 15, 18, 21')
|
@@ -589,21 +676,25 @@ def direct_download(var, lon_min=0, lon_max=359.92, lat_min=-80, lat_max=90, dow
|
|
589
676
|
if dataset_name is None and version_name is None:
|
590
677
|
print('The dataset_name and version_name are None, so the dataset and version will be chosen according to the download_time.\nIf there is more than one dataset and version in the time range, the first one will be chosen.')
|
591
678
|
print('If you wanna choose the dataset and version by yourself, please set the dataset_name and version_name together.')
|
592
|
-
|
679
|
+
ymdh_in_which_dataset_and_version(download_time)
|
593
680
|
dataset_name, version_name = direct_choose_dataset_and_version(download_time)
|
594
681
|
elif dataset_name is None and version_name is not None:
|
595
682
|
print('Please ensure the dataset_name is not None')
|
596
683
|
print('If you do not add the dataset_name, both the dataset and version will be chosen according to the download_time.')
|
597
|
-
|
684
|
+
ymdh_in_which_dataset_and_version(download_time)
|
598
685
|
dataset_name, version_name = direct_choose_dataset_and_version(download_time)
|
599
686
|
elif dataset_name is not None and version_name is None:
|
600
687
|
print('Please ensure the version_name is not None')
|
601
688
|
print('If you do not add the version_name, both the dataset and version will be chosen according to the download_time.')
|
602
|
-
|
689
|
+
ymdh_in_which_dataset_and_version(download_time)
|
603
690
|
dataset_name, version_name = direct_choose_dataset_and_version(download_time)
|
604
691
|
else:
|
605
692
|
print('The dataset_name and version_name are both set by yourself.')
|
606
693
|
|
694
|
+
return dataset_name, version_name
|
695
|
+
|
696
|
+
|
697
|
+
def get_submit_url_var(var, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time):
|
607
698
|
year_str = str(download_time)[:4]
|
608
699
|
if depth is not None and level_num is not None:
|
609
700
|
print('Please ensure the depth or level_num is None')
|
@@ -618,12 +709,128 @@ def direct_download(var, lon_min=0, lon_max=359.92, lat_min=-80, lat_max=90, dow
|
|
618
709
|
query_dict = get_query_dict_full_level(var, lon_min, lon_max, lat_min, lat_max, download_time)
|
619
710
|
submit_url = get_submit_url(
|
620
711
|
dataset_name, version_name, var, year_str, query_dict)
|
621
|
-
|
712
|
+
return submit_url
|
713
|
+
|
714
|
+
|
715
|
+
def direct_download_single_time(var, lon_min=0, lon_max=359.92, lat_min=-80, lat_max=90, download_time='2024083100', depth=None, level_num=None, store_path=None, dataset_name=None, version_name=None, check=False):
|
716
|
+
download_time = str(download_time)
|
717
|
+
dataset_name, version_name = check_dataset_version_single_time(dataset_name, version_name, download_time)
|
718
|
+
|
622
719
|
if store_path is None:
|
623
720
|
store_path = str(Path.cwd())
|
624
721
|
else:
|
625
722
|
os.makedirs(str(store_path), exist_ok=True)
|
626
|
-
|
723
|
+
|
724
|
+
if isinstance(var, str):
|
725
|
+
var = [var]
|
726
|
+
|
727
|
+
if isinstance(var, list):
|
728
|
+
if len(var) == 1:
|
729
|
+
var = var[0]
|
730
|
+
submit_url = get_submit_url_var(var, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time)
|
731
|
+
file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}.nc"
|
732
|
+
dlownload_file(submit_url, store_path, file_name, check)
|
733
|
+
else:
|
734
|
+
varlist = [_ for _ in var]
|
735
|
+
for key, value in var_group.items():
|
736
|
+
current_group = []
|
737
|
+
for v in varlist:
|
738
|
+
if v in value:
|
739
|
+
current_group.append(v)
|
740
|
+
if len(current_group) == 0:
|
741
|
+
continue
|
742
|
+
|
743
|
+
var = current_group[0]
|
744
|
+
submit_url = get_submit_url_var(var, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time)
|
745
|
+
file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}.nc"
|
746
|
+
old_str = f'var={variable_info[var]["var_name"]}'
|
747
|
+
new_str = f'var={variable_info[var]["var_name"]}'
|
748
|
+
if len(current_group) > 1:
|
749
|
+
for v in current_group[1:]:
|
750
|
+
new_str = f'{new_str}&var={variable_info[v]["var_name"]}'
|
751
|
+
submit_url = submit_url.replace(old_str, new_str)
|
752
|
+
# file_name = f'HYCOM_{'-'.join([variable_info[v]["var_name"] for v in current_group])}_{download_time}.nc'
|
753
|
+
file_name = f'HYCOM_{key}_{download_time}.nc'
|
754
|
+
dlownload_file(submit_url, store_path, file_name, check)
|
755
|
+
|
756
|
+
|
757
|
+
def check_dataset_version_whold_day(dataset_name, version_name, download_time):
|
758
|
+
download_time = str(download_time)
|
759
|
+
if dataset_name is None and version_name is None:
|
760
|
+
print('The dataset_name and version_name are None, so the dataset and version will be chosen according to the download_time.\nIf there is more than one dataset and version in the time range, the first one will be chosen.')
|
761
|
+
print('If you wanna choose the dataset and version by yourself, please set the dataset_name and version_name together.')
|
762
|
+
ymd_in_which_dataset_and_version(download_time)
|
763
|
+
dataset_name, version_name = direct_choose_dataset_and_version_whole_day(download_time)
|
764
|
+
elif dataset_name is None and version_name is not None:
|
765
|
+
print('Please ensure the dataset_name is not None')
|
766
|
+
print('If you do not add the dataset_name, both the dataset and version will be chosen according to the download_time.')
|
767
|
+
ymd_in_which_dataset_and_version(download_time)
|
768
|
+
dataset_name, version_name = direct_choose_dataset_and_version_whole_day(download_time)
|
769
|
+
elif dataset_name is not None and version_name is None:
|
770
|
+
print('Please ensure the version_name is not None')
|
771
|
+
print('If you do not add the version_name, both the dataset and version will be chosen according to the download_time.')
|
772
|
+
ymd_in_which_dataset_and_version(download_time)
|
773
|
+
dataset_name, version_name = direct_choose_dataset_and_version_whole_day(download_time)
|
774
|
+
else:
|
775
|
+
print('The dataset_name and version_name are both set by yourself.')
|
776
|
+
|
777
|
+
return dataset_name, version_name
|
778
|
+
|
779
|
+
|
780
|
+
def direct_download_whole_day(var, lon_min=0, lon_max=359.92, lat_min=-80, lat_max=90, download_time='20240831', depth=None, level_num=None, store_path=None, dataset_name=None, version_name=None, check=False):
|
781
|
+
download_time = str(download_time)[:8]+'00'
|
782
|
+
dataset_name, version_name = check_dataset_version_whold_day(dataset_name, version_name, download_time[:8])
|
783
|
+
|
784
|
+
if store_path is None:
|
785
|
+
store_path = str(Path.cwd())
|
786
|
+
else:
|
787
|
+
os.makedirs(str(store_path), exist_ok=True)
|
788
|
+
|
789
|
+
if isinstance(var, str):
|
790
|
+
var = [var]
|
791
|
+
|
792
|
+
if isinstance(var, list):
|
793
|
+
if len(var) == 1:
|
794
|
+
var = var[0]
|
795
|
+
submit_url = get_submit_url_var(var, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time)
|
796
|
+
|
797
|
+
# https://ncss.hycom.org/thredds/ncss/GLBu0.08/expt_93.0/ts3z?var=salinity&disableLLSubset=on&disableProjSubset=on&horizStride=1&time=2018-12-09T09%3A00%3A00Z&vertCoord=&accept=netcdf4
|
798
|
+
# https://ncss.hycom.org/thredds/ncss/GLBu0.08/expt_93.0/ts3z?var=salinity&disableLLSubset=on&disableProjSubset=on&horizStride=1&time_start=2018-09-19T12%3A00%3A00Z&time_end=2018-12-09T09%3A00%3A00Z&timeStride=1&vertCoord=&accept=netcdf4
|
799
|
+
# 将time=2018-12-09T09%3A00%3A00Z替换为time_start=2018-09-19T12%3A00%3A00Z&time_end=2018-12-09T09%3A00%3A00Z&timeStride=1
|
800
|
+
daytime_s = transform_time(str(download_time)[:8]+'00')
|
801
|
+
daytime_e = transform_time(str(download_time)[:8]+'21')
|
802
|
+
submit_url = submit_url.replace(
|
803
|
+
f'time={daytime_s}', f'time_start={daytime_s}&time_end={daytime_e}&timeStride=1')
|
804
|
+
|
805
|
+
file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}.nc"
|
806
|
+
|
807
|
+
dlownload_file(submit_url, store_path, file_name, check)
|
808
|
+
else:
|
809
|
+
varlist = [_ for _ in var]
|
810
|
+
for key, value in var_group.items():
|
811
|
+
current_group = []
|
812
|
+
for v in varlist:
|
813
|
+
if v in value:
|
814
|
+
current_group.append(v)
|
815
|
+
if len(current_group) == 0:
|
816
|
+
continue
|
817
|
+
|
818
|
+
var = current_group[0]
|
819
|
+
submit_url = get_submit_url_var(var, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time)
|
820
|
+
daytime_s = transform_time(str(download_time)[:8]+'00')
|
821
|
+
daytime_e = transform_time(str(download_time)[:8]+'21')
|
822
|
+
submit_url = submit_url.replace(
|
823
|
+
f'time={daytime_s}', f'time_start={daytime_s}&time_end={daytime_e}&timeStride=1')
|
824
|
+
file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}.nc"
|
825
|
+
old_str = f'var={variable_info[var]["var_name"]}'
|
826
|
+
new_str = f'var={variable_info[var]["var_name"]}'
|
827
|
+
if len(current_group) > 1:
|
828
|
+
for v in current_group[1:]:
|
829
|
+
new_str = f'{new_str}&var={variable_info[v]["var_name"]}'
|
830
|
+
submit_url = submit_url.replace(old_str, new_str)
|
831
|
+
# file_name = f'HYCOM_{'-'.join([variable_info[v]["var_name"] for v in current_group])}_{download_time}.nc'
|
832
|
+
file_name = f'HYCOM_{key}_{download_time}.nc'
|
833
|
+
dlownload_file(submit_url, store_path, file_name, check)
|
627
834
|
|
628
835
|
|
629
836
|
def convert_full_name_to_short_name(full_name):
|
@@ -646,10 +853,13 @@ def download_task(var, time_str, lon_min, lon_max, lat_min, lat_max, depth, leve
|
|
646
853
|
这样,每个任务都是独立的,有自己的参数和数据,不会与其他任务共享或修改任何数据。
|
647
854
|
因此,即使多个任务同时执行,也不会出现数据交互错乱的问题。
|
648
855
|
'''
|
649
|
-
|
856
|
+
if len(time_str) == 8:
|
857
|
+
direct_download_whole_day(var, lon_min, lon_max, lat_min, lat_max, time_str, depth, level, store_path, dataset_name, version_name, check)
|
858
|
+
else:
|
859
|
+
direct_download_single_time(var, lon_min, lon_max, lat_min, lat_max, time_str, depth, level, store_path, dataset_name, version_name, check)
|
650
860
|
|
651
861
|
|
652
|
-
def
|
862
|
+
def download_single_hour(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):
|
653
863
|
'''
|
654
864
|
Description:
|
655
865
|
Download the data of single time or a series of time
|
@@ -672,6 +882,146 @@ def download(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_min=-80, lat_ma
|
|
672
882
|
Returns:
|
673
883
|
None
|
674
884
|
'''
|
885
|
+
if isinstance(var, list):
|
886
|
+
if len(var) == 1:
|
887
|
+
var = convert_full_name_to_short_name(var[0])
|
888
|
+
else:
|
889
|
+
var = [convert_full_name_to_short_name(v) for v in var]
|
890
|
+
elif isinstance(var, str):
|
891
|
+
var = convert_full_name_to_short_name(var)
|
892
|
+
else:
|
893
|
+
raise ValueError('The var is invalid')
|
894
|
+
if var is False:
|
895
|
+
raise ValueError('The var is invalid')
|
896
|
+
if lon_min < 0 or lon_min > 359.92 or lon_max < 0 or lon_max > 359.92 or lat_min < -80 or lat_min > 90 or lat_max < -80 or lat_max > 90:
|
897
|
+
print('Please ensure the lon_min, lon_max, lat_min, lat_max are in the range')
|
898
|
+
print('The range of lon_min, lon_max is 0~359.92')
|
899
|
+
print('The range of lat_min, lat_max is -80~90')
|
900
|
+
raise ValueError('The lon or lat is invalid')
|
901
|
+
ymdh_time_s = str(time_s)
|
902
|
+
if len(ymdh_time_s) == 8:
|
903
|
+
ymdh_time_s += '00'
|
904
|
+
ymdh_time_e = str(time_e)
|
905
|
+
if len(ymdh_time_e) == 8:
|
906
|
+
ymdh_time_e += '21'
|
907
|
+
if ymdh_time_s == ymdh_time_e:
|
908
|
+
direct_download_single_time(var, lon_min, lon_max, lat_min, lat_max, ymdh_time_s, depth, level, store_path, dataset_name, version_name)
|
909
|
+
elif int(ymdh_time_s) < int(ymdh_time_e):
|
910
|
+
print('Downloading a series of files...')
|
911
|
+
time_list = get_hour_list(ymdh_time_s, ymdh_time_e, 3)
|
912
|
+
with Progress() as progress:
|
913
|
+
task = progress.add_task("[cyan]Downloading...", total=len(time_list))
|
914
|
+
if num_workers is None or num_workers <= 1:
|
915
|
+
# 串行方式
|
916
|
+
for time_str in time_list:
|
917
|
+
direct_download_single_time(var, lon_min, lon_max, lat_min, lat_max, time_str, depth, level, store_path, dataset_name, version_name, check)
|
918
|
+
progress.update(task, advance=1)
|
919
|
+
else:
|
920
|
+
# 并行方式
|
921
|
+
if num_workers > 10:
|
922
|
+
print('The number of workers is too large!')
|
923
|
+
print('In order to avoid the server being blocked, the number of workers is set to 10')
|
924
|
+
num_workers = 10
|
925
|
+
with ThreadPoolExecutor(max_workers=num_workers) as executor:
|
926
|
+
futures = [executor.submit(download_task, var, time_str, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, check) for time_str in time_list]
|
927
|
+
for future in futures:
|
928
|
+
future.add_done_callback(lambda _: progress.update(task, advance=1))
|
929
|
+
else:
|
930
|
+
print('Please ensure the time_s is less than the time_e')
|
931
|
+
|
932
|
+
|
933
|
+
def download_whole_day(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):
|
934
|
+
'''
|
935
|
+
Description:
|
936
|
+
Download the data of single time or a series of time
|
937
|
+
|
938
|
+
Parameters:
|
939
|
+
var: str, the variable name, such as 'u', 'v', 'temp', 'salt', 'ssh', 'u_b', 'v_b', 'temp_b', 'salt_b' or 'water_u', 'water_v', 'water_temp', 'salinity', 'surf_el', 'water_u_bottom', 'water_v_bottom', 'water_temp_bottom', 'salinity_bottom'
|
940
|
+
time_s: str, the start time, such as '20241101', without hour
|
941
|
+
time_e: str, the end time, such as '20241102', without hour
|
942
|
+
lon_min: float, the minimum longitude, default is 0
|
943
|
+
lon_max: float, the maximum longitude, default is 359.92
|
944
|
+
lat_min: float, the minimum latitude, default is -80
|
945
|
+
lat_max: float, the maximum latitude, default is 90
|
946
|
+
depth: float, the depth, default is None
|
947
|
+
level: int, the level number, default is None
|
948
|
+
store_path: str, the path to store the data, default is None
|
949
|
+
dataset_name: str, the dataset name, default is None, example: 'GLBv0.08', 'GLBu0.08', 'GLBy0.08'
|
950
|
+
version_name: str, the version name, default is None, example: '53.X', '56.3'
|
951
|
+
num_workers: int, the number of workers, default is None
|
952
|
+
|
953
|
+
Returns:
|
954
|
+
None
|
955
|
+
'''
|
956
|
+
if isinstance(var, list):
|
957
|
+
if len(var) == 1:
|
958
|
+
var = convert_full_name_to_short_name(var[0])
|
959
|
+
else:
|
960
|
+
var = [convert_full_name_to_short_name(v) for v in var]
|
961
|
+
elif isinstance(var, str):
|
962
|
+
var = convert_full_name_to_short_name(var)
|
963
|
+
else:
|
964
|
+
raise ValueError('The var is invalid')
|
965
|
+
if var is False:
|
966
|
+
raise ValueError('The var is invalid')
|
967
|
+
if lon_min < 0 or lon_min > 359.92 or lon_max < 0 or lon_max > 359.92 or lat_min < -80 or lat_min > 90 or lat_max < -80 or lat_max > 90:
|
968
|
+
print('Please ensure the lon_min, lon_max, lat_min, lat_max are in the range')
|
969
|
+
print('The range of lon_min, lon_max is 0~359.92')
|
970
|
+
print('The range of lat_min, lat_max is -80~90')
|
971
|
+
raise ValueError('The lon or lat is invalid')
|
972
|
+
time_s, time_e = str(time_s)[:8], str(time_e)[:8]
|
973
|
+
|
974
|
+
if time_s == time_e:
|
975
|
+
direct_download_whole_day(var, lon_min, lon_max, lat_min, lat_max, time_s, depth, level, store_path, dataset_name, version_name)
|
976
|
+
elif int(time_s) < int(time_e):
|
977
|
+
print('Downloading a series of files...')
|
978
|
+
time_list = get_day_list(time_s, time_e, 1)
|
979
|
+
with Progress() as progress:
|
980
|
+
task = progress.add_task("[cyan]Downloading...", total=len(time_list))
|
981
|
+
if num_workers is None or num_workers <= 1:
|
982
|
+
# 串行方式
|
983
|
+
for time_str in time_list:
|
984
|
+
direct_download_whole_day(var, lon_min, lon_max, lat_min, lat_max, time_str, depth, level, store_path, dataset_name, version_name, check)
|
985
|
+
progress.update(task, advance=1)
|
986
|
+
else:
|
987
|
+
# 并行方式
|
988
|
+
if num_workers > 10:
|
989
|
+
print('The number of workers is too large!')
|
990
|
+
print('In order to avoid the server being blocked, the number of workers is set to 10')
|
991
|
+
num_workers = 10
|
992
|
+
with ThreadPoolExecutor(max_workers=num_workers) as executor:
|
993
|
+
futures = [executor.submit(download_task, var, time_str, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, check) for time_str in time_list]
|
994
|
+
for future in futures:
|
995
|
+
future.add_done_callback(lambda _: progress.update(task, advance=1))
|
996
|
+
else:
|
997
|
+
print('Please ensure the time_s is less than the time_e')
|
998
|
+
|
999
|
+
|
1000
|
+
def download_his1(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):
|
1001
|
+
'''
|
1002
|
+
Description:
|
1003
|
+
Download the data of single time or a series of time
|
1004
|
+
|
1005
|
+
Parameters:
|
1006
|
+
var: str, the variable name, such as 'u', 'v', 'temp', 'salt', 'ssh', 'u_b', 'v_b', 'temp_b', 'salt_b' or 'water_u', 'water_v', 'water_temp', 'salinity', 'surf_el', 'water_u_bottom', 'water_v_bottom', 'water_temp_bottom', 'salinity_bottom'
|
1007
|
+
time_s: str, the start time, such as '2024110100' or '20241101', if add hour, the hour should be 00, 03, 06, 09, 12, 15, 18, 21
|
1008
|
+
time_e: str, the end time, such as '2024110221' or '20241102', if add hour, the hour should be 00, 03, 06, 09, 12, 15, 18, 21
|
1009
|
+
lon_min: float, the minimum longitude, default is 0
|
1010
|
+
lon_max: float, the maximum longitude, default is 359.92
|
1011
|
+
lat_min: float, the minimum latitude, default is -80
|
1012
|
+
lat_max: float, the maximum latitude, default is 90
|
1013
|
+
depth: float, the depth, default is None
|
1014
|
+
level: int, the level number, default is None
|
1015
|
+
store_path: str, the path to store the data, default is None
|
1016
|
+
dataset_name: str, the dataset name, default is None, example: 'GLBv0.08', 'GLBu0.08', 'GLBy0.08'
|
1017
|
+
version_name: str, the version name, default is None, example: '53.X', '56.3'
|
1018
|
+
num_workers: int, the number of workers, default is None
|
1019
|
+
|
1020
|
+
Returns:
|
1021
|
+
None
|
1022
|
+
'''
|
1023
|
+
if isinstance(var, list):
|
1024
|
+
var = var[0]
|
675
1025
|
var = convert_full_name_to_short_name(var)
|
676
1026
|
if var is False:
|
677
1027
|
raise ValueError('The var is invalid')
|
@@ -687,16 +1037,16 @@ def download(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_min=-80, lat_ma
|
|
687
1037
|
if len(ymdh_time_e) == 8:
|
688
1038
|
ymdh_time_e += '21'
|
689
1039
|
if ymdh_time_s == ymdh_time_e:
|
690
|
-
|
1040
|
+
direct_download_single_time(var, lon_min, lon_max, lat_min, lat_max, ymdh_time_s, depth, level, store_path, dataset_name, version_name)
|
691
1041
|
elif int(ymdh_time_s) < int(ymdh_time_e):
|
692
1042
|
print('Downloading a series of files...')
|
693
|
-
time_list =
|
1043
|
+
time_list = get_hour_list(ymdh_time_s, ymdh_time_e, 3)
|
694
1044
|
with Progress() as progress:
|
695
1045
|
task = progress.add_task("[cyan]Downloading...", total=len(time_list))
|
696
1046
|
if num_workers is None or num_workers <= 1:
|
697
1047
|
# 串行方式
|
698
1048
|
for time_str in time_list:
|
699
|
-
|
1049
|
+
direct_download_single_time(var, lon_min, lon_max, lat_min, lat_max, time_str, depth, level, store_path, dataset_name, version_name, check)
|
700
1050
|
progress.update(task, advance=1)
|
701
1051
|
else:
|
702
1052
|
# 并行方式
|
@@ -713,6 +1063,40 @@ def download(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_min=-80, lat_ma
|
|
713
1063
|
print('Please ensure the ymdh_time_s is less than the ymdh_time_e')
|
714
1064
|
|
715
1065
|
|
1066
|
+
def download(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, resolution='hour'):
|
1067
|
+
'''
|
1068
|
+
Description:
|
1069
|
+
Download the data of single time or a series of time
|
1070
|
+
|
1071
|
+
Parameters:
|
1072
|
+
var: str, the variable name, such as 'u', 'v', 'temp', 'salt', 'ssh', 'u_b', 'v_b', 'temp_b', 'salt_b' or 'water_u', 'water_v', 'water_temp', 'salinity', 'surf_el', 'water_u_bottom', 'water_v_bottom', 'water_temp_bottom', 'salinity_bottom'
|
1073
|
+
time_s: str, the start time, such as '2024110100' or '20241101', if add hour, the hour should be 00, 03, 06, 09, 12, 15, 18, 21
|
1074
|
+
time_e: str, the end time, such as '2024110221' or '20241102', if add hour, the hour should be 00, 03, 06, 09, 12, 15, 18, 21
|
1075
|
+
lon_min: float, the minimum longitude, default is 0
|
1076
|
+
lon_max: float, the maximum longitude, default is 359.92
|
1077
|
+
lat_min: float, the minimum latitude, default is -80
|
1078
|
+
lat_max: float, the maximum latitude, default is 90
|
1079
|
+
depth: float, the depth, default is None
|
1080
|
+
level: int, the level number, default is None
|
1081
|
+
store_path: str, the path to store the data, default is None
|
1082
|
+
dataset_name: str, the dataset name, default is None, example: 'GLBv0.08', 'GLBu0.08', 'GLBy0.08'
|
1083
|
+
version_name: str, the version name, default is None, example: '53.X', '56.3'
|
1084
|
+
num_workers: int, the number of workers, default is None
|
1085
|
+
|
1086
|
+
Returns:
|
1087
|
+
None
|
1088
|
+
'''
|
1089
|
+
if resolution == 'hour':
|
1090
|
+
download_single_hour(var, time_s, time_e, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, num_workers, check)
|
1091
|
+
elif resolution == 'day':
|
1092
|
+
print('Currently can not download the data of whole day...')
|
1093
|
+
# download_whole_day(var, time_s, time_e, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, num_workers, check)
|
1094
|
+
download_single_hour(var, time_s, time_e, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, num_workers, check)
|
1095
|
+
else:
|
1096
|
+
print('Please ensure the resolution is in [hour, day]\n This will be set to hour')
|
1097
|
+
download_single_hour(var, time_s, time_e, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, num_workers, check)
|
1098
|
+
|
1099
|
+
|
716
1100
|
def how_to_use():
|
717
1101
|
print('''
|
718
1102
|
# 1. Choose the dataset and version according to the time:
|
@@ -763,59 +1147,67 @@ def how_to_use():
|
|
763
1147
|
|
764
1148
|
|
765
1149
|
if __name__ == '__main__':
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
1150
|
+
# help(hycom3h.download)
|
1151
|
+
time_s, time_e = '2018010100', '2024103121'
|
1152
|
+
merge_name = '2018_010300-020100'
|
1153
|
+
root_path = r'G:\Data\HYCOM\3hourly'
|
1154
|
+
location_dict = {'west': 105, 'east': 130, 'south': 15, 'north': 45}
|
770
1155
|
download_dict = {
|
771
1156
|
'water_u': {'simple_name': 'u', 'download': 1},
|
772
|
-
'water_v': {'simple_name': 'v', 'download':
|
773
|
-
'surf_el': {'simple_name': 'ssh', 'download':
|
774
|
-
'water_temp': {'simple_name': 'temp', 'download':
|
1157
|
+
'water_v': {'simple_name': 'v', 'download': 1},
|
1158
|
+
'surf_el': {'simple_name': 'ssh', 'download': 1},
|
1159
|
+
'water_temp': {'simple_name': 'temp', 'download': 1},
|
775
1160
|
'salinity': {'simple_name': 'salt', 'download': 1},
|
1161
|
+
'water_u_bottom': {'simple_name': 'u_b', 'download': 0},
|
1162
|
+
'water_v_bottom': {'simple_name': 'v_b', 'download': 0},
|
1163
|
+
'water_temp_bottom': {'simple_name': 'temp_b', 'download': 0},
|
1164
|
+
'salinity_bottom': {'simple_name': 'salt_b', 'download': 0},
|
776
1165
|
}
|
777
1166
|
|
1167
|
+
var_list = []
|
1168
|
+
for var_name in download_dict.keys():
|
1169
|
+
if download_dict[var_name]['download'] == 1:
|
1170
|
+
var_list.append(var_name)
|
1171
|
+
|
778
1172
|
# set depth or level, only one can be True
|
779
1173
|
# if you wanna download all depth or level, set both False
|
780
|
-
|
781
|
-
|
782
|
-
num_workers =
|
1174
|
+
depth = None # or 0-4000 meters
|
1175
|
+
level = None # or 1-40 levels
|
1176
|
+
num_workers = 2
|
1177
|
+
|
783
1178
|
check = True
|
784
1179
|
|
785
|
-
download_switch = True
|
786
|
-
combine_switch =
|
1180
|
+
download_switch, single_var = True, False
|
1181
|
+
combine_switch = True
|
1182
|
+
copy_switch, copy_dir = True, r'G:\Data\HYCOM\3hourly'
|
787
1183
|
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
return
|
793
|
-
if set_depth:
|
794
|
-
download(var=var, time_s=time_s, time_e=time_e, store_path=Path(root_path)/var, lon_min=location_dict[
|
795
|
-
'west'], lon_max=location_dict['east'], lat_min=location_dict['south'], lat_max=location_dict['north'], depth=depth, num_workers=num_workers, check=check)
|
796
|
-
elif set_level:
|
797
|
-
download(var=var, time_s=time_s, time_e=time_e, store_path=Path(root_path)/var, lon_min=location_dict[
|
798
|
-
'west'], lon_max=location_dict['east'], lat_min=location_dict['south'], lat_max=location_dict['north'], level=level, num_workers=num_workers, check=check)
|
1184
|
+
if download_switch:
|
1185
|
+
if single_var:
|
1186
|
+
for var_name in var_list:
|
1187
|
+
download(var=var_name, time_s=time_s, time_e=time_e, store_path=Path(root_path), lon_min=location_dict['west'], lon_max=location_dict['east'], lat_min=location_dict['south'], lat_max=location_dict['north'], num_workers=num_workers, check=check, depth=depth, level=level)
|
799
1188
|
else:
|
800
|
-
download(var=
|
801
|
-
'west'], lon_max=location_dict['east'], lat_min=location_dict['south'], lat_max=location_dict['north'], num_workers=num_workers, check=check)
|
1189
|
+
download(var=var_list, time_s=time_s, time_e=time_e, store_path=Path(root_path), lon_min=location_dict['west'], lon_max=location_dict['east'], lat_min=location_dict['south'], lat_max=location_dict['north'], num_workers=num_workers, check=check, depth=depth, level=level)
|
802
1190
|
|
803
|
-
if
|
804
|
-
|
805
|
-
|
806
|
-
|
807
|
-
# draw_time_range(r'I:\Delete')
|
808
|
-
|
809
|
-
""" if combine_switch:
|
810
|
-
time_list = get_time_list(time_s, time_e, 3)
|
811
|
-
for var_name in download_dict.keys():
|
812
|
-
var = download_dict[var_name]['simple_name']
|
813
|
-
if_download = download_dict[var_name]['download']
|
814
|
-
if if_download == 0:
|
815
|
-
continue
|
1191
|
+
""" if combine_switch or copy_switch:
|
1192
|
+
time_list = get_hour_list(time_s, time_e, 3)
|
1193
|
+
for var_name in var_list:
|
816
1194
|
file_list = []
|
817
|
-
|
818
|
-
|
819
|
-
Path(root_path)/
|
820
|
-
|
821
|
-
|
1195
|
+
if single_var:
|
1196
|
+
for time_str in time_list:
|
1197
|
+
file_list.append(Path(root_path)/f'HYCOM_{var_name}_{time_str}.nc')
|
1198
|
+
merge_path_name = Path(root_path)/f'HYCOM_{var_name}_{merge_name}.nc'
|
1199
|
+
else:
|
1200
|
+
# 如果混合,需要看情况获取文件列表
|
1201
|
+
fname = ''
|
1202
|
+
if var_name in ['water_u', 'water_v', 'water_u_bottom', 'water_v_bottom'] or var_name in ['u', 'v', 'u_b', 'v_b']:
|
1203
|
+
fname = 'uv3z'
|
1204
|
+
elif var_name in ['water_temp', 'salinity', 'water_temp_bottom', 'salinity_bottom'] or var_name in ['temp', 'salt', 'temp_b', 'salt_b']:
|
1205
|
+
fname = 'ts3z'
|
1206
|
+
elif var_name in ['surf_el'] or var_name in ['ssh']:
|
1207
|
+
fname = 'surf_el'
|
1208
|
+
for time_str in time_list:
|
1209
|
+
file_list.append(Path(root_path)/f'HYCOM_{fname}_{time_str}.nc')
|
1210
|
+
if combine_switch:
|
1211
|
+
merge5nc(file_list, var_name, 'time', merge_path_name)
|
1212
|
+
if copy_switch:
|
1213
|
+
copy_file(merge_path_name, copy_dir) """
|