09 Exercises 2: WA state hourly data
Contents
09 Exercises 2: WA state hourly data¶
UW Geospatial Data Analysis
CEE498/CEWA599
David Shean
import os
from glob import glob
import numpy as np
import xarray as xr
import pandas as pd
import geopandas as gpd
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
curr_y = pd.to_datetime("today").year
curr_y
2022
Load the WA temperature, precipitation and snow depth products¶
Note: these are extracted for 12:00 UTC
Really want daily averages for much of this, but I didn’t have time to go back and requery ERA5
Let’s use what we have to play around
outdir = 'era5_data'
merge_fn = os.path.join(outdir, 'WA_ERA5-Land_hourly_1950-2022_6hr.nc')
Optional: start Dask cluster using Jupterlab interface, connect to client¶
Note this will use all CPUs on the shared node by default
Maybe best to avoid during lab session
#Start from Jupyterlab, copy paste corresponding code
#from dask.distributed import Client, LocalCluster
#cluster = LocalCluster() # Launches a scheduler and workers locally
#client = Client(cluster) # Connect to distributed cluster and override default
#Set up dask chunking
chunks = {'longitude':27, 'latitude':19}
wa_merge = xr.open_dataset(merge_fn, chunks=chunks)
wa_merge
<xarray.Dataset>
Dimensions: (longitude: 81, latitude: 38, time: 105191)
Coordinates:
* longitude (longitude) float32 -124.8 -124.7 -124.6 ... -116.9 -116.8 -116.8
* latitude (latitude) float32 49.2 49.1 49.0 48.9 ... 45.8 45.7 45.6 45.5
* time (time) datetime64[ns] 1950-01-01T06:00:00 ... 2021-12-31T18:00:00
Data variables:
t2m (time, latitude, longitude) float32 dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
sde (time, latitude, longitude) float32 dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
tp (time, latitude, longitude) float32 dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
Attributes:
Conventions: CF-1.6
history: 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmw...- longitude: 81
- latitude: 38
- time: 105191
- longitude(longitude)float32-124.8 -124.7 ... -116.8 -116.8
- units :
- degrees_east
- long_name :
- longitude
array([-124.75, -124.65, -124.55, -124.45, -124.35, -124.25, -124.15, -124.05, -123.95, -123.85, -123.75, -123.65, -123.55, -123.45, -123.35, -123.25, -123.15, -123.05, -122.95, -122.85, -122.75, -122.65, -122.55, -122.45, -122.35, -122.25, -122.15, -122.05, -121.95, -121.85, -121.75, -121.65, -121.55, -121.45, -121.35, -121.25, -121.15, -121.05, -120.95, -120.85, -120.75, -120.65, -120.55, -120.45, -120.35, -120.25, -120.15, -120.05, -119.95, -119.85, -119.75, -119.65, -119.55, -119.45, -119.35, -119.25, -119.15, -119.05, -118.95, -118.85, -118.75, -118.65, -118.55, -118.45, -118.35, -118.25, -118.15, -118.05, -117.95, -117.85, -117.75, -117.65, -117.55, -117.45, -117.35, -117.25, -117.15, -117.05, -116.95, -116.85, -116.75], dtype=float32) - latitude(latitude)float3249.2 49.1 49.0 ... 45.7 45.6 45.5
- units :
- degrees_north
- long_name :
- latitude
array([49.2, 49.1, 49. , 48.9, 48.8, 48.7, 48.6, 48.5, 48.4, 48.3, 48.2, 48.1, 48. , 47.9, 47.8, 47.7, 47.6, 47.5, 47.4, 47.3, 47.2, 47.1, 47. , 46.9, 46.8, 46.7, 46.6, 46.5, 46.4, 46.3, 46.2, 46.1, 46. , 45.9, 45.8, 45.7, 45.6, 45.5], dtype=float32) - time(time)datetime64[ns]1950-01-01T06:00:00 ... 2021-12-...
- long_name :
- time
array(['1950-01-01T06:00:00.000000000', '1950-01-01T12:00:00.000000000', '1950-01-01T18:00:00.000000000', ..., '2021-12-31T06:00:00.000000000', '2021-12-31T12:00:00.000000000', '2021-12-31T18:00:00.000000000'], dtype='datetime64[ns]')
- t2m(time, latitude, longitude)float32dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
- units :
- K
- long_name :
- 2 metre temperature
Array Chunk Bytes 1.21 GiB 205.85 MiB Shape (105191, 38, 81) (105191, 19, 27) Count 7 Tasks 6 Chunks Type float32 numpy.ndarray - sde(time, latitude, longitude)float32dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
- units :
- m
- long_name :
- Snow depth
- standard_name :
- lwe_thickness_of_surface_snow_amount
Array Chunk Bytes 1.21 GiB 205.85 MiB Shape (105191, 38, 81) (105191, 19, 27) Count 7 Tasks 6 Chunks Type float32 numpy.ndarray - tp(time, latitude, longitude)float32dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
- units :
- m
- long_name :
- Total precipitation
Array Chunk Bytes 1.21 GiB 205.85 MiB Shape (105191, 38, 81) (105191, 19, 27) Count 7 Tasks 6 Chunks Type float32 numpy.ndarray
- Conventions :
- CF-1.6
- history :
- 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmwf/mars-client/bin/grib_to_netcdf -S param -o /cache/data0/adaptor.mars.internal-1646044021.7626116-32111-11-598f31f4-2f0f-4d4d-a065-6787dd3dcf2d.nc /cache/tmp/598f31f4-2f0f-4d4d-a065-6787dd3dcf2d-adaptor.mars.internal-1646028471.675862-32111-17-tmp.grib
wa_merge['t2m'] -= 273.15
wa_merge['t2m'].attrs['units'] = 'C'
#Convert meters to mm
wa_merge['tp'] *= 1000
wa_merge['tp'].attrs['units'] = 'mm'
wa_merge['t2m']
<xarray.DataArray 't2m' (time: 105191, latitude: 38, longitude: 81)>
dask.array<sub, shape=(105191, 38, 81), dtype=float32, chunksize=(105191, 19, 27), chunktype=numpy.ndarray>
Coordinates:
* longitude (longitude) float32 -124.8 -124.7 -124.6 ... -116.9 -116.8 -116.8
* latitude (latitude) float32 49.2 49.1 49.0 48.9 ... 45.8 45.7 45.6 45.5
* time (time) datetime64[ns] 1950-01-01T06:00:00 ... 2021-12-31T18:00:00
Attributes:
units: C
long_name: 2 metre temperature- time: 105191
- latitude: 38
- longitude: 81
- dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
Array Chunk Bytes 1.21 GiB 205.85 MiB Shape (105191, 38, 81) (105191, 19, 27) Count 13 Tasks 6 Chunks Type float32 numpy.ndarray - longitude(longitude)float32-124.8 -124.7 ... -116.8 -116.8
- units :
- degrees_east
- long_name :
- longitude
array([-124.75, -124.65, -124.55, -124.45, -124.35, -124.25, -124.15, -124.05, -123.95, -123.85, -123.75, -123.65, -123.55, -123.45, -123.35, -123.25, -123.15, -123.05, -122.95, -122.85, -122.75, -122.65, -122.55, -122.45, -122.35, -122.25, -122.15, -122.05, -121.95, -121.85, -121.75, -121.65, -121.55, -121.45, -121.35, -121.25, -121.15, -121.05, -120.95, -120.85, -120.75, -120.65, -120.55, -120.45, -120.35, -120.25, -120.15, -120.05, -119.95, -119.85, -119.75, -119.65, -119.55, -119.45, -119.35, -119.25, -119.15, -119.05, -118.95, -118.85, -118.75, -118.65, -118.55, -118.45, -118.35, -118.25, -118.15, -118.05, -117.95, -117.85, -117.75, -117.65, -117.55, -117.45, -117.35, -117.25, -117.15, -117.05, -116.95, -116.85, -116.75], dtype=float32) - latitude(latitude)float3249.2 49.1 49.0 ... 45.7 45.6 45.5
- units :
- degrees_north
- long_name :
- latitude
array([49.2, 49.1, 49. , 48.9, 48.8, 48.7, 48.6, 48.5, 48.4, 48.3, 48.2, 48.1, 48. , 47.9, 47.8, 47.7, 47.6, 47.5, 47.4, 47.3, 47.2, 47.1, 47. , 46.9, 46.8, 46.7, 46.6, 46.5, 46.4, 46.3, 46.2, 46.1, 46. , 45.9, 45.8, 45.7, 45.6, 45.5], dtype=float32) - time(time)datetime64[ns]1950-01-01T06:00:00 ... 2021-12-...
- long_name :
- time
array(['1950-01-01T06:00:00.000000000', '1950-01-01T12:00:00.000000000', '1950-01-01T18:00:00.000000000', ..., '2021-12-31T06:00:00.000000000', '2021-12-31T12:00:00.000000000', '2021-12-31T18:00:00.000000000'], dtype='datetime64[ns]')
- units :
- C
- long_name :
- 2 metre temperature
wa_merge
<xarray.Dataset>
Dimensions: (longitude: 81, latitude: 38, time: 105191)
Coordinates:
* longitude (longitude) float32 -124.8 -124.7 -124.6 ... -116.9 -116.8 -116.8
* latitude (latitude) float32 49.2 49.1 49.0 48.9 ... 45.8 45.7 45.6 45.5
* time (time) datetime64[ns] 1950-01-01T06:00:00 ... 2021-12-31T18:00:00
Data variables:
t2m (time, latitude, longitude) float32 dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
sde (time, latitude, longitude) float32 dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
tp (time, latitude, longitude) float32 dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
Attributes:
Conventions: CF-1.6
history: 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmw...- longitude: 81
- latitude: 38
- time: 105191
- longitude(longitude)float32-124.8 -124.7 ... -116.8 -116.8
- units :
- degrees_east
- long_name :
- longitude
array([-124.75, -124.65, -124.55, -124.45, -124.35, -124.25, -124.15, -124.05, -123.95, -123.85, -123.75, -123.65, -123.55, -123.45, -123.35, -123.25, -123.15, -123.05, -122.95, -122.85, -122.75, -122.65, -122.55, -122.45, -122.35, -122.25, -122.15, -122.05, -121.95, -121.85, -121.75, -121.65, -121.55, -121.45, -121.35, -121.25, -121.15, -121.05, -120.95, -120.85, -120.75, -120.65, -120.55, -120.45, -120.35, -120.25, -120.15, -120.05, -119.95, -119.85, -119.75, -119.65, -119.55, -119.45, -119.35, -119.25, -119.15, -119.05, -118.95, -118.85, -118.75, -118.65, -118.55, -118.45, -118.35, -118.25, -118.15, -118.05, -117.95, -117.85, -117.75, -117.65, -117.55, -117.45, -117.35, -117.25, -117.15, -117.05, -116.95, -116.85, -116.75], dtype=float32) - latitude(latitude)float3249.2 49.1 49.0 ... 45.7 45.6 45.5
- units :
- degrees_north
- long_name :
- latitude
array([49.2, 49.1, 49. , 48.9, 48.8, 48.7, 48.6, 48.5, 48.4, 48.3, 48.2, 48.1, 48. , 47.9, 47.8, 47.7, 47.6, 47.5, 47.4, 47.3, 47.2, 47.1, 47. , 46.9, 46.8, 46.7, 46.6, 46.5, 46.4, 46.3, 46.2, 46.1, 46. , 45.9, 45.8, 45.7, 45.6, 45.5], dtype=float32) - time(time)datetime64[ns]1950-01-01T06:00:00 ... 2021-12-...
- long_name :
- time
array(['1950-01-01T06:00:00.000000000', '1950-01-01T12:00:00.000000000', '1950-01-01T18:00:00.000000000', ..., '2021-12-31T06:00:00.000000000', '2021-12-31T12:00:00.000000000', '2021-12-31T18:00:00.000000000'], dtype='datetime64[ns]')
- t2m(time, latitude, longitude)float32dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
- units :
- C
- long_name :
- 2 metre temperature
Array Chunk Bytes 1.21 GiB 205.85 MiB Shape (105191, 38, 81) (105191, 19, 27) Count 13 Tasks 6 Chunks Type float32 numpy.ndarray - sde(time, latitude, longitude)float32dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
- units :
- m
- long_name :
- Snow depth
- standard_name :
- lwe_thickness_of_surface_snow_amount
Array Chunk Bytes 1.21 GiB 205.85 MiB Shape (105191, 38, 81) (105191, 19, 27) Count 7 Tasks 6 Chunks Type float32 numpy.ndarray - tp(time, latitude, longitude)float32dask.array<chunksize=(105191, 19, 27), meta=np.ndarray>
- units :
- mm
- long_name :
- Total precipitation
Array Chunk Bytes 1.21 GiB 205.85 MiB Shape (105191, 38, 81) (105191, 19, 27) Count 13 Tasks 6 Chunks Type float32 numpy.ndarray
- Conventions :
- CF-1.6
- history :
- 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmwf/mars-client/bin/grib_to_netcdf -S param -o /cache/data0/adaptor.mars.internal-1646044021.7626116-32111-11-598f31f4-2f0f-4d4d-a065-6787dd3dcf2d.nc /cache/tmp/598f31f4-2f0f-4d4d-a065-6787dd3dcf2d-adaptor.mars.internal-1646028471.675862-32111-17-tmp.grib
#Unset units (avoid plotting in x and y label)
wa_merge['latitude'].attrs['units'] = None
wa_merge['longitude'].attrs['units'] = None
Clip to WA state geometry¶
#wa_merge_clip = wa_merge.rio.write_crs(wa_state.crs);
#wa_merge_clip = wa_merge_clip.rio.clip(wa_geom, crs=world.crs, drop=False)
Compute seasonal mean values for each variable¶
This may take ~30-60 seconds depending on chunks and server load
This is a simple
groupby()andmean()Inspect the output values - do these make sense?
wa_merge_seasonal_mean = wa_merge.groupby('time.season').mean().compute()
wa_merge_seasonal_mean
<xarray.Dataset>
Dimensions: (longitude: 81, latitude: 38, season: 4)
Coordinates:
* longitude (longitude) float32 -124.8 -124.7 -124.6 ... -116.9 -116.8 -116.8
* latitude (latitude) float32 49.2 49.1 49.0 48.9 ... 45.8 45.7 45.6 45.5
* season (season) object 'DJF' 'JJA' 'MAM' 'SON'
Data variables:
t2m (season, latitude, longitude) float32 0.9609 0.2696 ... 6.214
sde (season, latitude, longitude) float32 0.2804 0.3006 ... 0.02896
tp (season, latitude, longitude) float32 5.971 5.626 ... 1.292 1.302- longitude: 81
- latitude: 38
- season: 4
- longitude(longitude)float32-124.8 -124.7 ... -116.8 -116.8
- units :
- None
- long_name :
- longitude
array([-124.75, -124.65, -124.55, -124.45, -124.35, -124.25, -124.15, -124.05, -123.95, -123.85, -123.75, -123.65, -123.55, -123.45, -123.35, -123.25, -123.15, -123.05, -122.95, -122.85, -122.75, -122.65, -122.55, -122.45, -122.35, -122.25, -122.15, -122.05, -121.95, -121.85, -121.75, -121.65, -121.55, -121.45, -121.35, -121.25, -121.15, -121.05, -120.95, -120.85, -120.75, -120.65, -120.55, -120.45, -120.35, -120.25, -120.15, -120.05, -119.95, -119.85, -119.75, -119.65, -119.55, -119.45, -119.35, -119.25, -119.15, -119.05, -118.95, -118.85, -118.75, -118.65, -118.55, -118.45, -118.35, -118.25, -118.15, -118.05, -117.95, -117.85, -117.75, -117.65, -117.55, -117.45, -117.35, -117.25, -117.15, -117.05, -116.95, -116.85, -116.75], dtype=float32) - latitude(latitude)float3249.2 49.1 49.0 ... 45.7 45.6 45.5
- units :
- None
- long_name :
- latitude
array([49.2, 49.1, 49. , 48.9, 48.8, 48.7, 48.6, 48.5, 48.4, 48.3, 48.2, 48.1, 48. , 47.9, 47.8, 47.7, 47.6, 47.5, 47.4, 47.3, 47.2, 47.1, 47. , 46.9, 46.8, 46.7, 46.6, 46.5, 46.4, 46.3, 46.2, 46.1, 46. , 45.9, 45.8, 45.7, 45.6, 45.5], dtype=float32) - season(season)object'DJF' 'JJA' 'MAM' 'SON'
array(['DJF', 'JJA', 'MAM', 'SON'], dtype=object)
- t2m(season, latitude, longitude)float320.9609 0.2696 ... 6.408 6.214
array([[[ 0.9608662 , 0.26957658, -0.05297273, ..., -8.125559 , -7.570897 , -6.559904 ], [ 0.14377968, -0.66860163, -1.0369308 , ..., -8.307996 , -7.758505 , -6.632995 ], [ 0.48809895, -0.12534052, -0.3571267 , ..., -7.625072 , -7.3141055 , -6.6958904 ], ..., [ nan, nan, nan, ..., -4.113628 , -3.4252656 , -2.7472563 ], [ nan, nan, nan, ..., -4.48182 , -4.169463 , -4.1303368 ], [ nan, nan, nan, ..., -5.0529437 , -4.9746666 , -5.0103426 ]], [[15.196534 , 14.327342 , 13.856261 , ..., 12.0687895 , 13.005667 , 14.8839245 ], [14.495896 , 13.857115 , 13.465471 , ..., 11.711291 , 12.591215 , 14.916636 ], [14.413533 , 14.32616 , 14.395856 , ..., 13.263345 , 13.608513 , 14.753174 ], ... [ nan, nan, nan, ..., 4.3349624 , 5.3436685 , 6.032879 ], [ nan, nan, nan, ..., 4.0313063 , 4.3736544 , 4.3109555 ], [ nan, nan, nan, ..., 3.458183 , 3.4102736 , 3.1008487 ]], [[ 8.742788 , 7.93855 , 7.50984 , ..., 2.2622662 , 3.0302382 , 4.4526386 ], [ 8.073067 , 7.328565 , 6.887931 , ..., 1.8708735 , 2.605023 , 4.242009 ], [ 8.284869 , 7.8949914 , 7.7257977 , ..., 2.8213863 , 3.1963508 , 4.0755677 ], ..., [ nan, nan, nan, ..., 7.1309657 , 7.9837255 , 8.620941 ], [ nan, nan, nan, ..., 6.874441 , 7.1740904 , 7.1993217 ], [ nan, nan, nan, ..., 6.3713794 , 6.408295 , 6.213758 ]]], dtype=float32) - sde(season, latitude, longitude)float320.2804 0.3006 ... 0.03019 0.02896
array([[[2.80389130e-01, 3.00635397e-01, 2.99659759e-01, ..., 1.23812032e+00, 1.22704399e+00, 1.19872928e+00], [3.70033950e-01, 4.74735171e-01, 5.39419234e-01, ..., 1.22916305e+00, 1.20123184e+00, 1.12964165e+00], [3.17811668e-01, 4.17957753e-01, 4.83184546e-01, ..., 1.16831899e+00, 1.14746273e+00, 1.10006797e+00], ..., [ nan, nan, nan, ..., 3.79122108e-01, 3.86305958e-01, 4.18855220e-01], [ nan, nan, nan, ..., 5.01634002e-01, 4.95917171e-01, 4.73622829e-01], [ nan, nan, nan, ..., 6.12135291e-01, 5.54873168e-01, 5.23426890e-01]], [[4.81114839e-05, 1.75759982e-04, 1.68928353e-04, ..., 1.13978721e-01, 8.86574164e-02, 4.52102758e-02], [1.60232972e-04, 1.93330424e-03, 3.46710626e-03, ..., 1.12941891e-01, 9.28539485e-02, 3.95821966e-02], [2.20447415e-04, 5.76192455e-04, 1.03925087e-03, ..., 5.83353862e-02, 4.84932065e-02, 2.97168773e-02], ... [ nan, nan, nan, ..., 1.89636752e-01, 1.79012835e-01, 1.92565814e-01], [ nan, nan, nan, ..., 3.06625575e-01, 2.96791047e-01, 2.88627833e-01], [ nan, nan, nan, ..., 4.60190624e-01, 4.06346500e-01, 3.99849296e-01]], [[1.08954702e-02, 1.18942140e-02, 1.20264972e-02, ..., 1.44482881e-01, 1.35728553e-01, 1.23796493e-01], [1.47690969e-02, 1.97550971e-02, 2.29764264e-02, ..., 1.40614346e-01, 1.29552647e-01, 1.08919606e-01], [1.33836484e-02, 1.81084294e-02, 2.11291034e-02, ..., 1.22289561e-01, 1.14184909e-01, 1.01198360e-01], ..., [ nan, nan, nan, ..., 1.74681731e-02, 1.71599295e-02, 1.76748969e-02], [ nan, nan, nan, ..., 2.36358158e-02, 2.30771564e-02, 2.27020513e-02], [ nan, nan, nan, ..., 3.28891613e-02, 3.01924665e-02, 2.89574284e-02]]], dtype=float32) - tp(season, latitude, longitude)float325.971 5.626 5.353 ... 1.292 1.302
array([[[5.9708543 , 5.626095 , 5.353475 , ..., 2.4645054 , 2.5164413 , 2.5598085 ], [6.523473 , 6.213825 , 5.9119925 , ..., 2.4522858 , 2.476637 , 2.4918225 ], [6.9921937 , 6.7291417 , 6.4449058 , ..., 2.4705107 , 2.488049 , 2.4971995 ], ..., [ nan, nan, nan, ..., 1.6356691 , 1.6571568 , 1.6812229 ], [ nan, nan, nan, ..., 1.718449 , 1.7257987 , 1.7400942 ], [ nan, nan, nan, ..., 1.7836069 , 1.7741454 , 1.7716526 ]], [[1.2035366 , 1.1665776 , 1.1446036 , ..., 1.4398484 , 1.4066566 , 1.3690296 ], [1.3387612 , 1.3048563 , 1.2724243 , ..., 1.357698 , 1.3202622 , 1.2774682 ], [1.3964874 , 1.3633964 , 1.324738 , ..., 1.3124241 , 1.2902232 , 1.2540016 ], ... [ nan, nan, nan, ..., 1.6793942 , 1.7355512 , 1.790109 ], [ nan, nan, nan, ..., 1.7495741 , 1.7874206 , 1.8274063 ], [ nan, nan, nan, ..., 1.7786472 , 1.7924751 , 1.8101676 ]], [[4.3695226 , 4.0727696 , 3.8539214 , ..., 2.0713081 , 2.1269755 , 2.1715345 ], [4.7803082 , 4.4754405 , 4.20544 , ..., 1.9956996 , 2.0299242 , 2.0517647 ], [5.178129 , 4.8815637 , 4.5949073 , ..., 1.9596436 , 1.9906403 , 2.0101244 ], ..., [ nan, nan, nan, ..., 1.189737 , 1.2305676 , 1.2720792 ], [ nan, nan, nan, ..., 1.2495333 , 1.2752199 , 1.3044505 ], [ nan, nan, nan, ..., 1.2857243 , 1.2921 , 1.3021969 ]]], dtype=float32)
#Hack to reorder seasons, as default is alphabetical
#order = np.array(['DJF', 'MAM', 'JJA', 'SON'], dtype=object)
order = np.array([0,2,1,3])
#wa_merge_seasonal_mean.season.values
wa_merge_seasonal_mean = wa_merge_seasonal_mean.isel(season=order)
#wa_merge_seasonal_resample = wa_merge.resample(time='Q-NOV').mean('time')
Plot seasonal mean grids¶
Note that plot will assume
x='longitude', y='latitude', but can also explicitly specify
wa_merge_seasonal_mean.data_vars
Data variables:
t2m (season, latitude, longitude) float32 0.9609 0.2696 ... 6.408 6.214
sde (season, latitude, longitude) float32 0.2804 0.3006 ... 0.02896
tp (season, latitude, longitude) float32 5.971 5.626 ... 1.292 1.302
for i in wa_merge_seasonal_mean.data_vars:
wa_merge_seasonal_mean[i].plot.imshow(col='season')
Compute mean monthly values for WA state¶
wa_monthly_mean = wa_merge.groupby('time.month').mean('time').mean(['latitude','longitude']).compute()
wa_monthly_mean
<xarray.Dataset>
Dimensions: (month: 12)
Coordinates:
* month (month) int64 1 2 3 4 5 6 7 8 9 10 11 12
Data variables:
t2m (month) float32 -1.957 0.09294 2.627 6.119 ... 8.671 2.257 -1.521
sde (month) float32 0.4876 0.5431 0.5326 ... 0.009246 0.08937 0.2947
tp (month) float32 3.241 2.678 2.378 1.75 ... 0.9946 1.997 3.257 3.394- month: 12
- month(month)int641 2 3 4 5 6 7 8 9 10 11 12
array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
- t2m(month)float32-1.957 0.09294 ... 2.257 -1.521
array([-1.9572749 , 0.09293701, 2.627388 , 6.1190596 , 10.575189 , 14.497497 , 18.679752 , 18.71483 , 14.792599 , 8.671006 , 2.25671 , -1.5210348 ], dtype=float32) - sde(month)float320.4876 0.5431 ... 0.08937 0.2947
array([4.8756382e-01, 5.4307640e-01, 5.3258258e-01, 4.1211388e-01, 2.3939146e-01, 8.6320348e-02, 1.4964289e-02, 8.6208753e-04, 3.5991980e-04, 9.2461938e-03, 8.9369945e-02, 2.9471704e-01], dtype=float32) - tp(month)float323.241 2.678 2.378 ... 3.257 3.394
array([3.2405887 , 2.6784945 , 2.378413 , 1.7501407 , 1.2799574 , 1.035217 , 0.47339597, 0.5659153 , 0.9946057 , 1.9967929 , 3.2574167 , 3.3939404 ], dtype=float32)
f, axa = plt.subplots(3,1, sharex=True)
wa_monthly_mean['t2m'].plot(ax=axa[0])
wa_monthly_mean['tp'].plot(ax=axa[1])
wa_monthly_mean['sde'].plot(ax=axa[2]);
Helper function for plotting WA grids with state outline overlay¶
def plotwa(ds_in, v_list=['t2m','tp','sde'], op='mean'):
f,axa = plt.subplots(1,3, figsize=(12,2), sharex=True, sharey=True)
for i,v in enumerate(v_list):
ds_in[v].plot(ax=axa[i], robust=True)
wa_state.plot(ax=axa[i], facecolor='none', edgecolor='black')
axa[i].set_title('WA State ERA5 Hourly: %s %s' % (op, v))
f.tight_layout()
Get the WA state outline¶
#states_url = 'http://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_040_00_5m.json'
states_url = 'http://eric.clst.org/assets/wiki/uploads/Stuff/gz_2010_us_040_00_500k.json'
states_gdf = gpd.read_file(states_url)
wa_state = states_gdf.loc[states_gdf['NAME'] == 'Washington']
wa_state.plot();
wa_geom = wa_state.iloc[0].geometry
wa_geom
Create some plots of descriptive stats (mean, max, min, std) for 1979-present¶
Pass the relevant dataset (e.g.
wa_merge.mean('time')) to theplotwahelper functionWhat do these metrics tell you?
What is causing most of the temperature variability captured by the std?
What is the highest temperature value
plotwa(wa_merge.mean('time'), op='mean')
plotwa(wa_merge.max('time'), op='max')
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/utils.py:37: RuntimeWarning: All-NaN slice encountered
return func(*args, **kwargs)
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/core.py:119: RuntimeWarning: All-NaN slice encountered
return func(*(_execute_task(a, cache) for a in args))
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/utils.py:37: RuntimeWarning: All-NaN slice encountered
return func(*args, **kwargs)
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/core.py:119: RuntimeWarning: All-NaN slice encountered
return func(*(_execute_task(a, cache) for a in args))
plotwa(wa_merge.min('time'), op='min')
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/utils.py:37: RuntimeWarning: All-NaN slice encountered
return func(*args, **kwargs)
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/core.py:119: RuntimeWarning: All-NaN slice encountered
return func(*(_execute_task(a, cache) for a in args))
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/utils.py:37: RuntimeWarning: All-NaN slice encountered
return func(*args, **kwargs)
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/core.py:119: RuntimeWarning: All-NaN slice encountered
return func(*(_execute_task(a, cache) for a in args))
plotwa(wa_merge.std('time'), op='std')
/srv/conda/envs/notebook/lib/python3.9/site-packages/numpy/lib/nanfunctions.py:1670: RuntimeWarning: Degrees of freedom <= 0 for slice.
var = nanvar(a, axis=axis, dtype=dtype, out=out, ddof=ddof,
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/array/numpy_compat.py:39: RuntimeWarning: invalid value encountered in true_divide
x = np.divide(x1, x2, out)
/srv/conda/envs/notebook/lib/python3.9/site-packages/dask/array/numpy_compat.py:39: RuntimeWarning: invalid value encountered in true_divide
x = np.divide(x1, x2, out)
Create a plot showing the conditions the day before and after the Mt. St. Helen’s eruption¶
pre = wa_merge.sel(time='1980-05-17T06:00')
plotwa(pre)
post = wa_merge.sel(time='1980-05-19T06:00')
plotwa(post)
Create a plot showing the conditions during the June 2021 heat wave¶
https://en.wikipedia.org/wiki/2021_Western_North_America_heat_wave
Extra credit: prepare a map of the long-term average t2m for June 29, then difference against the t2m values from June 29, 2021
wa_merge.t2m.sel(time=slice("2021-06-22", "2021-07-05")).mean(dim=('longitude', 'latitude')).plot()
[<matplotlib.lines.Line2D at 0x7f6b73d3d160>]
plotwa(wa_merge.sel(time='2021-06-24T00:00'))
plotwa(wa_merge.sel(time='2021-06-29T00:00'))
plotwa(wa_merge.sel(time='2021-07-03T00:00'))
Extract the time series for Seattle and Mt. Rainier temperature and create line plot¶
You’ll need to look up coordinates
Check the longitude system in the DataArrays (-180 to 180, or 0 to 360)
Can use the
sel()method to extract time series for the grid cell nearest the specified ‘longitude’ and ‘latitude’ coordinatesRemember, these are large grid cells (~31x31 km), so one grid cell could cover the most of Mt. Rainier (a single temperature value that includes the cold summit and the warmer, lowland river valleys)
Sanity check
#sea_coord = (-122.25, 47.5)
sea_coord = (-122.3321, 47.6062)
rainier_coord = (121.7603, 46.8523)
sea_ts = wa_merge.sel(longitude=sea_coord[0], latitude=sea_coord[1], method='nearest')
sea_ts
<xarray.Dataset>
Dimensions: (time: 105191)
Coordinates:
longitude float32 -122.3
latitude float32 47.6
* time (time) datetime64[ns] 1950-01-01T06:00:00 ... 2021-12-31T18:00:00
Data variables:
t2m (time) float32 -1.475 -1.604 -1.013 ... -4.004 -5.29 -4.117
sde (time) float32 dask.array<chunksize=(105191,), meta=np.ndarray>
tp (time) float32 dask.array<chunksize=(105191,), meta=np.ndarray>
Attributes:
Conventions: CF-1.6
history: 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmw...- time: 105191
- longitude()float32-122.3
- units :
- None
- long_name :
- longitude
array(-122.35, dtype=float32)
- latitude()float3247.6
- units :
- None
- long_name :
- latitude
array(47.6, dtype=float32)
- time(time)datetime64[ns]1950-01-01T06:00:00 ... 2021-12-...
- long_name :
- time
array(['1950-01-01T06:00:00.000000000', '1950-01-01T12:00:00.000000000', '1950-01-01T18:00:00.000000000', ..., '2021-12-31T06:00:00.000000000', '2021-12-31T12:00:00.000000000', '2021-12-31T18:00:00.000000000'], dtype='datetime64[ns]')
- t2m(time)float32-1.475 -1.604 ... -5.29 -4.117
- units :
- C
- long_name :
- 2 metre temperature
array([-1.4751282, -1.6038208, -1.0126648, ..., -4.0040894, -5.289612 , -4.1174927], dtype=float32) - sde(time)float32dask.array<chunksize=(105191,), meta=np.ndarray>
- units :
- m
- long_name :
- Snow depth
- standard_name :
- lwe_thickness_of_surface_snow_amount
Array Chunk Bytes 410.90 kiB 410.90 kiB Shape (105191,) (105191,) Count 8 Tasks 1 Chunks Type float32 numpy.ndarray - tp(time)float32dask.array<chunksize=(105191,), meta=np.ndarray>
- units :
- mm
- long_name :
- Total precipitation
Array Chunk Bytes 410.90 kiB 410.90 kiB Shape (105191,) (105191,) Count 14 Tasks 1 Chunks Type float32 numpy.ndarray
- Conventions :
- CF-1.6
- history :
- 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmwf/mars-client/bin/grib_to_netcdf -S param -o /cache/data0/adaptor.mars.internal-1646044021.7626116-32111-11-598f31f4-2f0f-4d4d-a065-6787dd3dcf2d.nc /cache/tmp/598f31f4-2f0f-4d4d-a065-6787dd3dcf2d-adaptor.mars.internal-1646028471.675862-32111-17-tmp.grib
rainier_ts = wa_merge.sel(longitude=rainier_coord[0], latitude=rainier_coord[1], method='nearest')
rainier_ts
<xarray.Dataset>
Dimensions: (time: 105191)
Coordinates:
longitude float32 -116.8
latitude float32 46.9
* time (time) datetime64[ns] 1950-01-01T06:00:00 ... 2021-12-31T18:00:00
Data variables:
t2m (time) float32 -6.065 -7.447 -7.155 ... -9.224 -11.02 -13.0
sde (time) float32 dask.array<chunksize=(105191,), meta=np.ndarray>
tp (time) float32 dask.array<chunksize=(105191,), meta=np.ndarray>
Attributes:
Conventions: CF-1.6
history: 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmw...- time: 105191
- longitude()float32-116.8
- units :
- None
- long_name :
- longitude
array(-116.75, dtype=float32)
- latitude()float3246.9
- units :
- None
- long_name :
- latitude
array(46.9, dtype=float32)
- time(time)datetime64[ns]1950-01-01T06:00:00 ... 2021-12-...
- long_name :
- time
array(['1950-01-01T06:00:00.000000000', '1950-01-01T12:00:00.000000000', '1950-01-01T18:00:00.000000000', ..., '2021-12-31T06:00:00.000000000', '2021-12-31T12:00:00.000000000', '2021-12-31T18:00:00.000000000'], dtype='datetime64[ns]')
- t2m(time)float32-6.065 -7.447 ... -11.02 -13.0
- units :
- C
- long_name :
- 2 metre temperature
array([ -6.0654907, -7.446533 , -7.154785 , ..., -9.223816 , -11.022736 , -13.001312 ], dtype=float32) - sde(time)float32dask.array<chunksize=(105191,), meta=np.ndarray>
- units :
- m
- long_name :
- Snow depth
- standard_name :
- lwe_thickness_of_surface_snow_amount
Array Chunk Bytes 410.90 kiB 410.90 kiB Shape (105191,) (105191,) Count 8 Tasks 1 Chunks Type float32 numpy.ndarray - tp(time)float32dask.array<chunksize=(105191,), meta=np.ndarray>
- units :
- mm
- long_name :
- Total precipitation
Array Chunk Bytes 410.90 kiB 410.90 kiB Shape (105191,) (105191,) Count 14 Tasks 1 Chunks Type float32 numpy.ndarray
- Conventions :
- CF-1.6
- history :
- 2022-02-28 10:58:20 GMT by grib_to_netcdf-2.24.2: /opt/ecmwf/mars-client/bin/grib_to_netcdf -S param -o /cache/data0/adaptor.mars.internal-1646044021.7626116-32111-11-598f31f4-2f0f-4d4d-a065-6787dd3dcf2d.nc /cache/tmp/598f31f4-2f0f-4d4d-a065-6787dd3dcf2d-adaptor.mars.internal-1646028471.675862-32111-17-tmp.grib
rainier_ts.time.values.min()
numpy.datetime64('1950-01-01T06:00:00.000000000')
f, ax = plt.subplots(figsize=(12,1.5))
v = 't2m'
rainier_ts[v].plot(ax=ax, label='Rainer %s' % v)
sea_ts[v].plot(ax=ax, label='Seattle %s' % v)
ax.axhline(0,color='k',lw=0.5)
ax.legend(fontsize=8)
ax.set_xlim(rainier_ts.time.values.min(), rainier_ts.time.values.max())
ax.set_title("ERA5 Hourly T: Seattle and Mt. Rainier");
f, ax = plt.subplots(figsize=(12,1.5))
v = 't2m'
rainier_ts[v].loc[f'{curr_y-1}-01-01':].plot(ax=ax, label='Rainer %s' % v)
sea_ts[v].loc[f'{curr_y-1}-01-01':].plot(ax=ax, label='Seattle %s' % v)
ax.axhline(0,color='k',lw=0.5)
ax.legend(fontsize=8)
ax.set_title("ERA5 Hourly T: Seattle and Mt. Rainier, WA");
Helper function to plot time series¶
def plotv(ds_in, v_list=['t2m','tp','sde']):
f,axa = plt.subplots(3,1, figsize=(10,6), sharex=True)
for i,v in enumerate(v_list):
ds_in[v].dropna(dim='time').plot(ax=axa[i], lw=0.5)
axa[i].axhline(0,color='k',lw=0.5)
f.tight_layout()
plotv(wa_merge.sel(longitude=sea_coord[0], latitude=sea_coord[1], method='nearest'))
plotv(wa_merge.sel(longitude=rainier_coord[0], latitude=rainier_coord[1], method='nearest'))
Compute stats for monthly, annual time periods¶
Can use
groupby('time.year').max(dim='time')Plot snow depth for April and September
Extra Credit: Create a map that shows the year containing the maximum T value at each grid cell¶
These should mostly be in the most recent decade
Note the
.compute()is needed to converty dask array to ndarray for use in vectorized indexing
Note from 2022 - the ERA5-Land products include some cells that are all nan over time (e.g., ocean). This creates problems for the xarray argmax function, even with skipna=True, and various dropna calls
Need to revisit
#wa_merge['t2m'].dropna(dim='time', how='all').argmax(dim='time').compute()
#wa_merge['t2m'].idxmax(dim='time').compute()
#xr.apply_ufunc(np.nanargmax, wa_merge['t2m'].load())
#max_t_idx = wa_merge['t2m'].argmax(dim='time', skipna=True).compute()
#f, ax = plt.subplots()
#wa_merge['t2m']['time.year'][max_t_idx].plot(ax=ax)
#wa_state.plot(ax=ax, facecolor='none', edgecolor='black');
#wa_merge['t2m']['time.year'][max_t_idx].median()