Skip to content

Commit ba60ace

Browse files
committed
add nexrad plotting example
1 parent 714f501 commit ba60ace

File tree

1 file changed

+161
-0
lines changed

1 file changed

+161
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "code",
5+
"execution_count": null,
6+
"metadata": {},
7+
"outputs": [],
8+
"source": [
9+
"from datetime import datetime, timedelta\n",
10+
"\n",
11+
"import cartopy.crs as ccrs\n",
12+
"import cartopy.feature as cfeature\n",
13+
"import matplotlib.pyplot as plt\n",
14+
"from metpy.plots import colortables, USSTATES, USCOUNTIES\n",
15+
"import numpy as np\n",
16+
"from pyproj import Proj\n",
17+
"from siphon.catalog import TDSCatalog\n",
18+
"import xarray as xr\n",
19+
"\n",
20+
"import warnings\n",
21+
"warnings.filterwarnings(\"ignore\")"
22+
]
23+
},
24+
{
25+
"cell_type": "code",
26+
"execution_count": null,
27+
"metadata": {},
28+
"outputs": [],
29+
"source": [
30+
"def get_radar_file_url(datasets, date):\n",
31+
" '''A function to help find the desired satellite data based on the time given.\n",
32+
" \n",
33+
" Input:\n",
34+
" - List of datasets from a THREDDS Catalog\n",
35+
" - Date of desired dataset (datetime object)\n",
36+
" \n",
37+
" Output:\n",
38+
" - Index value of dataset closest to desired time\n",
39+
" '''\n",
40+
" rad_date_hour = date.strftime('%Y%m%d_%H')\n",
41+
" files = []\n",
42+
" times = []\n",
43+
" for file in cat.datasets:\n",
44+
" if rad_date_hour in file:\n",
45+
" times.append(datetime.strptime(file[-18:-5], '%Y%m%d_%H%M'))\n",
46+
" files.append(file)\n",
47+
" if not files:\n",
48+
" date = date - timedelta(hours=1)\n",
49+
" rad_date_hour = date.strftime('%Y%m%d_%H')\n",
50+
" for file in cat.datasets:\n",
51+
" if rad_date_hour in file:\n",
52+
" times.append(datetime.strptime(file[-18:-5], '%Y%m%d_%H%M'))\n",
53+
" files.append(file)\n",
54+
" find_file = np.abs(np.array(times) - date)\n",
55+
" return list(cat.datasets).index(files[np.argmin(find_file)])"
56+
]
57+
},
58+
{
59+
"cell_type": "code",
60+
"execution_count": null,
61+
"metadata": {},
62+
"outputs": [],
63+
"source": [
64+
"date = datetime.utcnow()\n",
65+
"\n",
66+
"# Create variables for URL generation\n",
67+
"station = 'KLOT'\n",
68+
"\n",
69+
"# Construct the data_url string\n",
70+
"data_url = (f'https://thredds.ucar.edu/thredds/catalog/nexrad/level2/'\n",
71+
" f'{station}/{date:%Y%m%d}/catalog.html')\n",
72+
"\n",
73+
"# Get list of files available for particular day\n",
74+
"cat = TDSCatalog(data_url)\n",
75+
"\n",
76+
"# Use homemade function to get dataset for desired time\n",
77+
"dataset = cat.datasets[get_radar_file_url(cat.datasets, date)]\n",
78+
"\n",
79+
"ds = xr.open_dataset(dataset.access_urls['OPENDAP'], decode_times=False,\n",
80+
" decode_coords=False, mask_and_scale=True)"
81+
]
82+
},
83+
{
84+
"cell_type": "code",
85+
"execution_count": null,
86+
"metadata": {},
87+
"outputs": [],
88+
"source": [
89+
"station = ds.Station\n",
90+
"slat = ds.StationLatitude\n",
91+
"slon = ds.StationLongitude\n",
92+
"elevation = ds.StationElevationInMeters\n",
93+
"vtime = datetime.strptime(ds.time_coverage_start, '%Y-%m-%dT%H:%M:%SZ')\n",
94+
"\n",
95+
"dataproj = Proj(f\"+proj=stere +lat_0={slat} +lat_ts={slat} +lon_0={slon} +ellps=WGS84 +units=m\")\n",
96+
"\n",
97+
"sweep = 0\n",
98+
"rng = ds.distanceR_HI.values\n",
99+
"az = ds.azimuthR_HI.values[sweep]\n",
100+
"ref = ds.Reflectivity_HI.values[sweep]\n",
101+
"\n",
102+
"x = rng * np.sin(np.deg2rad(az))[:, None]\n",
103+
"y = rng * np.cos(np.deg2rad(az))[:, None]\n",
104+
"\n",
105+
"lon, lat = dataproj(x, y, inverse=True)"
106+
]
107+
},
108+
{
109+
"cell_type": "code",
110+
"execution_count": null,
111+
"metadata": {},
112+
"outputs": [],
113+
"source": [
114+
"cmap = colortables.get_colortable('NWSStormClearReflectivity')\n",
115+
"\n",
116+
"fig, ax = plt.subplots(1, 1, figsize=(12, 10), subplot_kw=dict(projection=ccrs.PlateCarree()))\n",
117+
"\n",
118+
"img = ax.pcolormesh(lon, lat, ref, vmin=-30, vmax=79, cmap=cmap)\n",
119+
"plt.colorbar(img, aspect=50, pad=0)\n",
120+
"\n",
121+
"ax.set_extent([slon-2.5, slon+2.5, slat-2.5, slat+2.5], ccrs.PlateCarree())\n",
122+
"ax.set_aspect('equal', 'datalim')\n",
123+
"\n",
124+
"ax.add_feature(USCOUNTIES.with_scale('5m'), edgecolor='darkgrey')\n",
125+
"ax.add_feature(USSTATES.with_scale('5m'))\n",
126+
"\n",
127+
"plt.title(f'{station}: {ds.Reflectivity_HI.name}', loc='left')\n",
128+
"plt.title(f'Valid Time: {vtime}', loc='right')\n",
129+
"plt.show()"
130+
]
131+
},
132+
{
133+
"cell_type": "code",
134+
"execution_count": null,
135+
"metadata": {},
136+
"outputs": [],
137+
"source": []
138+
}
139+
],
140+
"metadata": {
141+
"kernelspec": {
142+
"display_name": "Python 3",
143+
"language": "python",
144+
"name": "python3"
145+
},
146+
"language_info": {
147+
"codemirror_mode": {
148+
"name": "ipython",
149+
"version": 3
150+
},
151+
"file_extension": ".py",
152+
"mimetype": "text/x-python",
153+
"name": "python",
154+
"nbconvert_exporter": "python",
155+
"pygments_lexer": "ipython3",
156+
"version": "3.8.2"
157+
}
158+
},
159+
"nbformat": 4,
160+
"nbformat_minor": 4
161+
}

0 commit comments

Comments
 (0)