Nathan Bergey
6 years ago
7 changed files with 159 additions and 3 deletions
-
1.gitignore
-
12Makefile
-
14Pipfile
-
17README.markdown
-
3README.md
-
BINtornados_us.png
-
115tornados_us.py
@ -0,0 +1,12 @@ |
|||
all: tornados_us.png |
|||
|
|||
1950-2017_actual_tornadoes.csv: |
|||
curl -O https://www.spc.noaa.gov/wcm/data/1950-2017_actual_tornadoes.csv |
|||
|
|||
%.png: %.py 1950-2017_actual_tornadoes.csv |
|||
pipenv run python $^ |
|||
|
|||
clean: |
|||
rm -f *.png |
|||
|
|||
.PHONY: all clean |
@ -0,0 +1,14 @@ |
|||
[[source]] |
|||
name = "pypi" |
|||
url = "https://pypi.org/simple" |
|||
verify_ssl = true |
|||
|
|||
[dev-packages] |
|||
|
|||
[packages] |
|||
matplotlib = "*" |
|||
cartopy = "*" |
|||
scipy = "*" |
|||
|
|||
[requires] |
|||
python_version = "3.7" |
@ -0,0 +1,17 @@ |
|||
Map of tornado historic tornado traces |
|||
====================================== |
|||
|
|||
Data from https://www.spc.noaa.gov/wcm |
|||
|
|||
|
|||
## All US tornados 1950-20017 |
|||
|
|||
![map of US with traces of tornado paths](tornados_us.png) |
|||
|
|||
|
|||
### Dev |
|||
|
|||
Using pipenv |
|||
|
|||
$ pipenv install |
|||
$ make |
@ -1,3 +0,0 @@ |
|||
# tornado-map |
|||
|
|||
Map of tornado historic tornado traces |
After Width: 2048 | Height: 1536 | Size: 865 KiB |
@ -0,0 +1,115 @@ |
|||
# -*- coding: utf-8 -*- |
|||
|
|||
import csv |
|||
from dataclasses import dataclass |
|||
from datetime import datetime |
|||
|
|||
import cartopy.crs as ccrs |
|||
import matplotlib.pyplot as plt |
|||
import cartopy.feature as cfeature |
|||
from mpl_toolkits.axes_grid1.inset_locator import inset_axes |
|||
from cartopy import geodesic |
|||
import shapely.geometry as sgeom |
|||
|
|||
|
|||
proj = ccrs.AlbersEqualArea( |
|||
central_longitude=-95, |
|||
central_latitude=40, |
|||
) |
|||
water_blue = "#7ebfd4" |
|||
|
|||
|
|||
def phys(name, resolv): |
|||
return cfeature.NaturalEarthFeature('physical', name, resolv, facecolor="none") |
|||
|
|||
|
|||
def cultural(name, resolv): |
|||
return cfeature.NaturalEarthFeature('cultural', name, resolv, facecolor="none") |
|||
|
|||
|
|||
land = phys("land", "50m") |
|||
rivers = phys("rivers_lake_centerlines", "50m") |
|||
lakes = phys("lakes", "50m") |
|||
countries = cultural("admin_0_countries", "50m") |
|||
states = cultural("admin_1_states_provinces_lines", "50m") |
|||
|
|||
|
|||
@dataclass |
|||
class Tornado: |
|||
om: str |
|||
yr: str |
|||
mo: str |
|||
dy: str |
|||
date: str |
|||
time: str |
|||
tz: str |
|||
st: str |
|||
stf: str |
|||
stn: str |
|||
mag: str |
|||
inj: str |
|||
fat: str |
|||
loss: str |
|||
closs: str |
|||
slat: str |
|||
slon: str |
|||
elat: str |
|||
elon: str |
|||
len: str |
|||
wid: str |
|||
ns: str |
|||
sn: str |
|||
sg: str |
|||
f1: str |
|||
f2: str |
|||
f3: str |
|||
f4: str |
|||
fc: str |
|||
|
|||
def __post_init__(self): |
|||
self.id = int(self.om) |
|||
self.dt = datetime.strptime(self.date, "%Y-%m-%d") |
|||
self.slon = float(self.slon) |
|||
self.slat = float(self.slat) |
|||
self.elon = float(self.elon) |
|||
self.elat = float(self.elat) |
|||
|
|||
def __repr__(self): |
|||
return "<tornado {id} {date}>".format(id=self.id, date=self.dt) |
|||
|
|||
|
|||
def read_data(): |
|||
tornados = [] |
|||
with open("1950-2017_actual_tornadoes.csv", newline='') as csvfile: |
|||
reader = csv.DictReader(csvfile) |
|||
for i, row in enumerate(reader): |
|||
tornados.append(Tornado(**row)) |
|||
return tornados |
|||
|
|||
|
|||
def draw_map(data): |
|||
fig = plt.figure(frameon=False) |
|||
ax = fig.add_subplot(111, projection=proj) |
|||
ax.background_patch.set_facecolor(water_blue) |
|||
ax.set_extent([-125, -65, 20, 50], ccrs.Geodetic()) |
|||
ax.add_feature(land, facecolor="#f0f0f0") |
|||
ax.add_feature(rivers, edgecolor=water_blue) |
|||
ax.add_feature(lakes, facecolor=water_blue) |
|||
|
|||
ax.add_feature(countries, edgecolor="grey", linewidth=0.2, alpha=0.6, dashes='--') |
|||
ax.add_feature(states, edgecolor="grey", linewidth=0.2, alpha=0.4, dashes='--') |
|||
|
|||
for i, t in enumerate(data): |
|||
print(i) |
|||
if t.elon < 0: |
|||
ax.plot([t.slon, t.elon], [t.slat, t.elat], 'r', lw=0.3, transform=ccrs.Geodetic()) |
|||
else: |
|||
ax.plot([t.slon, t.slon], [t.slat, t.slat], 'r', lw=0.3, transform=ccrs.Geodetic()) |
|||
|
|||
fig.tight_layout() |
|||
plt.savefig("tornados_us.png", dpi=320) |
|||
|
|||
|
|||
if __name__ == '__main__': |
|||
ts = read_data() |
|||
draw_map(ts) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue