Skip to content
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

Merged
merged 2 commits into from
Jan 2, 2018
Merged

Updated fillstates.py to add Alaska and Hawaii as map insets #366

merged 2 commits into from
Jan 2, 2018

Conversation

jsh9
Copy link
Contributor

@jsh9 jsh9 commented Aug 7, 2017

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).

@story645
Copy link
Member

story645 commented Aug 7, 2017

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?

@jsh9
Copy link
Contributor Author

jsh9 commented Aug 7, 2017

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:
(1) Alaska and Hawaii
(2) Light gray lines to bound Alaska and Hawaii so that people know that they are map insets
(3) Color bar showing what each color means

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.

Copy link
Member

@WeatherGod WeatherGod left a 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?

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)
Copy link
Member

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?

Copy link
Contributor Author

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}$]')
Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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

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))
Copy link
Member

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)?

Copy link
Contributor Author

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,
Copy link
Member

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?

Copy link
Contributor Author

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.

# cycle through state names, color each one.

#%% --------- cycle through state names, color each one. --------------------
fig = plt.gcf() # get current figure instance
Copy link
Member

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?

Copy link
Contributor Author

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.

@jsh9
Copy link
Contributor Author

jsh9 commented Aug 9, 2017

Made a new commit just now. Suggestions welcome!

@WeatherGod WeatherGod merged commit 140f9fe into matplotlib:master Jan 2, 2018
@WeatherGod
Copy link
Member

Sorry this sat for so long! Hurricane season distracted me and I forgot to get back to this. Thanks for your contribution!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants