Forecast Processing
forecast_processing.ForecastClassifier module
Simple Algorithm to classify forecasts based on number of opposing winds. Similar to method used in RadioWinds.
For now, we are assuming looking at 6 hour increments for a 24 hour window (4 time instances)
For each time instance, calculate opposing winds with n_sectors (default is 8)
Levels are based on the netcdf file and pressure range. (Synth will have more levels than ERA5)
- class forecast_processing.ForecastClassifier.ForecastClassifier[source]
Bases:
object
Classifies forecasts based on opposing wind patterns.
- - determine_opposing_winds
Identify opposing wind levels and directions.
- - determine_OW_Rate
Calculate the opposing wind rate for a forecast subset.
- determine_OW_Rate(forecast_subset)[source]
Calculate the opposing wind rate for a forecast subset over a 24-hour window.
- Parameters:
forecast_subset (Forecast_Subset) – Subset of the forecast.
- Returns:
scores (list): Number of opposing wind levels at each time interval.
score (float): Normalized opposing wind rate.
- Return type:
tuple
- determine_opposing_winds(wd, levels, n_sectors)[source]
Identify opposing wind levels and directions from wind data.
- Parameters:
wd (numpy.ndarray) – Wind direction array (degrees).
levels (numpy.ndarray) – Pressure or altitude levels.
n_sectors (int) – Number of angular sectors.
- Returns:
opposing_wind_directions (numpy.ndarray): Indices of opposing wind directions.
opposing_wind_levels (numpy.ndarray): Levels with opposing winds.
- Return type:
tuple
forecast_processing.forecast module
Current Assumptions for Synth and ERA5 forecast
Both forecasts are downloaded for the same regions (0.25 degree resolution), same altitude band (config)
Synth Forecast is 1 month @ 12 hour intervals
Synth Forecast is 6 months @ 3 hour intervals
- class forecast_processing.forecast.Forecast(filename, forecast_type=None, month=None, timewarp=None)[source]
Bases:
object
Loads a full ERA5 or synthetic forecast into memory.
This class handles large-scale climate forecasts used for simulations, supporting operations like subsetting, time adjustments, and aligning forecasts for simulating.
Download from https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-era5-pressure-levels?tab=form
- forecast_type
Type of forecast (‘SYNTH’ or ‘ERA5’).
- Type:
str
- ds_original
Original dataset loaded from the forecast file.
- Type:
xarray.Dataset
- LAT_MIN, LAT_MAX
Latitude range of the forecast.
- Type:
float
- LON_MIN, LON_MAX
Longitude range of the forecast.
- Type:
float
- LEVEL_MIN, LEVEL_MAX
Pressure level range of the forecast.
- Type:
float
- TIME_MIN, TIME_MAX
Time range of the forecast.
- Type:
numpy.datetime64
- TIMEWARP(timewarp)[source]
By Default ERA5 forecasts are downloaded in 3 hour intervals, whereas Synth are in 12 hour intervals
Therefore we perform a “timewarp” to overwrite timestamps in both forecasts, while still matching up the data from the original timestamps with the new timestamps.
For example:
Synth (original): 2024-01-01 00:00:00, 2024-01-01 12:00:00, 2024-01-02 00:00:00, 2024-01-02 12:00:00 *original timestamps will be overwritten with the timewarp function Synth (timewarp) : 2024-01-01 00:00:00, 2024-01-01 03:00:00, 2024-01-01 06:00:00, 2024-01-01 09:00:00 *to line up with the ERA5 ERA5: 2024-01-01 00:00:00, 2024-01-01 03:00:00, 2024-01-01 06:00:00, 2024-01-01 09:00:00
Timewarping will typically only be used for Synth Forecast due to their sparse timing
- drop_era5_months(month)[source]
Filter ERA5 forecast to match the specified month and reduce time intervals to 12 hours. This is a bit hardcoded rn
By default, ERA5 forecasts are downloaded in 6 month @ 3 hour intervals. Since many simulations require both Synth and ERA5, we need change ERA5 to 12 hour intervals
- Parameters:
month (int) – Month to retain in the dataset.
- Raises:
Exception – If the specified month is not within the forecast’s range.
- class forecast_processing.forecast.Forecast_Subset(Forecast)[source]
Bases:
object
Creates a subset of the master forecast for efficient processing and simulation.
- lat_central
Central latitude of the subset.
- Type:
float
- lon_central
Central longitude of the subset.
- Type:
float
- start_time
Start time of the subset.
- Type:
numpy.datetime64
- ds
Subset dataset.
- Type:
xarray.Dataset
- assign_coord(lat, lon, timestamp)[source]
Assign central coordinates and timestamp for the subset.
- Parameters:
lat (float) – Central latitude.
lon (float) – Central longitude.
timestamp (numpy.datetime64) – Start timestamp.
- getNewCoord(Balloon, SimulationState, dt)[source]
Determines new coordinate based on the flow at the current position and integrates forward int time via dt
- get_alt_from_pressure(pressure)[source]
Get average altitude from ERA5 for a forecast subset. Average is taken since z is geopotential converted to altitude
- Parameters:
pressure (float) – atmospheric pressure.
- Returns:
corresponding altitude (from geopotential) for pressure level
- Return type:
alt
- get_unixtime(dt64)[source]
Convert numpy.datetime64 to Unix time in seconds.
- Parameters:
dt64 (numpy.datetime64) – DateTime value.
- Returns:
Unix timestamp in seconds.
- Return type:
int
- interpolate_wind(alt, z, u, v)[source]
Interpolates the u and v wind components given a 3D coordinate (lat,lon,alt) Currently only interpolating in the Z direction. No smoothing for time or horizontal changes.
- np_lookup(lat, lon, time)[source]
Perform a fast lookup for wind data using numpy arrays.
- Parameters:
lat (float) – Latitude.
lon (float) – Longitude.
time (numpy.datetime64) – Time.
- Returns:
Altitude, u-component, and v-component of the wind.
- Return type:
tuple
- randomize_coord(np_rng)[source]
Generates a random coordinate to centralize the Forecast Subset, and stores the coordinate for look up by other classes.
Altitude Bounds are the same as the PRIMARY FORECAST Horizontal Bounds are within 2 degrees of the min/max LAT/LON from the PRIMARY FORECAST Time Bounds are between the start time and up to 24 hours before the final timestamp of the PRIMARY FORECAST
pass np_rng to have forecasts randomize in the same order when manually setting seed
- Parameters:
np_rng (numpy.random.Generator) – Random number generator.
- subset_forecast(days=1)[source]
Subsets the Forecast to the central coordinate. This assume a random coordinate or user input coordinate has already been assigned.
Horizontal Bounds are determined by the relative distance (converted to lat/lon degrees) Altitude is the same Time is 24 hours
Converts the DataSet to a numpy array for faster processing
- Parameters:
days (int) – Number of days to include in the subset.
forecast_processing.forecast_test module
Tests to make sure that the manual interpretation methods match with xarray, scipy, and numpy methods
Our manually written interpolation methods are faster for simulating
forecast_processing.forecast_visualizer module
Create 3D visualizations of ERA5 or Synth forecast with colored quiver plots. Can shoose between coloring via speed or direction (default is direction).
Also gives an example of doing a side by side comparison of levels between ERA5 and Synth
As well as how to make GIFs
- class forecast_processing.forecast_visualizer.ForecastVisualizer(forecast, render_style='direction')[source]
Bases:
object
Visualizes forecast data for 3D quiver plots and comparisons.
- forecast_subset
The forecast subset to visualize.
- Type:
- render_style
Visualization style (‘direction’ or ‘speed’).
- Type:
str
- pressure_levels
Pressure levels in the forecast subset.
- Type:
list
- alts2
Altitudes corresponding to pressure levels.
- Type:
numpy.ndarray
- flow_field
Processed 3D flow field data.
- Type:
numpy.ndarray
- levels
Altitude levels for plotting.
- Type:
numpy.ndarray
- generate_flow_array(timestamp)[source]
Generate a 3D flow field array for visualization.
- Parameters:
timestamp (numpy.datetime64) – Timestamp for the forecast data.
- map_pres2alt()[source]
Map pressure levels to altitudes using standard atmospheric conditions. (Rough approximation)
- Returns:
List of altitudes corresponding to the pressure levels.
- Return type:
list
- visualize_3d_planar_flow(ax, quiver_skip=1, altitude_quiver_skip=3, show_cbar=False, arrow_head_angle=84.9, length=0.05, arrow_length_ratio=3.5)[source]
Visualize the 3D planar flow field using quiver plots.
- Parameters:
ax (matplotlib.axes._axes.Axes) – Axes object for plotting.
quiver_skip (int, optional) – Skip factor for quiver points in x and y.
altitude_quiver_skip (int, optional) – Skip factor for altitude levels.
show_cbar (bool, optional) – Whether to display the colorbar.
arrow_head_angle (float, optional) – Angle of arrowheads in quiver plot.
length (float, optional) – Length of arrows.
arrow_length_ratio (float, optional) – Ratio of arrowhead length to arrow length.
- forecast_processing.forecast_visualizer.plot_3d_quiver(timestamp, forecast_subset, quiver_skip=2)[source]
- forecast_processing.forecast_visualizer.plot_side_by_side_levels()[source]
Shows an example of creating a gif of comparing individual pressure levels between Synth and ERA5 for the same date
ERA5 and Synth need to contain the same downloaded region and date windows.
We use xarrays isel method to find the matching pressure levels (since Synth is altitude based, and ERA5 is pressure based)