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.
@@ -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-28 16:04:50
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 ymd_in_which_dataset_and_version(time_ymdh):
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
- if var in ['u', 'v', 'u_b', 'v_b']:
399
- base_url = url_dict['uv3z']
400
- elif var in ['temp', 'salt', 'temp_b', 'salt_b']:
401
- base_url = url_dict['ts3z']
402
- elif var in ['ssh']:
403
- base_url = url_dict['ssh']
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
- if var in ['u', 'v', 'u_b', 'v_b']:
408
- base_url = url_dict['uv3z'][str(year_str)]
409
- elif var in ['temp', 'salt', 'temp_b', 'salt_b']:
410
- base_url = url_dict['ts3z'][str(year_str)]
411
- elif var in ['ssh']:
412
- base_url = url_dict['ssh'][str(year_str)]
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'] = [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
- download_success = True
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 direct_download(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):
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
- ymd_in_which_dataset_and_version(download_time)
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
- ymd_in_which_dataset_and_version(download_time)
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
- ymd_in_which_dataset_and_version(download_time)
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
- file_name = f"HYCOM_{variable_info[var]['var_name']}_{download_time}.nc"
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
- dlownload_file(submit_url, store_path, file_name, check)
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
- direct_download(var, lon_min, lon_max, lat_min, lat_max, time_str, depth, level, store_path, dataset_name, version_name, check)
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 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):
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
- direct_download(var, lon_min, lon_max, lat_min, lat_max, ymdh_time_s, depth, level, store_path, dataset_name, version_name)
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 = get_time_list(ymdh_time_s, ymdh_time_e, 3)
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
- direct_download(var, lon_min, lon_max, lat_min, lat_max, time_str, depth, level, store_path, dataset_name, version_name, check)
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
- time_s, time_e = '2018010112', '2018010300'
767
- merge_name = '201801'
768
- root_path = r'I:\hycom_data_2018'
769
- location_dict = {'west': 115, 'east': 130, 'south': 33, 'north': 45}
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': 0},
773
- 'surf_el': {'simple_name': 'ssh', 'download': 0},
774
- 'water_temp': {'simple_name': 'temp', 'download': 0},
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
- set_depth, depth = False, 0 # 0-4000 meters
781
- set_level, level = False, 1 # 1-40 levels
782
- num_workers = 5
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 = False
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
- def download_var(var_name):
789
- var = download_dict[var_name]['simple_name']
790
- if_download = download_dict[var_name]['download']
791
- if if_download == 0:
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=var, time_s=time_s, time_e=time_e, store_path=Path(root_path)/var, lon_min=location_dict[
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 download_switch:
804
- for var_name in download_dict.keys():
805
- download_var(var_name)
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
- for time_str in time_list:
818
- file_list.append(
819
- Path(root_path)/var/f'HYCOM_{var_name}_{time_str}.nc')
820
- merge5nc(file_list, var_name, 'time',
821
- Path(root_path)/var/f'HYCOM_{var_name}_{merge_name}.nc') """
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) """