Make a geographic map in Cartopy. Add locations or 'stations' as x/y pairs.¶
More tutorial info: https://scitools.org.uk/cartopy/docs/latest/
INSTRUCTIONS: You will need to complete the code below
Note: Cartopy has to be installed separately.
At the command line, this should work as >> conda install -c conda-forge cartopyIf the conda install takes too long, then try installing via the pip package manager.
$ pip --version #this should return some version info.
$ pip install cartopy # This should download and install Cartopy - hopefully version 0.22.
At the end of this exercise, you will know how to add data points (x/y pairs) to a map. This is a way to graph the position of GPS points collected using your smartphone or other GPS device. The module Cartopy extends the basic capabilities of Matplotlib for making geographic maps. It is easy to use and builds maps rapidly with a few short commands. More complicated tasks are also possible, including adding topography, bathymetry or contouring other info on top of a map. This can be image data, NASA satellite data, earthquake data - the possibilities are many.
# Import numpy and pyplot as well as cartopy.
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
# Create a figure object and specify its size
# plt.figure(figsize=(8,8))
# Add a plot axis using the axis command. Here, Matplotlib is told this will be a map axis with the projection= command.
# ax = plt.axes(projection=ccrs.Robinson())
# Draw the outline of the coastlines.
# ax.coastlines() #Note
# Let's visualize a few of the many projections that cartopy permits
# Uncomment the lines below to generate the figure.
### NOTE: You can uncomment/comment a block of code by highlighting it and typing CTRL + /, that's "Control Slash".
projections = [ccrs.PlateCarree(),
ccrs.Robinson(),
ccrs.Mercator(),
ccrs.Orthographic(),
ccrs.InterruptedGoodeHomolosine(),
ccrs.Mollweide()
]
i = 1
plt.figure(figsize=(10,5))
for proj in projections:
#plt.figure()
geoax = plt.subplot(3,2,i,projection=proj)
#geoax.stock_img()
geoax.coastlines()
geoax.set_title(f'{type(proj)}')
i+=1
# We set the bounds of the map using the set_extent() input.
extent = [-150, -50, 20, 50]
#ax = plt.axes(projection=ccrs.Mollweide())
#ax.set_extent(extent)
#ax.coastlines(resolution='50m')
#ax.stock_img()
#plt.show()
# Using the feature library, we can add geographic features, such as land masks, coastline boundaries, and rivers.
import cartopy.feature as cfeature
ax = plt.axes(projection=ccrs.Mollweide())
ax.set_extent(extent)
ax.coastlines(resolution='50m')
#ax.stock_img()
ax.add_feature(cfeature.LAND,zorder=1)
ax.add_feature(cfeature.COASTLINE,zorder=1)
ax.add_feature(cfeature.RIVERS,zorder=1)
ax.gridlines()
plt.show()
Complete the rest of the assignment on your own or with your team¶
# Load the data file
# Go to https://earthquake.usgs.gov/earthquakes/search/
# Download all earthquakes in the past 30 days. Choose .csv under Other Options.
# Move that file into the directory where you are working and load it using the loadtxt command.
stations = np.loadtxt('query.csv',delimiter=',',skiprows=1,usecols=(1,2))
stations
# First just use a standard x-y plot to examine the stations.
# Graph using symbols, e.g. '.' dots or 'o' circles or 's' squares.
# Label the axes Lat and Lon - make sure you know which is which. Remember Lat is restricted between -90 and 90.
plt.figure() #create a figure objec
plt.scatter()
plt.plot(xdtata,ydata,)
plt.show() #render all the objects
The map you just made using Matplotlib gives you a vague idea of the distribution of earthquakes, it even roughly draws out the continental shapes that may be familiar to you, but it does not succeed in conveying the full geographic information we need. Therefore, we need to make a map using geographic projections. This is where cartopy becomes useful.
# Define a bounding box in polar coordinates (Lat, Lon) that tells cartopy how to set the
# map limits. This is so the map scale will match the scale of the points being plotted. Ie, you don't want a map
# of the world, if all the points are in Narragansett Bay.
# Your box should have four sides - North, East, West, South. The north and south limits are defined by the range of
# your latitudes. Similarly, the east and west limits are defined by the range of your longitudes.
# lat = stations[:,0].copy()
# Determine the limits of your bounding box.
# Go in order of BBox = [E,W,S,N] or [Left, Right, Bottom, Top]
# NOTE: Try to use coding to introduce flexibility to the Bounding Box limits, rather than hardwire them.
# This is important, because your data may change. Here, it is helpful to use the lat/lon data to establish the
# map limits.
Now that you have your bounding box, you are ready to create a Map object.
You will need to feed Cartopy the following details:
+ The sides of the bounding box, using the set_extent() command
+ The projection to use (I recomend using PlateCarree())
+ The resolution for drawing the coastlines
Coordinate transformation
NOTE: There are may be at least 2 coordinate systems used when making maps with geographic data. The first (1) is the geographic coordinates, which can be Lat/Lon or UTM or spherical (Phi,Theta,r). Usually they are Lat/Lon in degrees. The second (2) is the coordinate system on map axis, which demarcates the space on the figure. The transformation from geographic to figure coordinates happens inside the Matplotlib functions, such as e.g. plot().
It is necessary to specify the coordinate system for use in the coordinate transformation. That is >> transform=ccrs.Geodetic() or similar.
# Define the bounding box extent and use that with the results from the cells above to make
# a plot of all earthquakes in the past 30 days.
# BBox = [x0,x1,y0,y1], so [Lon_e, Lon_w,Lat_s,Lat_n]
# Create a figure object
fig = plt.figure(figsize=(15,10))
# Add axes and define a projection
# Add some features to make it pretty
# plot the earthquake locations on the map. Specify the correct coordinate transform.
plt.show()
Now do the same thing for All Earthquakes in the past 6 hours.¶
Note: Your bounding box should be a lot smaller (focused in on the fewer points of the past hour).
stations = np.loadtxt('all_hour.csv',delimiter=',',skiprows=1,usecols=(1,2))
# Define a bounding box in polar coordinates (Lat, Lon)
lat = stations[:,0].copy()
# Go in order of BBox = [E,W,S,N] or [Left, Right, Bottom, Top]
# Add axes and define a projection
# Add some features to make it pretty
# plot the earthquake locations on the map. Specify the correct coordinate transform.
# Change the fill color of the continents
# Add the location of a nearby city and mark it with a symbol and label.
# Note that zorder controls the layers. If you want something on top to show, it needs a higher zorder.
CSC 593: Download a satellite image of a recent natural disaster (e.g. wildfire, tropical storm) and overlay that on a map coordinate system. (Extra credit for OCG 404).¶
Check out this example https://scitools.org.uk/cartopy/docs/latest/matplotlib/advanced_plotting.html#images
What to turn in:¶
Upload this .ipynb with the completed code for generating map limits and any other supporting docs, like the .csv files you downloaded. Add comments to your code as you see fit.