windborne 1.2.5__tar.gz → 1.2.7__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: windborne
3
- Version: 1.2.5
3
+ Version: 1.2.7
4
4
  Summary: A Python library for interacting with WindBorne Data and Forecasts API
5
5
  Author-email: WindBorne Systems <data@windbornesystems.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "windborne"
7
- version = "1.2.5"
7
+ version = "1.2.7"
8
8
  description = "A Python library for interacting with WindBorne Data and Forecasts API"
9
9
  readme = {file = "README.md", content-type = "text/markdown"}
10
10
  authors = [
@@ -22,6 +22,7 @@ from .data_api import (
22
22
  from .forecasts_api import (
23
23
  get_point_forecasts,
24
24
  get_initialization_times,
25
+ get_historical_initialization_times,
25
26
  get_forecast_hours,
26
27
  get_generation_times,
27
28
 
@@ -41,7 +42,8 @@ from .forecasts_api import (
41
42
 
42
43
  get_tropical_cyclones,
43
44
 
44
- get_population_weighted_hdd
45
+ get_population_weighted_hdd,
46
+ get_population_weighted_cdd
45
47
  )
46
48
 
47
49
  # Define what should be available when users import *
@@ -63,6 +65,7 @@ __all__ = [
63
65
 
64
66
  "get_point_forecasts",
65
67
  "get_initialization_times",
68
+ "get_historical_initialization_times",
66
69
  "get_forecast_hours",
67
70
  "get_generation_times",
68
71
 
@@ -86,5 +89,6 @@ __all__ = [
86
89
  "get_historical_500hpa_wind_v",
87
90
  "get_tropical_cyclones",
88
91
 
89
- "get_population_weighted_hdd"
92
+ "get_population_weighted_hdd",
93
+ "get_population_weighted_cdd"
90
94
  ]
@@ -19,12 +19,14 @@ from . import (
19
19
 
20
20
  get_point_forecasts,
21
21
  get_initialization_times,
22
+ get_historical_initialization_times,
22
23
  get_forecast_hours,
23
24
  get_generation_times,
24
25
  get_full_gridded_forecast,
25
26
  get_gridded_forecast,
26
27
  get_tropical_cyclones,
27
- get_population_weighted_hdd
28
+ get_population_weighted_hdd,
29
+ get_population_weighted_cdd
28
30
 
29
31
  )
30
32
 
@@ -169,6 +171,8 @@ def main():
169
171
  'dewpoint_2m',
170
172
  'wind_u_10m',
171
173
  'wind_v_10m',
174
+ 'wind_u_100m',
175
+ 'wind_v_100m',
172
176
  'pressure_msl',
173
177
  '500/temperature',
174
178
  '500/wind_u',
@@ -235,11 +239,24 @@ def main():
235
239
  hdd_parser.add_argument('-m', '--external-model', help='External model (eg gfs, ifs, hrrr, aifs)')
236
240
  hdd_parser.add_argument('-o', '--output', help='Output file (supports .csv and .json formats)')
237
241
 
242
+ # Population Weighted CDD Command
243
+ cdd_parser = subparsers.add_parser('cdd', help='Get population weighted cooling degree days (CDD) forecasts')
244
+ cdd_parser.add_argument('initialization_time', help='Initialization time (YYYYMMDDHH, YYYY-MM-DDTHH, or YYYY-MM-DDTHH:mm:ss)')
245
+ cdd_parser.add_argument('-i', '--intracycle', action='store_true', help='Use the intracycle forecast')
246
+ cdd_parser.add_argument('-e', '--ens-member', help='Ensemble member (eg 1 or mean)')
247
+ cdd_parser.add_argument('-m', '--external-model', help='External model (eg gfs, ifs, hrrr, aifs)')
248
+ cdd_parser.add_argument('-o', '--output', help='Output file (supports .csv and .json formats)')
249
+
238
250
  # Initialization Times Command
239
251
  initialization_times_parser = subparsers.add_parser('init_times', help='Get available initialization times for point forecasts')
240
252
  initialization_times_parser.add_argument('-i', '--intracycle', action='store_true', help='Use the intracycle forecast')
241
253
  initialization_times_parser.add_argument('-e', '--ens-member', help='Ensemble member (eg 1 or mean)')
242
254
 
255
+ # Historical Initialization Times Command
256
+ hist_initialization_times_parser = subparsers.add_parser('hist_init_times', help='Get available historical initialization times')
257
+ hist_initialization_times_parser.add_argument('-i', '--intracycle', action='store_true', help='Use the intracycle forecast')
258
+ hist_initialization_times_parser.add_argument('-e', '--ens-member', help='Ensemble member (eg 1 or mean)')
259
+
243
260
  # Forecast Hours Command
244
261
  forecast_hours_parser = subparsers.add_parser('forecast_hours', help='Get available forecast hours for WeatherMesh')
245
262
  forecast_hours_parser.add_argument('-i', '--intracycle', action='store_true', help='Use the intracycle forecast')
@@ -449,6 +466,9 @@ def main():
449
466
  elif args.command == 'init_times':
450
467
  get_initialization_times(print_response=True, ensemble_member=args.ens_member, intracycle=args.intracycle)
451
468
 
469
+ elif args.command == 'hist_init_times':
470
+ get_historical_initialization_times(print_response=True, ensemble_member=args.ens_member, intracycle=args.intracycle)
471
+
452
472
  elif args.command == 'forecast_hours':
453
473
  get_forecast_hours(print_response=True, ensemble_member=args.ens_member, intracycle=args.intracycle)
454
474
 
@@ -547,6 +567,17 @@ def main():
547
567
  print_response=(not args.output)
548
568
  )
549
569
 
570
+ elif args.command == 'cdd':
571
+ # Handle population weighted CDD
572
+ get_population_weighted_cdd(
573
+ initialization_time=args.initialization_time,
574
+ intracycle=args.intracycle,
575
+ ens_member=args.ens_member,
576
+ external_model=args.external_model,
577
+ output_file=args.output,
578
+ print_response=(not args.output)
579
+ )
580
+
550
581
  else:
551
582
  parser.print_help()
552
583
 
@@ -301,6 +301,23 @@ def get_initialization_times(print_response=False, ensemble_member=None, intracy
301
301
  return response
302
302
 
303
303
 
304
+ def get_historical_initialization_times(print_response=False, ensemble_member=None, intracycle=False):
305
+ """
306
+ Get historical initialization times for forecasts from our archive
307
+ These may be higher latency to fetch and cannot be used for custom point forecasting
308
+ """
309
+ params = {
310
+ 'ens_member': ensemble_member,
311
+ 'intracycle': intracycle
312
+ }
313
+ response = make_api_request(f"{FORECASTS_API_BASE_URL}/historical_initialization_times.json", params=params)
314
+
315
+ if print_response:
316
+ print("Available historical initialization times:")
317
+ for time in response:
318
+ print(f" - {time}")
319
+
320
+
304
321
  def get_forecast_hours(print_response=False, ensemble_member=None, intracycle=False):
305
322
  """
306
323
  Get available forecast hours for WeatherMesh
@@ -427,3 +444,41 @@ def get_population_weighted_hdd(initialization_time, intracycle=False, ens_membe
427
444
  print(f" {dates[i]}: {response['hdd'][region][dates[i]]}")
428
445
 
429
446
  return response
447
+
448
+ def get_population_weighted_cdd(initialization_time, intracycle=False, ens_member=None, external_model=None, output_file=None, print_response=False):
449
+ """
450
+ Get population weighted CDD data from the API.
451
+ """
452
+ params = {
453
+ "initialization_time": initialization_time,
454
+ "intracycle": intracycle,
455
+ "ens_member": ens_member,
456
+ "external_model": external_model
457
+ }
458
+ response = make_api_request(f"{FORECASTS_API_BASE_URL}/cdd", params=params, as_json=True)
459
+
460
+ if output_file:
461
+ if output_file.endswith('.csv'):
462
+ import csv
463
+
464
+ # save as csv, with a row for each region, and a column for each date, sorted alphabetically by region
465
+ regions = sorted(response['cdd'].keys())
466
+ dates = response['dates']
467
+ data = [[response['cdd'][region][dates[i]] for region in regions] for i in range(len(dates))]
468
+
469
+ with open(output_file, 'w') as f:
470
+ writer = csv.writer(f)
471
+ writer.writerow(['Region'] + dates)
472
+
473
+ for region in regions:
474
+ writer.writerow([region] + [response['cdd'][region][date] for date in dates])
475
+
476
+ if print_response:
477
+ dates = response['dates']
478
+ print(response['cdd']['Alabama'])
479
+ for region in sorted(response['cdd'].keys()):
480
+ print(f"{region}:")
481
+ for i in range(len(dates)):
482
+ print(f" {dates[i]}: {response['cdd'][region][dates[i]]}")
483
+
484
+ return response
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: windborne
3
- Version: 1.2.5
3
+ Version: 1.2.7
4
4
  Summary: A Python library for interacting with WindBorne Data and Forecasts API
5
5
  Author-email: WindBorne Systems <data@windbornesystems.com>
6
6
  Classifier: Programming Language :: Python :: 3
File without changes
File without changes
File without changes