import xarray as xr
import numpy as np
import scipy.stats as stats
Function to calculate SPI for a given location’s precipitation time series
def calculate_spi(precipitation, scale=1):
“”"
Calculates SPI for a given precipitation time series using a Gamma distribution.
Args:
precipitation: Precipitation time series (monthly data) for a specific location.
scale: The scale (number of months) over which to calculate the SPI (1 for 1-month SPI, etc.).
Returns:
SPI values for the given time series.
"""
# Filter out zeros or negative values
precip_data = precipitation[precipitation > 0]
if len(precip_data) < 2: # Not enough data to fit a distribution
return np.nan * np.ones_like(precip_data)
# Fit a Gamma distribution
shape, loc, scale_param = stats.gamma.fit(precip_data, floc=0) # Fit Gamma distribution
# Calculate the cumulative distribution function (CDF) for each value
cdf_values = stats.gamma.cdf(precip_data, shape, loc, scale_param)
# Calculate SPI as the inverse of the CDF
spi_values = stats.norm.ppf(cdf_values)
return spi_values
Function to read the NetCDF file and extract monthly precipitation data
def extract_precipitation_data(netcdf_file):
“”"
Extract precipitation data from a NetCDF file.
Args:
netcdf_file: Path to the NetCDF file containing monthly precipitation data.
Returns:
Precipitation data as a xarray DataArray.
"""
# Open the NetCDF file using xarray
dataset = xr.open_dataset(netcdf_file)
# Check the available variables and adjust the variable name accordingly
print(dataset.variables) # You can inspect the variable names this way
# Assuming the variable name for precipitation in the NetCDF is 'precipitation' or 'pr'
precip = dataset['precipitation'] # Change 'precipitation' to the actual variable name if needed
# Ensure it's monthly data and handle time axis
precip = precip.sel(time=slice("1981-01-16", "2024-01-16")) # Adjust time range as needed
return precip
Function to calculate SPI for the entire dataset (across multiple locations)
def calculate_spi_for_all_locations(netcdf_file, scale=1):
“”"
Calculate SPI for all locations in the NetCDF file.
Args:
netcdf_file: Path to the NetCDF file containing monthly precipitation data.
scale: Number of months over which to calculate SPI (1 for 1-month SPI, etc.).
Returns:
SPI values for all locations as a xarray DataArray.
"""
# Extract precipitation data from NetCDF
precip = extract_precipitation_data(netcdf_file)
# Initialize an empty array to store SPI values
spi_values = np.zeros_like(precip.values)
# Loop through all locations and calculate SPI
for i in range(precip.shape[1]): # Loop over latitudes
for j in range(precip.shape[2]): # Loop over longitudes
precip_series = precip[:, i, j].values
spi_values[:, i, j] = calculate_spi(precip_series, scale=scale)
# Return SPI values as a DataArray with the same coordinates
spi_data = xr.DataArray(spi_values, coords=precip.coords, dims=precip.dims)
return spi_data
Example usage
netcdf_file = ‘C:/Users/HP EliteBook/Downloads/data3.nc’
scale = 1 # 1-month SPI, change as needed (e.g., for 3-month SPI, scale=3)
spi_data = calculate_spi_for_all_locations(netcdf_file, scale)
Optionally, save the resulting SPI data to a new NetCDF file
spi_data.to_netcdf(‘spi_output.nc’)
Plot or analyze the SPI data
print(spi_data)