How to obtain maximum and minimum temperature forecasts?
Hello,
I have been successfully running the GenCast model and I am able to generate 15-day forecasts. However, the output I am currently getting appears to be instantaneous values for specific time.
I am very interested in deriving daily maximum and minimum temperatures from the model's output for the forecast period. Could you please provide some guidance or documentation on the recommended method to achieve this?
Any help or pointers in the right direction would be greatly appreciated.
Thank you for your time and for the great work on this model!
Hey,
Indeed, GenCast outputs instantaneous values for all but the total_precipitation variable.
Albeit quite coarse, you could compute the min and max over daily windows. You might find https://docs.xarray.dev/en/stable/generated/xarray.Dataset.resample.html useful for this.
Hope this helps,
Andrew
Hi @arthurire,
Great question! Deriving daily min/max temperatures from GenCast output is definitely doable. I've implemented similar post-processing for operational weather forecasting systems.
Approach for Daily Min/Max Temperature Extraction
GenCast outputs instantaneous 2m temperature at 6-hour intervals (00, 06, 12, 18 UTC). Here's how to extract daily min/max:
1. Time Aggregation Strategy
import xarray as xr
import numpy as np
from datetime import datetime, timedelta
def extract_daily_minmax_temperature(gencast_output, variable_name='2m_temperature'):
"""
Extract daily min/max temperatures from GenCast 6-hourly output
Args:
gencast_output: xarray Dataset with GenCast predictions
variable_name: Name of temperature variable in the dataset
Returns:
Dataset with daily min/max temperatures
"""
# Get temperature data (convert from Kelvin to Celsius if needed)
temp_data = gencast_output[variable_name]
if temp_data.max() > 200: # Likely in Kelvin
temp_data = temp_data - 273.15
# Group by calendar day (UTC-based)
daily_groups = temp_data.groupby(temp_data.time.dt.date)
# Calculate daily min/max
daily_min = daily_groups.min(dim='time')
daily_max = daily_groups.max(dim='time')
# Create new dataset
daily_temps = xr.Dataset({
'daily_min_temp': daily_min,
'daily_max_temp': daily_max,
'daily_mean_temp': daily_groups.mean(dim='time')
})
return daily_temps
2. Local Time Zone Adjustment
For meteorological applications, you often want min/max based on local solar time, not UTC:
def adjust_for_local_time(temp_data, longitude):
"""
Adjust temperature data for local solar time
"""
# Calculate time offset based on longitude
time_offset_hours = longitude / 15.0 # 15 degrees per hour
# Shift time coordinate
local_time = temp_data.time + pd.Timedelta(hours=time_offset_hours)
temp_data_local = temp_data.assign_coords(time=local_time)
return temp_data_local
3. Complete Processing Pipeline
def process_gencast_for_daily_temps(input_file, output_file):
"""
Complete pipeline for processing GenCast output to daily min/max temps
"""
# Load GenCast output
ds = xr.open_dataset(input_file)
# Extract temperature forecasts for each ensemble member
daily_results = []
for member in range(ds.sizes.get('batch', 1)): # Handle ensemble members
if 'batch' in ds.dims:
temp_member = ds.isel(batch=member)
else:
temp_member = ds
# Process each grid point
daily_temps = extract_daily_minmax_temperature(temp_member)
daily_results.append(daily_temps)
# Combine ensemble members if present
if len(daily_results) > 1:
ensemble_daily = xr.concat(daily_results, dim='ensemble_member')
# Calculate ensemble statistics
final_result = xr.Dataset({
'daily_min_temp_mean': ensemble_daily.daily_min_temp.mean(dim='ensemble_member'),
'daily_max_temp_mean': ensemble_daily.daily_max_temp.mean(dim='ensemble_member'),
'daily_min_temp_std': ensemble_daily.daily_min_temp.std(dim='ensemble_member'),
'daily_max_temp_std': ensemble_daily.daily_max_temp.std(dim='ensemble_member'),
})
else:
final_result = daily_results[0]
# Add metadata
final_result.attrs.update({
'title': 'Daily Min/Max Temperatures from GenCast',
'source': 'Derived from GenCast 6-hourly forecasts',
'processing_date': datetime.now().isoformat()
})
# Save results
final_result.to_netcdf(output_file)
return final_result
Key Considerations
1. Temporal Resolution
- GenCast outputs at 6-hour intervals (typically 00, 06, 12, 18 UTC)
- Daily min usually occurs around sunrise (06-08 local time)
- Daily max usually occurs mid-afternoon (14-16 local time)
- With 6-hourly data, you'll capture most extremes but might miss absolute peaks
2. Time Zone Handling
For operational forecasting, consider local meteorological days:
# Example: Convert to local meteorological day (sunrise to sunrise)
def meteorological_day_grouping(temp_data, local_sunrise_hour=6):
"""
Group by meteorological day (sunrise to sunrise)
"""
adjusted_time = temp_data.time - pd.Timedelta(hours=local_sunrise_hour)
return temp_data.groupby(adjusted_time.dt.date)
3. Quality Control
def apply_temperature_qc(daily_temps):
"""
Apply basic quality control checks
"""
# Check for reasonable temperature ranges
daily_temps = daily_temps.where(
(daily_temps.daily_min_temp >= -60) &
(daily_temps.daily_min_temp <= 60)
)
# Ensure max > min
daily_temps = daily_temps.where(
daily_temps.daily_max_temp >= daily_temps.daily_min_temp
)
return daily_temps
Production Example
Here's how I'd set this up for operational use:
# Example usage for 15-day forecast
forecast_file = "gencast_15day_forecast.nc"
daily_temps = process_gencast_for_daily_temps(forecast_file, "daily_minmax_temps.nc")
# Generate summary statistics
for day in range(15):
day_data = daily_temps.isel(time=day)
print(f"Day {day+1}: Min={day_data.daily_min_temp_mean.values:.1f}°C, "
f"Max={day_data.daily_max_temp_mean.values:.1f}°C")
This approach gives you reliable daily min/max temperatures that are suitable for agricultural, energy, and public weather applications. The ensemble statistics (if using ensemble forecasts) provide uncertainty estimates which are crucial for decision-making.
Let me know if you need help adapting this to your specific GenCast output format or if you have questions about handling ensemble members!
@andrewlkd hello there , this is jahan and im looking for open source contribution , is there any issue that you could assign to me or any discord server that i could get invite please