Permalink
d1f0e17 Apr 27, 2018
3 contributors

Users who have contributed to this file

@jswhit @jsh9 @ocefpaf
143 lines (127 sloc) 5.23 KB
from __future__ import (absolute_import, division, print_function)
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap as Basemap
from matplotlib.colors import rgb2hex, Normalize
from matplotlib.patches import Polygon
from matplotlib.colorbar import ColorbarBase
fig, ax = plt.subplots()
# Lambert Conformal map of lower 48 states.
m = Basemap(llcrnrlon=-119,llcrnrlat=20,urcrnrlon=-64,urcrnrlat=49,
projection='lcc',lat_1=33,lat_2=45,lon_0=-95)
# Mercator projection, for Alaska and Hawaii
m_ = Basemap(llcrnrlon=-190,llcrnrlat=20,urcrnrlon=-143,urcrnrlat=46,
projection='merc',lat_ts=20) # do not change these numbers
#%% --------- draw state boundaries ----------------------------------------
## data from U.S Census Bureau
## http://www.census.gov/geo/www/cob/st2000.html
shp_info = m.readshapefile('st99_d00','states',drawbounds=True,
linewidth=0.45,color='gray')
shp_info_ = m_.readshapefile('st99_d00','states',drawbounds=False)
## population density by state from
## http://en.wikipedia.org/wiki/List_of_U.S._states_by_population_density
popdensity = {
'New Jersey': 438.00,
'Rhode Island': 387.35,
'Massachusetts': 312.68,
'Connecticut': 271.40,
'Maryland': 209.23,
'New York': 155.18,
'Delaware': 154.87,
'Florida': 114.43,
'Ohio': 107.05,
'Pennsylvania': 105.80,
'Illinois': 86.27,
'California': 83.85,
'Hawaii': 72.83,
'Virginia': 69.03,
'Michigan': 67.55,
'Indiana': 65.46,
'North Carolina': 63.80,
'Georgia': 54.59,
'Tennessee': 53.29,
'New Hampshire': 53.20,
'South Carolina': 51.45,
'Louisiana': 39.61,
'Kentucky': 39.28,
'Wisconsin': 38.13,
'Washington': 34.20,
'Alabama': 33.84,
'Missouri': 31.36,
'Texas': 30.75,
'West Virginia': 29.00,
'Vermont': 25.41,
'Minnesota': 23.86,
'Mississippi': 23.42,
'Iowa': 20.22,
'Arkansas': 19.82,
'Oklahoma': 19.40,
'Arizona': 17.43,
'Colorado': 16.01,
'Maine': 15.95,
'Oregon': 13.76,
'Kansas': 12.69,
'Utah': 10.50,
'Nebraska': 8.60,
'Nevada': 7.03,
'Idaho': 6.04,
'New Mexico': 5.79,
'South Dakota': 3.84,
'North Dakota': 3.59,
'Montana': 2.39,
'Wyoming': 1.96,
'Alaska': 0.42}
#%% -------- choose a color for each state based on population density. -------
colors={}
statenames=[]
cmap = plt.cm.hot_r # use 'reversed hot' colormap
vmin = 0; vmax = 450 # set range.
norm = Normalize(vmin=vmin, vmax=vmax)
for shapedict in m.states_info:
statename = shapedict['NAME']
# skip DC and Puerto Rico.
if statename not in ['District of Columbia','Puerto Rico']:
pop = popdensity[statename]
# calling colormap with value between 0 and 1 returns
# rgba value. Invert color range (hot colors are high
# population), take sqrt root to spread out colors more.
colors[statename] = cmap(np.sqrt((pop-vmin)/(vmax-vmin)))[:3]
statenames.append(statename)
#%% --------- cycle through state names, color each one. --------------------
for nshape,seg in enumerate(m.states):
# skip DC and Puerto Rico.
if statenames[nshape] not in ['Puerto Rico', 'District of Columbia']:
color = rgb2hex(colors[statenames[nshape]])
poly = Polygon(seg,facecolor=color,edgecolor=color)
ax.add_patch(poly)
AREA_1 = 0.005 # exclude small Hawaiian islands that are smaller than AREA_1
AREA_2 = AREA_1 * 30.0 # exclude Alaskan islands that are smaller than AREA_2
AK_SCALE = 0.19 # scale down Alaska to show as a map inset
HI_OFFSET_X = -1900000 # X coordinate offset amount to move Hawaii "beneath" Texas
HI_OFFSET_Y = 250000 # similar to above: Y offset for Hawaii
AK_OFFSET_X = -250000 # X offset for Alaska (These four values are obtained
AK_OFFSET_Y = -750000 # via manual trial and error, thus changing them is not recommended.)
for nshape, shapedict in enumerate(m_.states_info): # plot Alaska and Hawaii as map insets
if shapedict['NAME'] in ['Alaska', 'Hawaii']:
seg = m_.states[int(shapedict['SHAPENUM'] - 1)]
if shapedict['NAME'] == 'Hawaii' and float(shapedict['AREA']) > AREA_1:
seg = [(x + HI_OFFSET_X, y + HI_OFFSET_Y) for x, y in seg]
color = rgb2hex(colors[statenames[nshape]])
elif shapedict['NAME'] == 'Alaska' and float(shapedict['AREA']) > AREA_2:
seg = [(x*AK_SCALE + AK_OFFSET_X, y*AK_SCALE + AK_OFFSET_Y)\
for x, y in seg]
color = rgb2hex(colors[statenames[nshape]])
poly = Polygon(seg, facecolor=color, edgecolor='gray', linewidth=.45)
ax.add_patch(poly)
ax.set_title('United states population density by state')
#%% --------- Plot bounding boxes for Alaska and Hawaii insets --------------
light_gray = [0.8]*3 # define light gray color RGB
x1,y1 = m_([-190,-183,-180,-180,-175,-171,-171],[29,29,26,26,26,22,20])
x2,y2 = m_([-180,-180,-177],[26,23,20]) # these numbers are fine-tuned manually
m_.plot(x1,y1,color=light_gray,linewidth=0.8) # do not change them drastically
m_.plot(x2,y2,color=light_gray,linewidth=0.8)
#%% --------- Show color bar ---------------------------------------
ax_c = fig.add_axes([0.9, 0.1, 0.03, 0.8])
cb = ColorbarBase(ax_c,cmap=cmap,norm=norm,orientation='vertical',
label=r'[population per $\mathregular{km^2}$]')
plt.show()