Skip to content

Commit

Permalink
DOC: Add example plotting fronts on a map
Browse files Browse the repository at this point in the history
  • Loading branch information
dopplershift committed Apr 8, 2022
1 parent 704909e commit 839c3a8
Showing 1 changed file with 147 additions and 0 deletions.
147 changes: 147 additions & 0 deletions examples/plots/Front_Analysis.py
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))

0 comments on commit 839c3a8

Please sign in to comment.