-
Notifications
You must be signed in to change notification settings - Fork 390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Updated fillstates.py to add Alaska and Hawaii as map insets #366
Conversation
I love this in theory 'cause I forgot too late I left out states, but is there anyway to refine this example so it's not quite this complicated? |
I thought about it and I don't think the code can be simplified much while maintaining the look of the map. I added three elements: Each of the three elements are essential to a scientifically complete map, and the codes I wrote for each of the three elements are already quite simple. Also, for (1) and (2), I choose to use Mercator projection, because (a) this projection makes Alaska look "upright" instead of "tilted", and (b) enables me to draw straight gray lines on the map. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to revise this whole choroplething example, but that isn't the focus of this PR.
Could we also consider the possibility of separating this insetting feature into its own example?
examples/fillstates.py
Outdated
m_.plot(np.linspace(-175,-171),np.linspace(26,22),linewidth=1., | ||
color=light_gray,latlon=True) | ||
m_.plot(np.linspace(-171,-171),np.linspace(22,20),linewidth=1., | ||
color=light_gray,latlon=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These plot commands are distracting and largely overkill anyway. The linspace() doesn't really make sense since all you need are the vertexes. This could be simplified into two plot() calls, or possibly even two Polygons with 'none'
as their facecolor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modified these lines into four lines.
However, there is a tiny difference between the new result and old result: the light gray lines in the new version are now slightly thicker and look more "blurred" than the old version...
#%% --------- 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}$]') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not a regular colorbar creation approach instead of manually creating axes and such? An example like this is already getting pretty complicated, so we should aim to reduce complexity where-ever possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried the regular m.colorbar()
way, but I couldn't figure out what I should use for mappable
. Please provide advice if you can. Thanks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @jsh9:
I have this file around where I was coloring countries based on population. I used it for teaching purposes, so there is an intentional bug somewhere, but you can check out how I did the colorbar there at the end:
https://github.com/guziy/CMOS-python-tutorial/blob/master/fiona_test.py
Cheers
examples/fillstates.py
Outdated
seg = list(map(lambda (x,y): (x-1900000, y+250000), seg)) | ||
color = rgb2hex(colors[statenames[nshape]]) | ||
elif shapedict['NAME'] == 'Alaska' and float(shapedict['AREA']) > AREA_2: | ||
seg = list(map(lambda (x,y): (AK_SCALE*x-200000, AK_SCALE*y-650000), seg)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not a list comprehension? Might be easier to read.
Also, could you include a comment to explain how these numbers came about (so that others could adapt this process for other projections, perhaps)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I will change them to list comprehension. I copied and pasted the list(map(lambda())) directly from here https://stackoverflow.com/questions/39742305/how-to-use-basemap-python-to-plot-us-with-50-states without much thinking
These number are achieved by trial and error; I will add comments to point this out.
#%% --------- 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, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can this be read in only once and the drawbounds be a part of drawing the polygons?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really. Alaska and Hawaii are plotted using Mercator projection, while the other contiguous states are plotted using Lambert projection. The reason for choosing Mercator projection to plot Alaska and Hawaii is purely an aesthetic one, and I have noticed that this map-making choice (i.e., Alaska and Hawaii being plotted by Mercator projection) was adopted from as early as half a century ago.
I am not sure what you meant by "drawbounds be a part of drawing the polygons". Line 20 is in the original example script.
examples/fillstates.py
Outdated
# cycle through state names, color each one. | ||
|
||
#%% --------- cycle through state names, color each one. -------------------- | ||
fig = plt.gcf() # get current figure instance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fig, ax = plt.subplots()
at the top and then pass the ax kwarg to the Basemap methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original example script has ax = plt.gca()
on that location, and I just added fig = plt.gcf()
on top of it because I wanted the changed to the original script to be minimal.
I can change it to what you suggested. It is indeed more elegant.
Made a new commit just now. Suggestions welcome! |
Sorry this sat for so long! Hurricane season distracted me and I forgot to get back to this. Thanks for your contribution! |
I modified the example so that the map output imitates the map shown here (basically, Alaska and Hawaii are shown on the bottom left corner of the main map as small insets): https://en.wikipedia.org/wiki/List_of_U.S._states_by_population_density
I based my modifications partly on some code snippets in this stackoverflow thread (https://stackoverflow.com/questions/39742305/how-to-use-basemap-python-to-plot-us-with-50-states).