0
# Utility Functions
1
2
Helper functions for coordinate transformations, date/time conversions, grid operations, and library configuration.
3
4
## Module Constants
5
6
### Version Information
7
8
```python { .api }
9
__version__: str = "2.1.6"
10
"""pygrib package version string"""
11
```
12
13
Usage example:
14
```python
15
import pygrib
16
print(f"Using pygrib version: {pygrib.__version__}")
17
```
18
19
## Capabilities
20
21
### Grid Transformation
22
23
Convert between different grid representations and coordinate systems.
24
25
```python { .api }
26
def redtoreg(redgrid_data, lonsperlat, missval=None):
27
"""
28
Convert reduced Gaussian grid data to regular Gaussian grid.
29
30
Uses linear interpolation to expand reduced grid data to a regular grid
31
with the same number of latitudes and max(lonsperlat) longitudes.
32
33
Parameters:
34
- redgrid_data: array-like, 1D data array on reduced grid
35
- lonsperlat: array-like, number of longitudes at each latitude
36
- missval: float, optional, missing value (default: numpy.nan)
37
38
Returns:
39
numpy.ndarray, 2D array on regular grid (nlats, nlons)
40
"""
41
```
42
43
Usage example:
44
```python
45
import pygrib
46
import numpy as np
47
48
# Example reduced grid parameters
49
nlats = 48 # Number of latitude circles
50
lonsperlat = np.array([20, 25, 32, 40, 45, 48, 50, 52, ...]) # Lons per lat
51
52
# Simulated reduced grid data (in practice, from GRIB message)
53
total_points = lonsperlat.sum()
54
redgrid_data = np.random.randn(total_points)
55
56
# Convert to regular grid
57
reggrid_data = pygrib.redtoreg(redgrid_data, lonsperlat)
58
print(f"Regular grid shape: {reggrid_data.shape}") # (nlats, max(lonsperlat))
59
60
# Handle missing values
61
redgrid_with_missing = redgrid_data.copy()
62
redgrid_with_missing[100:110] = -999.0 # Insert missing values
63
reggrid_data = pygrib.redtoreg(redgrid_with_missing, lonsperlat, missval=-999.0)
64
```
65
66
### Date/Time Conversions
67
68
Convert between Julian day numbers and Python datetime objects.
69
70
```python { .api }
71
def julian_to_datetime(jd):
72
"""
73
Convert Julian day number to Python datetime object.
74
75
Parameters:
76
- jd: float, Julian day number
77
78
Returns:
79
datetime.datetime object
80
"""
81
82
def datetime_to_julian(d):
83
"""
84
Convert Python datetime object to Julian day number.
85
86
Parameters:
87
- d: datetime.datetime, datetime object
88
89
Returns:
90
float, Julian day number
91
"""
92
```
93
94
Usage example:
95
```python
96
import pygrib
97
from datetime import datetime
98
99
# Convert Julian day to datetime
100
julian_day = 2459580.5 # Example Julian day
101
dt = pygrib.julian_to_datetime(julian_day)
102
print(f"Julian day {julian_day} = {dt}")
103
104
# Convert datetime to Julian day
105
dt = datetime(2022, 1, 15, 12, 0, 0)
106
jd = pygrib.datetime_to_julian(dt)
107
print(f"DateTime {dt} = Julian day {jd}")
108
109
# Round-trip conversion
110
original_dt = datetime(2023, 6, 15, 18, 30, 0)
111
julian = pygrib.datetime_to_julian(original_dt)
112
converted_dt = pygrib.julian_to_datetime(julian)
113
print(f"Original: {original_dt}")
114
print(f"Converted: {converted_dt}")
115
```
116
117
### Gaussian Grid Utilities
118
119
Calculate Gaussian latitudes for meteorological grids.
120
121
```python { .api }
122
def gaulats(nlats):
123
"""
124
Compute Gaussian latitudes for specified number of latitude circles.
125
126
Returns the latitudes of a Gaussian grid with nlats latitude circles
127
between the poles. Used in global meteorological models.
128
129
Parameters:
130
- nlats: int, number of latitude circles
131
132
Returns:
133
numpy.ndarray, Gaussian latitudes in degrees (north to south)
134
"""
135
```
136
137
Usage example:
138
```python
139
import pygrib
140
import numpy as np
141
142
# Calculate Gaussian latitudes for different resolutions
143
for n in [32, 64, 96, 128]:
144
lats = pygrib.gaulats(n)
145
print(f"N{n} grid: {n} latitudes from {lats[0]:.2f}° to {lats[-1]:.2f}°")
146
147
# Use with reduced Gaussian grid
148
nlats = 48
149
gaussian_lats = pygrib.gaulats(nlats)
150
lonsperlat = np.full(nlats, 96) # 96 longitudes at each latitude
151
152
# Create coordinate meshgrid for plotting
153
lons = np.linspace(0, 360, 96, endpoint=False)
154
lon_grid, lat_grid = np.meshgrid(lons, gaussian_lats)
155
print(f"Grid shape: {lat_grid.shape}")
156
```
157
158
### Error Handling Configuration
159
160
Control how pygrib handles malformed or problematic GRIB files.
161
162
```python { .api }
163
def tolerate_badgrib_on():
164
"""Enable tolerance for malformed GRIB files"""
165
166
def tolerate_badgrib_off():
167
"""Disable tolerance for malformed GRIB files (default)"""
168
```
169
170
Usage example:
171
```python
172
import pygrib
173
174
# Enable tolerance for bad GRIB files
175
pygrib.tolerate_badgrib_on()
176
177
try:
178
# This might work even with slightly corrupted files
179
grbs = pygrib.open('potentially_bad_file.grb')
180
for grb in grbs:
181
print(grb)
182
grbs.close()
183
except Exception as e:
184
print(f"Even with tolerance, file is too corrupted: {e}")
185
186
# Disable tolerance (restore strict checking)
187
pygrib.tolerate_badgrib_off()
188
```
189
190
### Multi-Field Message Support
191
192
Control handling of multi-field GRIB messages (messages containing multiple parameters).
193
194
```python { .api }
195
def multi_support_on():
196
"""Enable multi-field message support"""
197
198
def multi_support_off():
199
"""Disable multi-field message support"""
200
```
201
202
Usage example:
203
```python
204
import pygrib
205
206
# Enable multi-field support for files that contain them
207
pygrib.multi_support_on()
208
209
grbs = pygrib.open('multi_field_file.grb')
210
print(f"Multi-field messages: {grbs.has_multi_field_msgs}")
211
212
# Process multi-field messages (use with caution with indexes)
213
for grb in grbs:
214
print(f"Message {grb.messagenumber}: {grb}")
215
216
grbs.close()
217
218
# Disable multi-field support if not needed
219
pygrib.multi_support_off()
220
```
221
222
### ECCODES Configuration
223
224
Configure paths and settings for the underlying ECCODES library.
225
226
```python { .api }
227
def set_definitions_path(eccodes_definition_path):
228
"""
229
Set path to ECCODES definition files.
230
231
Parameters:
232
- eccodes_definition_path: str, path to ECCODES definitions directory
233
"""
234
235
def get_definitions_path():
236
"""
237
Get current path to ECCODES definition files.
238
239
Returns:
240
str, path to ECCODES definitions directory
241
"""
242
```
243
244
Usage example:
245
```python
246
import pygrib
247
import os
248
249
# Check current definitions path
250
current_path = pygrib.get_definitions_path()
251
print(f"Current ECCODES definitions path: {current_path}")
252
253
# Set custom definitions path (if needed)
254
custom_path = "/usr/local/share/eccodes/definitions"
255
if os.path.exists(custom_path):
256
pygrib.set_definitions_path(custom_path)
257
print(f"Set definitions path to: {pygrib.get_definitions_path()}")
258
else:
259
print("Custom path not found, using default")
260
```
261
262
### Date/Time Message Utilities
263
264
Set computed date/time attributes on GRIB messages.
265
266
```python { .api }
267
def setdates(grb):
268
"""
269
Set analDate and validDate attributes on gribmessage.
270
271
Computes analysis and valid dates from GRIB keys like
272
julianDay, forecastTime, and fcstimeunits.
273
274
Parameters:
275
- grb: gribmessage, message to update
276
277
Modifies message in-place by setting analDate and validDate attributes
278
"""
279
```
280
281
Usage example:
282
```python
283
import pygrib
284
285
grbs = pygrib.open('forecast.grb')
286
grb = grbs.readline()
287
288
# Check if dates are already set
289
print(f"Analysis date before: {getattr(grb, 'analDate', 'Not set')}")
290
print(f"Valid date before: {getattr(grb, 'validDate', 'Not set')}")
291
292
# Set computed dates
293
pygrib.setdates(grb)
294
295
# Check computed dates
296
print(f"Analysis date: {grb.analDate}")
297
print(f"Valid date: {grb.validDate}")
298
print(f"Forecast time: {grb['forecastTime']} {grb.fcstimeunits}")
299
```
300
301
## Advanced Utility Examples
302
303
### Processing Different Grid Types
304
305
```python
306
import pygrib
307
308
grbs = pygrib.open('mixed_grids.grb')
309
310
for grb in grbs:
311
grid_type = grb['gridType']
312
313
if grid_type == 'reduced_gg':
314
# Handle reduced Gaussian grid
315
print(f"Reduced Gaussian: {grb['name']}")
316
317
# Get reduced grid info
318
lonsperlat = grb['pl'] # Points per latitude
319
data_1d = grb['values'] # 1D data array
320
321
# Convert to regular grid if needed
322
reggrid_data = pygrib.redtoreg(data_1d, lonsperlat)
323
print(f"Expanded to regular grid: {reggrid_data.shape}")
324
325
elif grid_type == 'regular_ll':
326
# Handle regular lat/lon grid
327
print(f"Regular lat/lon: {grb['name']}")
328
data_2d = grb['values'] # Already 2D
329
lats, lons = grb.latlons()
330
331
elif grid_type == 'lambert':
332
# Handle Lambert conformal grid
333
print(f"Lambert conformal: {grb['name']}")
334
if grb.projparams:
335
print(f"Projection: {grb.projparams}")
336
```
337
338
### Batch Date Processing
339
340
```python
341
import pygrib
342
from datetime import datetime, timedelta
343
344
# Process forecast file and standardize dates
345
grbs = pygrib.open('forecast.grb')
346
347
reference_time = datetime(2023, 1, 1, 0, 0)
348
processed_messages = []
349
350
for grb in grbs:
351
# Ensure dates are computed
352
pygrib.setdates(grb)
353
354
# Calculate time difference from reference
355
if grb.validDate:
356
time_diff = grb.validDate - reference_time
357
hours_diff = time_diff.total_seconds() / 3600
358
359
# Add custom time information
360
grb['hoursFromReference'] = int(hours_diff)
361
362
processed_messages.append(grb)
363
print(f"Processed: {grb['shortName']} at +{grb['forecastTime']}h")
364
365
grbs.close()
366
```