embedding ICPAC [Precipitation] FORECASTING into STORM

load some libraries…

[25]:
import gc
import glob
import numpy as np
import pandas as pd
import xarray as xr
import matplotlib.pyplot as plt
from pathlib import Path

define some constants

[18]:
sdic = {'JF': [1, 2], 'MAM': [3, 4, 5], 'JJAS': [6, 7, 8, 9], 'OND': [10, 11, 12]}

seas = 'MAM'
nsim = 2
nrun = 5

outp = '/home/cuwalid/SETS/sims/'
outp = '/home/cuwalid/training/forecast/regional/dataset/pre/pools/'
fdir = './forecast/'
Path(fdir).mkdir(parents=True, exist_ok=True)

fetch the data

[11]:
# fetch the pools
pool = list(map(lambda x: sorted(glob.glob(f'{outp}/{x}/*_MAM.nc')),
                ['poolA', 'poolN', 'poolB']))
# create the combinations
allp = np.asarray([f'{x}+{y}+{z}' for x in pool[0] for
                   y in pool[1] for z in pool[2]])
# selected random combinations
what = np.random.default_rng().choice(allp, size=nsim, replace=False).tolist()

# read the ICPAC terciles
icpac = xr.open_dataset('./ICPAC_precipForecast_2022-MAM.nc', chunks='auto',
    decode_cf=True, mask_and_scale=True,)# drop_variables=['spatial_ref'],)
icpac = (icpac.tercile / 100).compute()

what are the combos?

[13]:
print(np.asarray(what))
['/home/manuel/SETS/sims//poolA/2015_MAM.nc+/home/manuel/SETS/sims//poolN/2005_MAM.nc+/home/manuel/SETS/sims//poolB/2024_MAM.nc'
 '/home/manuel/SETS/sims//poolA/2014_MAM.nc+/home/manuel/SETS/sims//poolN/2004_MAM.nc+/home/manuel/SETS/sims//poolB/2021_MAM.nc'
 '/home/manuel/SETS/sims//poolA/2012_MAM.nc+/home/manuel/SETS/sims//poolN/2012_MAM.nc+/home/manuel/SETS/sims//poolB/2020_MAM.nc']

helper functions…

[14]:
# sample either 0, 1, or 2 given some PROBS (probabilities)
def samp_ter(probs):
    prabs = np.random.default_rng().choice(
        [0, 1, 2], size=1, replace=True, p=probs, axis=0, shuffle=False,)
    return prabs[0]

# retrieve the pool-file given 0, 1, or 2
def CH_OLL(above, normal, below, map_ter, n_files):
    cual = [above, normal, below][map_ter]
    return cual

main function:

[20]:
def fore_cast(chain, yy, ii):
    print(f'\ncombo: {chain}\n')
    filo = chain.split('+')
    fool = list(map(lambda x: xr.open_dataset(x, chunks='auto',
        decode_cf=True, mask_and_scale=True,), filo))

    suma = fool[1].precipitation.load().copy(deep=True)
    suma[:] = 0.0
    suma = suma.drop_vars('time')

    for i in range(nrun):
        print(f'iter.. {i+1}')
        some_a = xr.apply_ufunc(
            samp_ter, icpac,
            dask='allowed', vectorize=True,
            input_core_dims=[['p'],],
            output_core_dims=[[],],
            )
        some_b = xr.apply_ufunc(
            CH_OLL,
            fool[0].precipitation, fool[1].precipitation, fool[2].precipitation, some_a,
            kwargs={'n_files': 3.14},
            dask_gufunc_kwargs={'allow_rechunk':True, 'output_sizes':{'time':2208}},
            output_dtypes=['f4'],
            dask='parallelized', vectorize=True,
            input_core_dims=[['time'], ['time'], ['time'], [],],
            exclude_dims=set(['time',]),
            output_core_dims=[['time',]],
            )
        step = some_b.compute()
        # weighted sum
        suma = suma + step / nrun

    # data for netcdf
    stamp = pd.date_range(
        start=f'{sdic[seas][0]}/1/{yy}', end=f'{sdic[seas][-1] + 1}/1/{yy}',
        freq='1h', inclusive='left'
        )
    suma['time'] = stamp
    suma = suma.to_dataset(name='precipitation')
    suma.rio.write_crs('EPSG:4326', inplace=True)

# homogenize names
    suma.precipitation.attrs['long_name'] = 'precipitation_forecasting'
    suma.precipitation.attrs['units'] = 'mm/h'
    suma.lat.attrs['long_name'] = 'latitude'
    suma.lat.attrs['valid_min'] = -90.0
    suma.lat.attrs['valid_max'] = 90.0
    suma.lat.attrs['bounds'] = 'lat_bnds'
    suma.lon.attrs['long_name'] = 'longitude'
    suma.lon.attrs['valid_min'] = -180.0
    suma.lon.attrs['valid_max'] = 180.0
    suma.lon.attrs['bounds'] = 'lon_bnds'
    suma.time.attrs['standard_name'] = 'time'
# set.up PRECIPITATION
    suma.precipitation.encoding['dtype'] = 'f4'
    suma.precipitation.encoding['zlib'] = True
    suma.precipitation.encoding['complevel'] = 9
    suma.precipitation.encoding['contiguous'] = False
    suma.precipitation.encoding['least_significant_digit'] = 2
    suma.precipitation.encoding['shuffle'] = True
    suma.precipitation.encoding['blosc'] = True
# export to NC
    namo = f'{fdir}/{yy}_{seas}_{ii}.nc'
    print('\nXporting NC.file...')
    suma.to_netcdf(namo, mode='w')
    gc.collect()

run the precipitation forecast!

[21]:
year = 2024 + np.r_[0:len(what)]
list(map(fore_cast, what, year, range(len(what)) ))

combo: /home/manuel/SETS/sims//poolA/2015_MAM.nc+/home/manuel/SETS/sims//poolN/2005_MAM.nc+/home/manuel/SETS/sims//poolB/2024_MAM.nc

iter.. 1
iter.. 2
iter.. 3
iter.. 4
iter.. 5
iter.. 6
iter.. 7

combo: /home/manuel/SETS/sims//poolA/2014_MAM.nc+/home/manuel/SETS/sims//poolN/2004_MAM.nc+/home/manuel/SETS/sims//poolB/2021_MAM.nc

iter.. 1
iter.. 2
iter.. 3
iter.. 4
iter.. 5
iter.. 6
iter.. 7

combo: /home/manuel/SETS/sims//poolA/2012_MAM.nc+/home/manuel/SETS/sims//poolN/2012_MAM.nc+/home/manuel/SETS/sims//poolB/2020_MAM.nc

iter.. 1
iter.. 2
iter.. 3
iter.. 4
iter.. 5
iter.. 6
iter.. 7
[21]:
[None, None, None]

let’s check the forecast now

[23]:
# pick one of the outputs that were produced in "./forecast"
fc = xr.open_dataset(f'{fdir}/{"2024_MAM_0.nc"}', chunks='auto',
                     decode_cf=True, mask_and_scale=True,)
print(fc)
fcs = fc.precipitation.sum(dim=('time')).compute()
<xarray.Dataset>
Dimensions:        (lat: 225, lon: 240, time: 2208)
Coordinates:
  * lat            (lat) float32 -6.95 -6.85 -6.75 -6.65 ... 15.25 15.35 15.45
  * lon            (lon) float32 28.05 28.15 28.25 28.35 ... 51.75 51.85 51.95
  * time           (time) datetime64[ns] 2024-03-01 ... 2024-05-31T23:00:00
Data variables:
    precipitation  (time, lat, lon) float32 dask.array<chunksize=(1451, 147, 157), meta=np.ndarray>
    spatial_ref    int64 ...

the plotting happens here!

[27]:
# plot
fig, ax = plt.subplots(figsize=(6, 5), dpi=150)
fcs.plot(
    x='lon', y='lat', cmap='gist_ncar_r', add_colorbar=True, vmin=50, vmax=2150,
    levels=22, robust=True,# ax=ax,
    cbar_kwargs={'shrink':0.75,
        'aspect':27, 'label':'precipitation  [mm/season]', 'pad':+.01,})
plt.show()
#plt.savefig(f'myFig.png', bbox_inches='tight', pad_inches=0.02)
../../_images/notebooks_STORM_10_sampling_18_0.png