graphcast icon indicating copy to clipboard operation
graphcast copied to clipboard

How to obtain maximum and minimum temperature forecasts?

Open arthurire opened this issue 5 months ago • 3 comments

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!

arthurire avatar Jul 05 '25 01:07 arthurire

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

andrewlkd avatar Jul 07 '25 09:07 andrewlkd

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!

anivar avatar Jul 20 '25 18:07 anivar

@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

schrodingers-cat-T10 avatar Nov 17 '25 14:11 schrodingers-cat-T10