-
Notifications
You must be signed in to change notification settings - Fork 416
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
DOC: Add example plotting fronts on a map
- Loading branch information
1 parent
704909e
commit 839c3a8
Showing
1 changed file
with
147 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import cartopy.crs as ccrs | ||
import cartopy.feature as cfeature | ||
import matplotlib.pyplot as plt | ||
|
||
from metpy.plots import ColdFront, WarmFront, OccludedFront, StationaryFront | ||
|
||
def str_to_lonlat(s): | ||
return -int(s[3:]) / 10, int(s[:3]) / 10 | ||
|
||
def parse_points(strs): | ||
for mag_str, loc_str in zip(strs[:-1:2], strs[1::2]): | ||
mag = int(mag_str) | ||
yield *str_to_lonlat(loc_str), mag | ||
|
||
def parse_path(strs): | ||
return [str_to_lonlat(s) for s in strs] | ||
|
||
def decode(fobj): | ||
ret = dict() | ||
last_field = '' | ||
for line in fobj: | ||
try: | ||
field, *info = line.split() | ||
except ValueError: # Not a good report line | ||
continue | ||
|
||
continuing = False | ||
if field not in ('VALID', 'HIGHS', 'LOWS', 'WARM', 'COLD', 'OCFNT', 'STNRY', 'TROF'): | ||
info = [field] + info | ||
field = last_field | ||
continuing = True | ||
if field == 'VALID': | ||
ret['VALID'] = info[0] | ||
elif field in ('HIGHS', 'LOWS'): | ||
ret.setdefault(field, []).extend(parse_points(info)) | ||
elif field in ('WARM', 'COLD', 'OCFNT', 'STNRY', 'TROF'): | ||
dest = ret.setdefault(field, []) | ||
vals = parse_path(info) | ||
if continuing: | ||
dest[-1].extend(vals) | ||
else: | ||
dest.append(vals) | ||
last_field = field | ||
return ret | ||
|
||
|
||
from io import StringIO | ||
|
||
data = StringIO("""870 | ||
ASUS02 KWBC 161500 | ||
CODSUS | ||
CODED SURFACE FRONTAL POSITIONS | ||
NWS WEATHER PREDICTION CENTER COLLEGE PARK MD | ||
1148 AM EST THU JAN 16 2020 | ||
VALID 011615Z | ||
HIGHS 1042 3861066 1047 4330965 1031 4051097 1043 5611072 1048 6381359 1027 | ||
2830840 1047 4760967 1018 2711238 1018 3511169 1029 4441105 | ||
LOWS 1004 4240707 1024 3090952 992 6600543 993 6010464 994 6270370 997 5960564 | ||
1001 4111212 1003 4371271 992 5131279 1003 4591186 1020 4471060 1017 4691101 | ||
OCFNT 4240707 4230701 4200697 4160694 4080692 3980694 3880701 | ||
WARM 3880701 3670692 3550676 3490655 | ||
COLD 3880701 3740718 3660736 3570760 3470790 3370814 3210850 3140883 3120907 | ||
3130925 3130932 | ||
TROF 6110627 6040668 5960723 5870777 5820829 5770871 5710939 5520985 5401016 | ||
TROF 7170861 7060959 6971059 6861166 | ||
TROF 3610946 3460947 3270952 3140953 | ||
COLD 3070954 3040960 3000973 2960985 2901004 2871023 2891048 2931066 2991080 | ||
3071092 3181100 3271103 3361108 3421116 | ||
STNRY 3130933 3110943 3070953 | ||
STNRY 6260372 6200373 6080385 5990416 6000439 6020454 6000466 | ||
COLD 6010464 5760448 5440444 5170477 5060528 | ||
STNRY 6170333 6240354 6250371 | ||
OCFNT 6600544 6510522 6340495 6210480 6010464 | ||
STNRY 5060526 5010553 4930577 4740605 4670621 4670642 4710686 4650709 | ||
COLD 4660708 4560722 4490736 4430758 4430786 4480817 4560847 4650870 | ||
TROF 4040687 3990674 4000653 3990640 3980625 | ||
COLD 4101212 4021216 3931223 3771234 3631244 3511257 3381275 3251299 3151319 | ||
TROF 5081274 5021265 4861245 4661238 4481239 | ||
STNRY 4941280 4931291 4961318 5141345 5371366 5521371 5721374 5861382 5921407 | ||
5951437 5921455 | ||
OCFNT 5121279 5091263 5051249 4991237 4921229 4721218 4621214 4531212 | ||
TROF 4341180 4261159 4271132 4321116 | ||
COLD 4531212 4461211 4371210 4251210 | ||
STNRY 4261210 4151211 4091212 | ||
STNRY 4311002 4341022 4411036 4471047 4461059 | ||
STNRY 4591186 4541189 4521199 4501207 4531212 | ||
WARM 7951527 7781482 7581465 7421461 | ||
TROF 7960731 7690701 7490642 7260577 6960544 6710536 | ||
STNRY 3421115 3471123 3551135 | ||
TROF 2801099 2671091 2391071 2071059 1821057 | ||
TROF 5401072 5271088 5061097 4831096 4711100 | ||
STNRY 4461059 4461067 4491079 4581086 4671093 4691102 | ||
TROF 4451059 4371058 4261058 4131052 3991041 3841043 3721041 | ||
STNRY 4691100 4681107 4701122 4711135 4771145 4901153 4951162 4951174 4901178 | ||
4761179 4641180 4581188 | ||
TROF 4661099 4541093 4391092 4301090 4201083 4111082 | ||
TROF 4191204 4011198 3861186 3701159 3571144 3401137 3231138 3071134 | ||
TROF 4131113 4041129 3911137 3831151 | ||
TROF 5471329 5331315 5231301 5131283 | ||
TROF 4501270 4271271 4011265 3811266 | ||
TROF 6121522 6321518 6411495 6481463 6561438 | ||
""") | ||
|
||
bull = decode(data) | ||
|
||
from metpy.plots._mpl import TextCollection | ||
def plot_bulletin(ax, data, style=None): | ||
size = 5 | ||
fontsize = 16 | ||
complete_style = {'HIGHS':{'color':'blue', 'fontsize':fontsize}, | ||
'LOWS':{'color':'red', 'fontsize':fontsize}, | ||
'WARM':{'linewidth':1, 'path_effects':[WarmFront(size=size)]}, | ||
'COLD':{'linewidth':1, 'path_effects':[ColdFront(size=size)]}, | ||
'OCFNT':{'linewidth':1, 'path_effects':[OccludedFront(size=size)]}, | ||
'STNRY':{'linewidth':1, 'path_effects':[StationaryFront(size=size)]}, | ||
'TROF':{'linewidth':2, 'linestyle':'dashed', 'color':'darkorange'}} | ||
if style: | ||
complete_style.update(style) | ||
for field in ('HIGHS', 'LOWS'): | ||
if field in data: | ||
x, y, vals = zip(*data[field]) | ||
tc = TextCollection(x, y, [field[0]] * len(x), ha='center', | ||
**complete_style[field], transform=ccrs.PlateCarree()) | ||
ax.add_collection(tc) | ||
tc = TextCollection(x, y, [str(v) for v in vals], offset=(0, -15), ha='center', | ||
**complete_style[field], transform=ccrs.PlateCarree()) | ||
ax.add_collection(tc) | ||
for field in ('WARM', 'COLD', 'STNRY', 'OCFNT', 'TROF'): | ||
for front in data[field]: | ||
if field == 'STNRY': | ||
front = reversed(front) | ||
x, y = zip(*front) | ||
plt.plot(x, y, **complete_style.get(field, {}), transform=ccrs.PlateCarree()) | ||
|
||
|
||
fig = plt.figure(figsize=(18, 18), dpi=300) | ||
ax = fig.add_subplot(1, 1, 1, projection=ccrs.LambertConformal(central_longitude=-103)) | ||
ax.add_feature(cfeature.COASTLINE) | ||
ax.add_feature(cfeature.OCEAN) | ||
ax.add_feature(cfeature.LAND) | ||
ax.add_feature(cfeature.BORDERS) | ||
ax.add_feature(cfeature.STATES) | ||
ax.add_feature(cfeature.LAKES) | ||
plot_bulletin(ax, bull) | ||
ax.set_extent((-125, -70, 20, 55)) |