hefty 0.2.0__tar.gz → 0.2.1__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: hefty
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Some (relatively) lightweight short-term energy forecasting tools for solar, wind, and load.
5
5
  Author: Will Hobbs
6
6
  License-Expression: BSD-3-Clause
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hefty"
7
- version = "0.2.0"
7
+ version = "0.2.1"
8
8
  description = "Some (relatively) lightweight short-term energy forecasting tools for solar, wind, and load."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -388,7 +388,6 @@ def get_solar_forecast(latitude, longitude, init_date, run_length,
388
388
  # irradiance that resets every 6 hours
389
389
  mixed = df[['sdswrf']].copy()
390
390
  mixed['hour'] = mixed.index.hour
391
- mixed['hour'] = mixed.index.hour
392
391
  mixed['hour_of_mixed_period'] = ((mixed['hour'] - 1) % 6) + 1
393
392
  mixed['sdswrf_prev'] = mixed['sdswrf'].shift(
394
393
  periods=1,
@@ -913,7 +912,6 @@ def get_solar_forecast_fast(latitude, longitude, init_date, run_length,
913
912
  # irradiance that resets every 6 hours
914
913
  mixed = df[['sdswrf']].copy()
915
914
  mixed['hour'] = mixed.index.hour
916
- mixed['hour'] = mixed.index.hour
917
915
  mixed['hour_of_mixed_period'] = ((mixed['hour'] - 1) % 6) + 1
918
916
  mixed['sdswrf_prev'] = mixed['sdswrf'].shift(
919
917
  periods=1,
@@ -2249,7 +2247,6 @@ def get_solar_forecast_ensemble(latitude, longitude, init_date, run_length,
2249
2247
  # irradiance that resets every 6 hours
2250
2248
  mixed = df[['sdswrf']].copy()
2251
2249
  mixed['hour'] = mixed.index.hour
2252
- mixed['hour'] = mixed.index.hour
2253
2250
  mixed['hour_of_mixed_period'] = ((mixed['hour'] - 1) % 6) + 1
2254
2251
  mixed['sdswrf_prev'] = mixed['sdswrf'].shift(
2255
2252
  periods=1,
@@ -24,8 +24,10 @@ def get_fcast_definition(model='gfs'):
24
24
 
25
25
  Notes
26
26
  -----
27
- ``delay_intercept`` and ``delay_slope`` values are based on this gist,
28
- https://gist.github.com/williamhobbs/9585ff5d1248ab5de4d9e8665d7c8ea6,
27
+ ``delay_intercept`` and ``delay_slope`` values are based on this notebook,
28
+ https://github.com/williamhobbs/hefty/blob/main/docs/forecast_model_delays.ipynb,
29
+ also available as a markdown file,
30
+ https://github.com/williamhobbs/hefty/blob/main/docs/forecast_model_delays.md,
29
31
  and https://dynamical.org/status/, along with
30
32
  https://confluence.ecmwf.int/display/DAC/Dissemination+schedule and
31
33
  https://confluence.ecmwf.int/display/CKB/CAMS%3A+Global+atmospheric+composition+forecast+data+documentation#heading-DataavailabilityHHMM.
@@ -47,7 +49,7 @@ def get_fcast_definition(model='gfs'):
47
49
  - ``'update_period'``: number of hours between cycles for the schdeule,
48
50
  e.g., ``12`` for 12 hour updates.
49
51
  - ``'delay_intercept'``: intercept of a fit between forecast delivery
50
- delay in minutes and the forecast hour, e.g., ``515`` minutes.
52
+ delay in minutes and the forecast hour, e.g., ``515`` minutes.
51
53
  - ``'delay_slope'``: slope of a fit between forecast delivery delay in
52
54
  minutes and the forecast hour, e.g., ``0.02`` for a model schedule that
53
55
  delivers one forecast hours per 0.02 minues (50 hours per minute).
@@ -70,32 +72,24 @@ def get_fcast_definition(model='gfs'):
70
72
  'interval': [3, 6, 3],
71
73
  'first_cycle': [0, 0, 6],
72
74
  'update_period': [12, 12, 12],
73
- 'delay_intercept': [515, 515, 450],
74
- 'delay_slope': [0.006, 0.006, 0.006],
75
+ 'delay_intercept': [515, 515, 448],
76
+ 'delay_slope': [0.005, 0.002, 0.006],
75
77
  'product': ['oper', 'oper', 'scda'],
76
78
  }
77
79
 
78
80
  # Nov 2024 extended 'oper' and 'scda' horizons
79
81
  # https://github.com/blaylockbk/Herbie/discussions/421
80
82
  fcast_sched_dict_ifs_2 = {
83
+ **fcast_sched_dict_ifs_1,
81
84
  'start_date': ['2024-11-12 12:00',
82
85
  '2024-11-12 12:00',
83
86
  '2024-11-12 06:00'],
84
- 'start_hour': [0, 150, 0],
85
87
  'end_hour': [144, 360, 144],
86
- 'interval': [3, 6, 3],
87
- 'first_cycle': [0, 0, 6],
88
- 'update_period': [12, 12, 12],
89
- 'delay_intercept': [515, 515, 450],
90
- 'delay_slope': [0.006, 0.006, 0.006],
91
- 'product': ['oper', 'oper', 'scda'],
92
88
  }
93
89
 
94
- # Approx Oct 1 2025, removed 1hr extra delay in releasing files
95
- # Start date is just a guess, needs confirmation. Descriptoin changed
96
- # sometime between Nov 6 [1] and Nov 22 [2] 2025, but the changes to the
97
- # ECMWF open data website are often delayed. Maybe it corresponded with
98
- # this press release [3]?
90
+ # Oct 1 2025, removed 1hr extra delay in releasing files. Date confirmed.
91
+ # Description changed sometime between Nov 6 [1] and Nov 22 [2] 2025.
92
+ # It corresponded with this press release [3].
99
93
  #
100
94
  # [1] https://web.archive.org/web/20251106132450/https://www.ecmwf.int/en/forecasts/datasets/open-data
101
95
  # [2] https://web.archive.org/web/20251122204201/https://www.ecmwf.int/en/forecasts/datasets/open-data
@@ -105,7 +99,8 @@ def get_fcast_definition(model='gfs'):
105
99
  'start_date': ['2025-10-01 12:00',
106
100
  '2025-10-01 12:00',
107
101
  '2025-10-01 06:00'],
108
- 'delay_intercept': [455, 455, 390],
102
+ 'delay_intercept': [455, 455, 388],
103
+ 'delay_slope': [0.003, 0.002, 0.006],
109
104
  }
110
105
 
111
106
  fcast_definition_ifs = {
@@ -135,8 +130,8 @@ def get_fcast_definition(model='gfs'):
135
130
  'interval': [3, 6, 3],
136
131
  'first_cycle': [0, 0, 6],
137
132
  'update_period': [12, 12, 12],
138
- 'delay_intercept': [520, 520, 484],
139
- 'delay_slope': [0.02, 0.02, 0.03],
133
+ 'delay_intercept': [515, 515, 448],
134
+ 'delay_slope': [0.003, 0.002, 0.006],
140
135
  'product': ['enfo', 'enfo', 'enfo'],
141
136
  }
142
137
 
@@ -154,7 +149,7 @@ def get_fcast_definition(model='gfs'):
154
149
  'start_date': ['2025-10-01 12:00',
155
150
  '2025-10-01 12:00',
156
151
  '2025-10-01 06:00'],
157
- 'delay_intercept': [460, 460, 424],
152
+ 'delay_intercept': [455, 455, 388],
158
153
  }
159
154
 
160
155
  fcast_definition_ifs_ens = {
@@ -174,8 +169,8 @@ def get_fcast_definition(model='gfs'):
174
169
  'interval': [6],
175
170
  'first_cycle': [0],
176
171
  'update_period': [6],
177
- 'delay_intercept': [339],
178
- 'delay_slope': [0.008],
172
+ 'delay_intercept': [370],
173
+ 'delay_slope': [0.003],
179
174
  'product': ['aifs'],
180
175
  }
181
176
 
@@ -188,8 +183,6 @@ def get_fcast_definition(model='gfs'):
188
183
  # AIFS ENS
189
184
  # First available 2025-07-2, added one day, as I seem to recall some
190
185
  # variables were missing for a few days (https://herbie.readthedocs.io/en/stable/gallery/ecmwf_models/ecmwf.html)
191
- # Schedule is unverified, based on
192
- # https://confluence.ecmwf.int/display/DAC/Dissemination+schedule
193
186
  fcast_sched_dict_aifs_ens = {
194
187
  'start_date': ['2025-07-03 00:00'],
195
188
  'start_hour': [0, 0],
@@ -197,8 +190,8 @@ def get_fcast_definition(model='gfs'):
197
190
  'interval': [6, 6],
198
191
  'first_cycle': [0, 6],
199
192
  'update_period': [12, 12],
200
- 'delay_intercept': [400, 400],
201
- 'delay_slope': [0.125, 0.125],
193
+ 'delay_intercept': [380, 380],
194
+ 'delay_slope': [0.06, 0.06],
202
195
  'product': ['enfo', 'enfo'],
203
196
  }
204
197
 
@@ -240,8 +233,8 @@ def get_fcast_definition(model='gfs'):
240
233
  'interval': [1, 1],
241
234
  'first_cycle': [0, 0],
242
235
  'update_period': [1, 6],
243
- 'delay_intercept': [61, 63],
244
- 'delay_slope': [1.862, 1.125],
236
+ 'delay_intercept': [61, 65],
237
+ 'delay_slope': [1.86, 1.126],
245
238
  'product': ['18h', '48h'],
246
239
  }
247
240
 
@@ -267,8 +260,8 @@ def get_fcast_definition(model='gfs'):
267
260
  'interval': [1, 3],
268
261
  'first_cycle': [0, 0],
269
262
  'update_period': [6, 6],
270
- 'delay_intercept': [238, 238],
271
- 'delay_slope': [0.263, 0.263],
263
+ 'delay_intercept': [235, 235],
264
+ 'delay_slope': [0.262, 0.262],
272
265
  'product': ['pgrb2.0p25', 'pgrb2.0p25'],
273
266
  }
274
267
 
@@ -285,15 +278,16 @@ def get_fcast_definition(model='gfs'):
285
278
  # Implemented 2020-09-23 (https://www.emc.ncep.noaa.gov/emc/pages/numerical_forecast_systems/gefs.php)
286
279
  fcast_sched_dict_gefs = {
287
280
  'start_date': ['2020-09-24 01:00',
281
+ '2020-09-24 00:00',
288
282
  '2020-09-24 00:00'],
289
- 'start_hour': [0, 390],
290
- 'end_hour': [384, 840],
291
- 'interval': [3, 6],
292
- 'first_cycle': [0, 0],
293
- 'update_period': [6, 24],
294
- 'delay_intercept': [235, 265],
295
- 'delay_slope': [0.429, 0.332],
296
- 'product': ['3-hourly', 'extended'], # needs update
283
+ 'start_hour': [0, 246, 390],
284
+ 'end_hour': [240, 384, 840],
285
+ 'interval': [3, 6, 6],
286
+ 'first_cycle': [0, 0, 0],
287
+ 'update_period': [6, 6, 24],
288
+ 'delay_intercept': [245, 250, 1435], # 6h, extended are set manually
289
+ 'delay_slope': [0.434, 0.43, 0.335],
290
+ 'product': ['3-hourly', '6-hourly', 'extended'], # needs update
297
291
  }
298
292
 
299
293
  fcast_definition_gefs = {
@@ -648,7 +642,7 @@ def model_input_formatter(init_date, run_length, lead_time_to_start=0,
648
642
  elif model == 'gefs':
649
643
  # GEFS:
650
644
  # 0.5 deg:
651
- # 0 to 384 by 3, 390 to 840 by 6 for 00z cycle only
645
+ # 0 to 240 by 3, 246 to 840 by 6 for 00z cycle only
652
646
  # 0.25 deg:
653
647
  # 0 to 240 by 3
654
648
  # runs every 6 hours starting at 00z
@@ -694,6 +688,16 @@ def model_input_formatter(init_date, run_length, lead_time_to_start=0,
694
688
 
695
689
  # set forecast lead times
696
690
  fxx_range = range(lead_time_to_start, fxx_max + 1, 3)
691
+ if lead_time_to_start <= 240 and fxx_max > 240:
692
+ fxx_max = round(fxx_max/6)*6
693
+ fxx_range = [*range(lead_time_to_start, 240+3, 3),
694
+ *range(246, fxx_max + 1, 6)]
695
+ elif lead_time_to_start > 240:
696
+ fxx_max = round(fxx_max/6)*6
697
+ lead_time_to_start = round(lead_time_to_start/6)*6
698
+ fxx_range = range(lead_time_to_start, fxx_max + 1, 6)
699
+ else:
700
+ fxx_range = range(lead_time_to_start, fxx_max + 1, 3)
697
701
 
698
702
  elif model == 'ifs' or model == 'ifs_ens':
699
703
  # From https://www.ecmwf.int/en/forecasts/datasets/open-data
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hefty
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Some (relatively) lightweight short-term energy forecasting tools for solar, wind, and load.
5
5
  Author: Will Hobbs
6
6
  License-Expression: BSD-3-Clause
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes