windborne 1.2.4__py3-none-any.whl → 1.2.6__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.
- windborne/__init__.py +8 -2
- windborne/cli.py +41 -1
- windborne/forecasts_api.py +76 -0
- {windborne-1.2.4.dist-info → windborne-1.2.6.dist-info}/METADATA +1 -1
- windborne-1.2.6.dist-info/RECORD +13 -0
- windborne-1.2.4.dist-info/RECORD +0 -13
- {windborne-1.2.4.dist-info → windborne-1.2.6.dist-info}/WHEEL +0 -0
- {windborne-1.2.4.dist-info → windborne-1.2.6.dist-info}/entry_points.txt +0 -0
- {windborne-1.2.4.dist-info → windborne-1.2.6.dist-info}/top_level.txt +0 -0
windborne/__init__.py
CHANGED
@@ -39,7 +39,10 @@ from .forecasts_api import (
|
|
39
39
|
get_historical_500hpa_geopotential,
|
40
40
|
get_historical_500hpa_wind_u, get_historical_500hpa_wind_v,
|
41
41
|
|
42
|
-
get_tropical_cyclones
|
42
|
+
get_tropical_cyclones,
|
43
|
+
|
44
|
+
get_population_weighted_hdd,
|
45
|
+
get_population_weighted_cdd
|
43
46
|
)
|
44
47
|
|
45
48
|
# Define what should be available when users import *
|
@@ -82,5 +85,8 @@ __all__ = [
|
|
82
85
|
"get_historical_500hpa_geopotential",
|
83
86
|
"get_historical_500hpa_wind_u",
|
84
87
|
"get_historical_500hpa_wind_v",
|
85
|
-
"get_tropical_cyclones"
|
88
|
+
"get_tropical_cyclones",
|
89
|
+
|
90
|
+
"get_population_weighted_hdd",
|
91
|
+
"get_population_weighted_cdd"
|
86
92
|
]
|
windborne/cli.py
CHANGED
@@ -23,7 +23,9 @@ from . import (
|
|
23
23
|
get_generation_times,
|
24
24
|
get_full_gridded_forecast,
|
25
25
|
get_gridded_forecast,
|
26
|
-
get_tropical_cyclones
|
26
|
+
get_tropical_cyclones,
|
27
|
+
get_population_weighted_hdd,
|
28
|
+
get_population_weighted_cdd
|
27
29
|
|
28
30
|
)
|
29
31
|
|
@@ -226,6 +228,22 @@ def main():
|
|
226
228
|
tropical_cyclones_parser.add_argument('args', nargs='*',
|
227
229
|
help='[optional: initialization time (YYYYMMDDHH, YYYY-MM-DDTHH, or YYYY-MM-DDTHH:mm:ss)] output_file')
|
228
230
|
|
231
|
+
# Population Weighted HDD Command
|
232
|
+
hdd_parser = subparsers.add_parser('hdd', help='Get population weighted heating degree days (HDD) forecasts')
|
233
|
+
hdd_parser.add_argument('initialization_time', help='Initialization time (YYYYMMDDHH, YYYY-MM-DDTHH, or YYYY-MM-DDTHH:mm:ss)')
|
234
|
+
hdd_parser.add_argument('-i', '--intracycle', action='store_true', help='Use the intracycle forecast')
|
235
|
+
hdd_parser.add_argument('-e', '--ens-member', help='Ensemble member (eg 1 or mean)')
|
236
|
+
hdd_parser.add_argument('-m', '--external-model', help='External model (eg gfs, ifs, hrrr, aifs)')
|
237
|
+
hdd_parser.add_argument('-o', '--output', help='Output file (supports .csv and .json formats)')
|
238
|
+
|
239
|
+
# Population Weighted CDD Command
|
240
|
+
cdd_parser = subparsers.add_parser('cdd', help='Get population weighted cooling degree days (CDD) forecasts')
|
241
|
+
cdd_parser.add_argument('initialization_time', help='Initialization time (YYYYMMDDHH, YYYY-MM-DDTHH, or YYYY-MM-DDTHH:mm:ss)')
|
242
|
+
cdd_parser.add_argument('-i', '--intracycle', action='store_true', help='Use the intracycle forecast')
|
243
|
+
cdd_parser.add_argument('-e', '--ens-member', help='Ensemble member (eg 1 or mean)')
|
244
|
+
cdd_parser.add_argument('-m', '--external-model', help='External model (eg gfs, ifs, hrrr, aifs)')
|
245
|
+
cdd_parser.add_argument('-o', '--output', help='Output file (supports .csv and .json formats)')
|
246
|
+
|
229
247
|
# Initialization Times Command
|
230
248
|
initialization_times_parser = subparsers.add_parser('init_times', help='Get available initialization times for point forecasts')
|
231
249
|
initialization_times_parser.add_argument('-i', '--intracycle', action='store_true', help='Use the intracycle forecast')
|
@@ -527,6 +545,28 @@ def main():
|
|
527
545
|
print("Error: Too many arguments")
|
528
546
|
print("Usage: windborne tropical_cyclones [initialization_time] output_file")
|
529
547
|
|
548
|
+
elif args.command == 'hdd':
|
549
|
+
# Handle population weighted HDD
|
550
|
+
get_population_weighted_hdd(
|
551
|
+
initialization_time=args.initialization_time,
|
552
|
+
intracycle=args.intracycle,
|
553
|
+
ens_member=args.ens_member,
|
554
|
+
external_model=args.external_model,
|
555
|
+
output_file=args.output,
|
556
|
+
print_response=(not args.output)
|
557
|
+
)
|
558
|
+
|
559
|
+
elif args.command == 'cdd':
|
560
|
+
# Handle population weighted CDD
|
561
|
+
get_population_weighted_cdd(
|
562
|
+
initialization_time=args.initialization_time,
|
563
|
+
intracycle=args.intracycle,
|
564
|
+
ens_member=args.ens_member,
|
565
|
+
external_model=args.external_model,
|
566
|
+
output_file=args.output,
|
567
|
+
print_response=(not args.output)
|
568
|
+
)
|
569
|
+
|
530
570
|
else:
|
531
571
|
parser.print_help()
|
532
572
|
|
windborne/forecasts_api.py
CHANGED
@@ -389,3 +389,79 @@ def download_and_save_output(output_file, response, silent=False):
|
|
389
389
|
if not silent:
|
390
390
|
print(f"Error processing the file: {e}")
|
391
391
|
return False
|
392
|
+
|
393
|
+
def get_population_weighted_hdd(initialization_time, intracycle=False, ens_member=None, external_model=None, output_file=None, print_response=False):
|
394
|
+
"""
|
395
|
+
Get population weighted HDD data from the API.
|
396
|
+
"""
|
397
|
+
params = {
|
398
|
+
"initialization_time": initialization_time,
|
399
|
+
"intracycle": intracycle,
|
400
|
+
"ens_member": ens_member,
|
401
|
+
"external_model": external_model
|
402
|
+
}
|
403
|
+
response = make_api_request(f"{FORECASTS_API_BASE_URL}/hdd", params=params, as_json=True)
|
404
|
+
|
405
|
+
if output_file:
|
406
|
+
if output_file.endswith('.csv'):
|
407
|
+
import csv
|
408
|
+
|
409
|
+
# save as csv, with a row for each region, and a column for each date, sorted alphabetically by region
|
410
|
+
regions = sorted(response['hdd'].keys())
|
411
|
+
dates = response['dates']
|
412
|
+
data = [[response['hdd'][region][dates[i]] for region in regions] for i in range(len(dates))]
|
413
|
+
|
414
|
+
with open(output_file, 'w') as f:
|
415
|
+
writer = csv.writer(f)
|
416
|
+
writer.writerow(['Region'] + dates)
|
417
|
+
|
418
|
+
for region in regions:
|
419
|
+
writer.writerow([region] + [response['hdd'][region][date] for date in dates])
|
420
|
+
|
421
|
+
if print_response:
|
422
|
+
dates = response['dates']
|
423
|
+
print(response['hdd']['Alabama'])
|
424
|
+
for region in sorted(response['hdd'].keys()):
|
425
|
+
print(f"{region}:")
|
426
|
+
for i in range(len(dates)):
|
427
|
+
print(f" {dates[i]}: {response['hdd'][region][dates[i]]}")
|
428
|
+
|
429
|
+
return response
|
430
|
+
|
431
|
+
def get_population_weighted_cdd(initialization_time, intracycle=False, ens_member=None, external_model=None, output_file=None, print_response=False):
|
432
|
+
"""
|
433
|
+
Get population weighted CDD data from the API.
|
434
|
+
"""
|
435
|
+
params = {
|
436
|
+
"initialization_time": initialization_time,
|
437
|
+
"intracycle": intracycle,
|
438
|
+
"ens_member": ens_member,
|
439
|
+
"external_model": external_model
|
440
|
+
}
|
441
|
+
response = make_api_request(f"{FORECASTS_API_BASE_URL}/cdd", params=params, as_json=True)
|
442
|
+
|
443
|
+
if output_file:
|
444
|
+
if output_file.endswith('.csv'):
|
445
|
+
import csv
|
446
|
+
|
447
|
+
# save as csv, with a row for each region, and a column for each date, sorted alphabetically by region
|
448
|
+
regions = sorted(response['cdd'].keys())
|
449
|
+
dates = response['dates']
|
450
|
+
data = [[response['cdd'][region][dates[i]] for region in regions] for i in range(len(dates))]
|
451
|
+
|
452
|
+
with open(output_file, 'w') as f:
|
453
|
+
writer = csv.writer(f)
|
454
|
+
writer.writerow(['Region'] + dates)
|
455
|
+
|
456
|
+
for region in regions:
|
457
|
+
writer.writerow([region] + [response['cdd'][region][date] for date in dates])
|
458
|
+
|
459
|
+
if print_response:
|
460
|
+
dates = response['dates']
|
461
|
+
print(response['cdd']['Alabama'])
|
462
|
+
for region in sorted(response['cdd'].keys()):
|
463
|
+
print(f"{region}:")
|
464
|
+
for i in range(len(dates)):
|
465
|
+
print(f" {dates[i]}: {response['cdd'][region][dates[i]]}")
|
466
|
+
|
467
|
+
return response
|
@@ -0,0 +1,13 @@
|
|
1
|
+
windborne/__init__.py,sha256=eTmMmiGDOwvecD4Eyfe13v0dn8yU9PqpwZbce9xLkpE,2240
|
2
|
+
windborne/api_request.py,sha256=moFKZFKMrHCINtve6ZfQYgrGgd6tXQffVGuNkZzprV4,8508
|
3
|
+
windborne/cli.py,sha256=qjXfyPPKTvrssl2Mr2X2NsIxsJw31slffoic0GoY3eE,31459
|
4
|
+
windborne/data_api.py,sha256=sYZkcQog8RuLErfdLLa4gC8fRkAoPGNKKQJ8i6o-LTQ,33826
|
5
|
+
windborne/forecasts_api.py,sha256=TPSR25_GiFnQrWharrefSGpxN5300Un0d4sx1sFIN6E,20063
|
6
|
+
windborne/observation_formatting.py,sha256=c739aaun6aaYhXl5VI-SRGR-TDS355_0Bfu1t6McoiM,14993
|
7
|
+
windborne/track_formatting.py,sha256=LaLfTyjpWoOtHmReJPLViY0MKm_iPL_5I2OB_lNvGGA,10054
|
8
|
+
windborne/utils.py,sha256=H8gvZ4Lrr0UmLl25iMZs6NsZliCY_73Ved_rBIqxJg4,7240
|
9
|
+
windborne-1.2.6.dist-info/METADATA,sha256=7P5KLbZ0q6HFRZ4ANStCOXGkHPeF3Bk0WDd6MAtt1SI,1304
|
10
|
+
windborne-1.2.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
11
|
+
windborne-1.2.6.dist-info/entry_points.txt,sha256=j_YrqdCDrCd7p5MIwQ2BYwNXEi95VNANzLRJmcXEg1U,49
|
12
|
+
windborne-1.2.6.dist-info/top_level.txt,sha256=PE9Lauriu5S5REf7JKhXprufZ_V5RiZ_TnfnrLGJrmE,10
|
13
|
+
windborne-1.2.6.dist-info/RECORD,,
|
windborne-1.2.4.dist-info/RECORD
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
windborne/__init__.py,sha256=dslI8_5Wozr96w7c0E7_HEpYIHt9YaTLo3ADF2yapSk,2102
|
2
|
-
windborne/api_request.py,sha256=moFKZFKMrHCINtve6ZfQYgrGgd6tXQffVGuNkZzprV4,8508
|
3
|
-
windborne/cli.py,sha256=TzEZtfzOgMgPU11ARgJ6O3YZFV3TcXPPYOabHBKb01Y,29247
|
4
|
-
windborne/data_api.py,sha256=sYZkcQog8RuLErfdLLa4gC8fRkAoPGNKKQJ8i6o-LTQ,33826
|
5
|
-
windborne/forecasts_api.py,sha256=mg7rJkBUE9xSyKIx4RMN0-RIZBdqqSz7Jp5JqFg8DhI,17053
|
6
|
-
windborne/observation_formatting.py,sha256=c739aaun6aaYhXl5VI-SRGR-TDS355_0Bfu1t6McoiM,14993
|
7
|
-
windborne/track_formatting.py,sha256=LaLfTyjpWoOtHmReJPLViY0MKm_iPL_5I2OB_lNvGGA,10054
|
8
|
-
windborne/utils.py,sha256=H8gvZ4Lrr0UmLl25iMZs6NsZliCY_73Ved_rBIqxJg4,7240
|
9
|
-
windborne-1.2.4.dist-info/METADATA,sha256=IueZfHUEH8-ZAqiUm-pODRED1uRRsRKfecGq7lokM8E,1304
|
10
|
-
windborne-1.2.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
11
|
-
windborne-1.2.4.dist-info/entry_points.txt,sha256=j_YrqdCDrCd7p5MIwQ2BYwNXEi95VNANzLRJmcXEg1U,49
|
12
|
-
windborne-1.2.4.dist-info/top_level.txt,sha256=PE9Lauriu5S5REf7JKhXprufZ_V5RiZ_TnfnrLGJrmE,10
|
13
|
-
windborne-1.2.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|