Skip to content

Commit e98557f

Browse files
committed
Update earthquakes example
- add cartopy as alternative to deprecated basemap - prevent numpy warning "Passing (type, 1) or '1type' as a synonym of type is deprecated"
1 parent b29c18d commit e98557f

File tree

3 files changed

+91
-54
lines changed

3 files changed

+91
-54
lines changed

README.rst

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ Earthquakes
657657
We'll now use the rain animation to visualize earthquakes on the planet from
658658
the last 30 days. The USGS Earthquake Hazards Program is part of the National
659659
Earthquake Hazards Reduction Program (NEHRP) and provides several data on their
660-
`website <http://earthquake.usgs.gov>`_. Those data are sorted according to
660+
`website <https://earthquake.usgs.gov>`_. Those data are sorted according to
661661
earthquakes magnitude, ranging from significant only down to all earthquakes,
662662
major or minor. You would be surprised by the number of minor earthquakes
663663
happening every hour on the planet. Since this would represent too much data
@@ -675,15 +675,14 @@ whose content is given by the first line::
675675

676676
We are only interested in latitude, longitude and magnitude and we won't parse
677677
time of event (ok, that's bad, feel free to send me a PR).
678-
678+
679679

680680
.. code:: python
681681
682682
import urllib
683-
from mpl_toolkits.basemap import Basemap
684683
685-
# -> http://earthquake.usgs.gov/earthquakes/feed/v1.0/csv.php
686-
feed = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/"
684+
# -> https://earthquake.usgs.gov/earthquakes/feed/v1.0/csv.php
685+
feed = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/"
687686
688687
# Significant earthquakes in the last 30 days
689688
# url = urllib.request.urlopen(feed + "significant_month.csv")
@@ -701,50 +700,64 @@ time of event (ok, that's bad, feel free to send me a PR).
701700
data = url.read()
702701
data = data.split(b'\n')[+1:-1]
703702
E = np.zeros(len(data), dtype=[('position', float, 2),
704-
('magnitude', float, 1)])
703+
('magnitude', float)])
705704
706705
for i in range(len(data)):
707-
row = data[i].split(',')
706+
row = data[i].split(b',')
708707
E['position'][i] = float(row[2]),float(row[1])
709708
E['magnitude'][i] = float(row[4])
710709
711710
712711
Now, we need to draw the earth on a figure to show precisely where the earthquake
713712
center is and to translate latitude/longitude in some coordinates matplotlib
714713
can handle. Fortunately, there is the `basemap
715-
<http://matplotlib.org/basemap/>`_ project (that tends to be replaced by the
716-
more complete `cartopy <http://scitools.org.uk/cartopy/>`_) that is really
714+
<https://matplotlib.org/basemap/>`_ project (which is now deprecated in favor
715+
of the `cartopy <https://scitools.org.uk/cartopy/docs/latest/>`_ project) that is really
717716
simple to install and to use. First step is to define a projection to draw the
718717
earth onto a screen (there exists many different projections) and we'll stick
719718
to the `mill` projection which is rather standard for non-specialist like me.
720-
719+
721720

722721
.. code:: python
723722
723+
from mpl_toolkits.basemap import Basemap
724724
fig = plt.figure(figsize=(14,10))
725725
ax = plt.subplot(1,1,1)
726726
727-
earth = Basemap(projection='mill')
727+
map = Basemap(projection='mill')
728728
729729
730730
Next, we request to draw coastline and fill continents:
731731

732732
.. code:: python
733-
734-
earth.drawcoastlines(color='0.50', linewidth=0.25)
735-
earth.fillcontinents(color='0.95')
736733
737-
The `earth` object will also be used to translate coordinates quite
738-
automatically. We are almost finished. Last step is to adapt the rain code and
739-
put some eye candy:
734+
map.drawcoastlines(color='0.50', linewidth=0.25)
735+
map.fillcontinents(color='0.95')
736+
737+
For cartopy, the steps are quite similar:
738+
739+
.. code:: python
740+
741+
import cartopy
742+
ax = plt.axes(projection=cartopy.crs.Miller())
743+
ax.coastlines(color='0.50', linewidth=0.25)
744+
ax.add_feature(cartopy.feature.LAND, color='0.95')
745+
ax.set_global()
746+
trans = cartopy.crs.PlateCarree()
747+
748+
749+
We are almost finished. Last step is to adapt the rain code and
750+
put some eye candy. For basemap we use the map object to
751+
transform the coordinates whereas for cartopy we use the transform_point
752+
function of the chosen Miller projection:
740753

741754

742755
.. code:: python
743756
744757
P = np.zeros(50, dtype=[('position', float, 2),
745-
('size', float, 1),
746-
('growth', float, 1),
747-
('color', float, 4)])
758+
('size', float),
759+
('growth', float),
760+
('color', float, 4)])
748761
scat = ax.scatter(P['position'][:,0], P['position'][:,1], P['size'], lw=0.5,
749762
edgecolors = P['color'], facecolors='None', zorder=10)
750763
@@ -756,7 +769,8 @@ put some eye candy:
756769
P['size'] += P['growth']
757770
758771
magnitude = E['magnitude'][current]
759-
P['position'][i] = earth(*E['position'][current])
772+
P['position'][i] = map(*E['position'][current]) if use_basemap else \
773+
cartopy.crs.Miller().transform_point(*E['position'][current], cartopy.crs.PlateCarree())
760774
P['size'][i] = 5
761775
P['growth'][i]= np.exp(magnitude) * 0.1
762776
@@ -770,8 +784,8 @@ put some eye candy:
770784
scat.set_offsets(P['position'])
771785
return scat,
772786
773-
774-
animation = FuncAnimation(fig, update, interval=10)
787+
788+
animation = FuncAnimation(fig, update, interval=10, blit=True)
775789
plt.show()
776790
777791
@@ -781,7 +795,7 @@ If everything went well, you should obtain something like this (with animation):
781795
:target: scripts/earthquakes.py
782796
:width: 50%
783797

784-
798+
785799
Other Types of Plots
786800
====================
787801

scripts/check-installation.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,30 @@
3737
else:
3838
print("ok")
3939

40-
# Check for basemap
40+
# Check for basemap or cartopy
4141
try:
42-
import mpl_toolkits.basemap as basemap
42+
import mpl_toolkits.basemap as basemap
43+
check_for_cartopy = False
4344
except:
44-
print("This tutorial requires basemap\n")
45-
sys.exit()
46-
print("Check for basemap: ", end="")
47-
if LooseVersion(basemap.__version__) < LooseVersion("1.0"):
48-
print("basemape is too old (< 1.0) \n")
49-
sys.exit()
50-
else:
51-
print("ok")
52-
53-
# Check for urllib
54-
try:
55-
import urllib
56-
except:
57-
print("This tutorial requires urllib")
45+
check_for_cartopy = True
5846
else:
59-
print("Check for urllib: ok")
47+
print("Check for basemap: ", end="")
48+
if LooseVersion(basemap.__version__) < LooseVersion("1.0"):
49+
print("basemap is too old (< 1.0) \n")
50+
sys.exit()
51+
else:
52+
print("ok")
53+
54+
if check_for_cartopy:
55+
try:
56+
import cartopy
57+
except:
58+
print("This tutorial requires either basemap or cartopy\n")
59+
sys.exit()
60+
61+
print("Check for cartopy: ", end="")
62+
if LooseVersion(cartopy.__version__) < LooseVersion("0.15"):
63+
print("cartopy is too old (< 0.15) \n")
64+
sys.exit()
65+
else:
66+
print("ok")

scripts/earthquakes.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,20 @@
1010
import matplotlib
1111
matplotlib.rcParams['toolbar'] = 'None'
1212
import matplotlib.pyplot as plt
13-
from mpl_toolkits.basemap import Basemap
1413
from matplotlib.animation import FuncAnimation
14+
try:
15+
from mpl_toolkits.basemap import Basemap
16+
use_basemap = True
17+
except ImportError:
18+
import cartopy
19+
use_basemap = False
20+
1521

1622

1723
# Open the earthquake data
1824
# -------------------------
19-
# -> http://earthquake.usgs.gov/earthquakes/feed/v1.0/csv.php
20-
feed = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/"
25+
# -> https://earthquake.usgs.gov/earthquakes/feed/v1.0/csv.php
26+
feed = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/"
2127

2228
# Significant earthquakes in the past 30 days
2329
# url = urllib.urlopen(feed + "significant_month.csv")
@@ -35,24 +41,32 @@
3541
data = url.read()
3642
data = data.split(b'\n')[+1:-1]
3743
E = np.zeros(len(data), dtype=[('position', float, 2),
38-
('magnitude', float, 1)])
44+
('magnitude', float)])
3945
for i in range(len(data)):
4046
row = data[i].split(b',')
4147
E['position'][i] = float(row[2]),float(row[1])
4248
E['magnitude'][i] = float(row[4])
4349

4450

4551
fig = plt.figure(figsize=(14,10))
46-
ax = plt.subplot(1,1,1)
4752
P = np.zeros(50, dtype=[('position', float, 2),
48-
('size', float, 1),
49-
('growth', float, 1),
53+
('size', float),
54+
('growth', float),
5055
('color', float, 4)])
5156

52-
# Basemap projection
53-
map = Basemap(projection='mill')
54-
map.drawcoastlines(color='0.50', linewidth=0.25)
55-
map.fillcontinents(color='0.95')
57+
if use_basemap:
58+
ax = plt.subplot(1,1,1)
59+
# Basemap projection
60+
map = Basemap(projection='mill')
61+
map.drawcoastlines(color='0.50', linewidth=0.25)
62+
map.fillcontinents(color='0.95')
63+
else:
64+
# Cartopy projection
65+
ax = plt.axes(projection=cartopy.crs.Miller())
66+
ax.coastlines(color='0.50', linewidth=0.25)
67+
ax.add_feature(cartopy.feature.LAND, color='0.95')
68+
ax.set_global()
69+
5670
scat = ax.scatter(P['position'][:,0], P['position'][:,1], P['size'], lw=0.5,
5771
edgecolors = P['color'], facecolors='None', zorder=10)
5872

@@ -65,7 +79,8 @@ def update(frame):
6579
P['size'] += P['growth']
6680

6781
magnitude = E['magnitude'][current]
68-
P['position'][i] = map(*E['position'][current])
82+
P['position'][i] = map(*E['position'][current]) if use_basemap else \
83+
cartopy.crs.Miller().transform_point(*E['position'][current], cartopy.crs.PlateCarree())
6984
P['size'][i] = 5
7085
P['growth'][i]= np.exp(magnitude) * 0.1
7186

@@ -77,7 +92,8 @@ def update(frame):
7792
scat.set_facecolors(P['color']*(1,1,1,0.25))
7893
scat.set_sizes(P['size'])
7994
scat.set_offsets(P['position'])
95+
return scat,
8096

8197
plt.title("Earthquakes > 4.5 in the last 30 days")
82-
animation = FuncAnimation(fig, update, interval=10)
98+
animation = FuncAnimation(fig, update, interval=10, blit=True)
8399
plt.show()

0 commit comments

Comments
 (0)