File size: 7,693 Bytes
8d032c5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 | #!/usr/bin/env python3
"""
Alternative solution using pygrib for polar stereographic GRIB files
"""
import numpy as np
import pandas as pd
def extract_with_pygrib(grib_file):
"""
Extract lat/lon and wave data using pygrib library
"""
try:
import pygrib
print(f"Opening GRIB file with pygrib: {grib_file}")
grbs = pygrib.open(grib_file)
# List all messages
print("Available messages:")
for i, grb in enumerate(grbs):
print(f"Message {i+1}: {grb}")
grbs.seek(0) # Reset to beginning
# Get first message for coordinates
grb = grbs[1] # First message
print(f"Grid type: {grb.gridType}")
print(f"Projection: {getattr(grb, 'projString', 'N/A')}")
# Get lat/lon coordinates
try:
lats, lons = grb.latlons()
print(f"Successfully extracted coordinates")
print(f"Lat shape: {lats.shape}, range: {lats.min():.3f} to {lats.max():.3f}")
print(f"Lon shape: {lons.shape}, range: {lons.min():.3f} to {lons.max():.3f}")
# Get data values
data = grb.values
print(f"Data shape: {data.shape}, range: {data.min():.3f} to {data.max():.3f}")
# Create flat arrays for lat, lon, data
lats_flat = lats.flatten()
lons_flat = lons.flatten()
data_flat = data.flatten()
# Remove any invalid data points
valid_mask = ~np.isnan(data_flat) & ~np.isnan(lats_flat) & ~np.isnan(lons_flat)
result_df = pd.DataFrame({
'latitude': lats_flat[valid_mask],
'longitude': lons_flat[valid_mask],
'wave_data': data_flat[valid_mask]
})
print(f"Created DataFrame with {len(result_df)} valid points")
grbs.close()
return result_df
except Exception as e:
print(f"Error extracting lat/lon with pygrib: {e}")
# Try alternative coordinate extraction
try:
# Some GRIB files store coordinates differently
if hasattr(grb, 'latitudeOfFirstGridPointInDegrees'):
lat_first = grb.latitudeOfFirstGridPointInDegrees
lon_first = grb.longitudeOfFirstGridPointInDegrees
print(f"First grid point: lat={lat_first}, lon={lon_first}")
if hasattr(grb, 'Ni') and hasattr(grb, 'Nj'):
ni, nj = grb.Ni, grb.Nj
print(f"Grid dimensions: {ni} x {nj}")
# Get projection parameters
if hasattr(grb, 'projParams'):
print(f"Projection parameters: {grb.projParams}")
except Exception as e2:
print(f"Error getting grid parameters: {e2}")
grbs.close()
return None
except ImportError:
print("pygrib not available. Install with: pip install pygrib")
return None
except Exception as e:
print(f"Error with pygrib: {e}")
return None
def manual_polar_stereographic_projection(grib_file):
"""
Manually implement polar stereographic coordinate calculation
"""
try:
import pygrib
grbs = pygrib.open(grib_file)
grb = grbs[1]
# Get polar stereographic parameters
params = {}
attr_names = [
'latitudeOfFirstGridPointInDegrees',
'longitudeOfFirstGridPointInDegrees',
'DxInMetres',
'DyInMetres',
'orientationOfTheGridInDegrees',
'latitudeWhereDxAndDyAreSpecifiedInDegrees',
'Ni', 'Nj'
]
for attr in attr_names:
if hasattr(grb, attr):
params[attr] = getattr(grb, attr)
print(f"{attr}: {params[attr]}")
# Manual coordinate calculation for polar stereographic
if 'Ni' in params and 'Nj' in params:
ni, nj = int(params['Ni']), int(params['Nj'])
# Get grid spacing
dx = params.get('DxInMetres', 25000) # Default 25km
dy = params.get('DyInMetres', 25000)
# Create coordinate arrays
x = np.arange(ni) * dx
y = np.arange(nj) * dy
X, Y = np.meshgrid(x, y)
# Convert from polar stereographic to lat/lon
# This is a simplified version - you may need a proper projection library
lat_origin = params.get('latitudeWhereDxAndDyAreSpecifiedInDegrees', 90.0)
lon_origin = params.get('orientationOfTheGridInDegrees', 0.0)
print(f"Grid origin: lat={lat_origin}, lon={lon_origin}")
print(f"Grid spacing: dx={dx}m, dy={dy}m")
print(f"Grid size: {ni} x {nj}")
# For proper conversion, you'd use pyproj or similar
try:
from pyproj import Proj, transform
# Define polar stereographic projection
proj_polar = Proj(
proj='stere',
lat_0=lat_origin,
lon_0=lon_origin,
lat_ts=lat_origin,
ellps='sphere'
)
proj_latlon = Proj(proj='latlong', ellps='sphere')
# Transform coordinates
lons, lats = transform(proj_polar, proj_latlon, X.flatten(), Y.flatten())
lats = np.array(lats).reshape(nj, ni)
lons = np.array(lons).reshape(nj, ni)
# Get data
data = grb.values
# Create DataFrame
result_df = pd.DataFrame({
'latitude': lats.flatten(),
'longitude': lons.flatten(),
'wave_data': data.flatten()
})
# Remove invalid points
valid_mask = ~np.isnan(result_df['wave_data'])
result_df = result_df[valid_mask]
print(f"Successfully calculated coordinates for {len(result_df)} points")
grbs.close()
return result_df
except ImportError:
print("pyproj not available for coordinate transformation")
grbs.close()
return None
grbs.close()
return None
except Exception as e:
print(f"Error in manual projection: {e}")
return None
# Example usage
if __name__ == "__main__":
grib_file = "/tmp/tmpr004q4kw.grib2" # Your file path
print("=== Trying pygrib extraction ===")
result1 = extract_with_pygrib(grib_file)
if result1 is not None:
print(f"Success with pygrib! {len(result1)} points extracted")
print(result1.head())
else:
print("=== Trying manual polar stereographic ===")
result2 = manual_polar_stereographic_projection(grib_file)
if result2 is not None:
print(f"Success with manual projection! {len(result2)} points extracted")
print(result2.head())
else:
print("All methods failed. Consider using wgrib2 conversion first.")
|