4.b Plot type - maps


This notebook shows how to plot a map and use mp resources to change the representation.



In [1]:
from IPython.display import Image
import numpy as np
import Ngl

wks = Ngl.open_wks('png', 'plot_maps.png')

plot = Ngl.map(wks)

Image(filename='plot_maps.png')


Out[1]:

To change the representation like gridlines, projection type, or subset a region, you should have a look at the mp resources. See http://ncl.ucar.edu/Document/Graphics/Resources/mp.shtml.


PyNGL provides 18 different map projections. We change the default CylindricalEquidistant projection to Mollweide, Robinson, and Orthographic projection.

Notice: We will anticipate something here and use PyNGL's panel function to show the plots in one.


In [2]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

projections = ['Mollweide', 'Robinson', 'Orthographic']

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'transparent'
mpres.mpLandFillColor        = 'gray90'
mpres.mpInlandWaterFillColor = 'gray90'

for i in range(len(projections)):
    mpres.mpProjection = projections[i]
    mpres.tiMainString = projections[i]
    map = Ngl.map(wks,mpres)

Image(filename='plot_maps.000001.png', retina=True)


Out[2]:

In [3]:
Image(filename='plot_maps.000002.png', retina=True)


Out[3]:

In [4]:
Image(filename='plot_maps.000003.png', retina=True)


Out[4]:

To zoom into map we use the four resources mpMinLatF, mpMaxLatF, mpMinLonF, and mpMaxLonF, but to make them available to the system we have to set mpLimitMode to 'LatLon'.


In [5]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'Transparent'
mpres.mpLandFillColor        = 'Gray90'
mpres.mpInlandWaterFillColor = 'Gray90'

mpres.mpLimitMode            = 'LatLon'       #-- limit map via lat/lon
mpres.mpMinLatF              =  30.           #-- select region to be plotted
mpres.mpMaxLatF              =  60.
mpres.mpMinLonF              = -15.
mpres.mpMaxLonF              =  25.

map = Ngl.map(wks,mpres)

Image(filename='plot_maps.png', retina=True)


Out[5]:

Let us change the line pattern and color of the grid lines.


In [6]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'transparent'
mpres.mpLandFillColor        = 'gray90'
mpres.mpInlandWaterFillColor = 'gray90'

mpres.mpLimitMode            = 'LatLon'       #-- limit map via lat/lon
mpres.mpMinLatF              =  30.           #-- select region to be plotted
mpres.mpMaxLatF              =  60.
mpres.mpMinLonF              = -20.
mpres.mpMaxLonF              =  20.

mpres.mpGridAndLimbOn        =  False         #-- turn off grid lines

mpres.tmXMajorGrid           =  True          #-- x-axis turn on grid lines
mpres.tmXMajorGridLineDashPattern = 14        #-- x-axis grid line dash pattern
mpres.tmXMajorGridLineColor  = 'red'
mpres.tmXMajorGridThicknessF =  5

mpres.tmYMajorGrid           =  True          #-- y-axis turn on grid lines
mpres.tmYMajorGridLineDashPattern = 14        #-- y-axis grid line dash pattern
mpres.tmYMajorGridLineColor  = 'red'
mpres.tmYMajorGridThicknessF =  5

map = Ngl.map(wks,mpres)

Image(filename='plot_maps.png', retina=True)


Out[6]:

Choose a higher map resolution and change the color for land and ocean.


In [7]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'lightblue'
mpres.mpLandFillColor        = 'darkgreen'
mpres.mpInlandWaterFillColor = 'lightblue'

mpres.mpDataSetName          = 'Earth..4'     #-- set map data base version
mpres.mpDataBaseVersion      = 'MediumRes'    #-- MediumRes = Ncarg4_1

mpres.mpLimitMode            = 'LatLon'       #-- limit map via lat/lon
mpres.mpMinLatF              =  30.           #-- select region to be plotted
mpres.mpMaxLatF              =  60.
mpres.mpMinLonF              = -15.
mpres.mpMaxLonF              =  20.

map = Ngl.map(wks,mpres)

Image(filename='plot_maps.png', retina=True)


Out[7]:

PyNGL provides national boundaries, too. To draw them you have to set the resource mpOutlineBoundarySets.


In [8]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'transparent'
mpres.mpLandFillColor        = 'gray90'
mpres.mpInlandWaterFillColor = 'gray90'

mpres.mpDataSetName          = 'Earth..4'     #-- set map data base version
mpres.mpDataBaseVersion      = 'MediumRes'    #-- MediumRes = Ncarg4_1

mpres.mpOutlineBoundarySets  = 'National'     #-- draw only national bounds

mpres.mpLimitMode            = 'LatLon'       #-- limit map via lat/lon
mpres.mpMinLatF              =  35.           #-- select region to be plotted
mpres.mpMaxLatF              =  70.
mpres.mpMinLonF              = -11.
mpres.mpMaxLonF              =  30.

map = Ngl.map(wks,mpres)

Image(filename='plot_maps.png', retina=True)


Out[8]:

You can also point to country by coloring the area of the country with **.


In [9]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'transparent'
mpres.mpLandFillColor        = 'gray90'
mpres.mpInlandWaterFillColor = 'gray90'

mpres.mpDataSetName          = 'Earth..4'     #-- set map data base version
mpres.mpDataBaseVersion      = 'MediumRes'    #-- MediumRes = Ncarg4_1

mpres.mpOutlineBoundarySets  = 'National'     #-- draw only national bounds
mpres.mpFillAreaSpecifiers   = 'Germany'      #-- fill listed states
mpres.mpSpecifiedFillColors  = 'steelblue'    #-- use generated color array

mpres.mpLimitMode            = 'LatLon'       #-- limit map via lat/lon
mpres.mpMinLatF              =  35.           #-- select region to be plotted
mpres.mpMaxLatF              =  70.
mpres.mpMinLonF              = -11.
mpres.mpMaxLonF              =  30.

map = Ngl.map(wks,mpres)

Image(filename='plot_maps.png', retina=True)


Out[9]:

These resources can be used whenever you want to draw maps, even with contours, vectors, and so on.

Finally, let's take a look at the Polar Stereographic Projection.

In this projection, we see some restrictions on the labeling of the map. And we want to get rid of the box around the map setting the resource pmTickMarkDisplayMode to Never.


In [10]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'transparent'
mpres.mpLandFillColor        = 'gray90'
mpres.mpInlandWaterFillColor = 'gray90'

mpres.mpProjection          = 'Stereographic'   #-- set projection
#mpres.mpEllipticalBoundary  =  True             #-- map projection area is limited to an ellipse 
                                                #--     inscribed within the normal rectangular 
mpres.mpLimitMode           = 'LatLon'
mpres.mpMaxLatF             =  90.              #-- maximum latitude; northern hemisphere
mpres.mpMinLatF             =  30.              #-- minimum latitude
mpres.mpCenterLatF          =  90.              #-- center latitude

mpres.pmTickMarkDisplayMode = 'Never'           #-- turn off default ticmkark object, don't draw the box

map = Ngl.map(wks,mpres)

Image(filename='plot_maps.png')


Out[10]:

Hm, no that's not what I've expected. I would like to have the circles of latitude only. And yes of course there exists a resource for that, it's mpEllipticalBoundary.


In [11]:
Ngl.delete_wks(wks)
wks = Ngl.open_wks('png', 'plot_maps.png')

mpres =  Ngl.Resources()

mpres.mpFillOn               =  True
mpres.mpOceanFillColor       = 'transparent'
mpres.mpLandFillColor        = 'gray90'
mpres.mpInlandWaterFillColor = 'gray90'

mpres.mpProjection          = 'Stereographic'   #-- set projection
mpres.mpEllipticalBoundary  =  True             #-- map projection area is limited to an ellipse 
                                                #--     inscribed within the normal rectangular 
mpres.mpLimitMode           = 'LatLon'
mpres.mpMaxLatF             =  90.              #-- maximum latitude; northern hemisphere
mpres.mpMinLatF             =  30.              #-- minimum latitude
mpres.mpCenterLatF          =  90.              #-- center latitude

mpres.pmTickMarkDisplayMode = 'Never'           #-- turn off default ticmkark object, don't draw the box

map = Ngl.map(wks,mpres)

Image(filename='plot_maps.png')


Out[11]:

And no, there are no resources to add the longitude tickmarks and values to the map.

But as in most cases, we can write a function to do that for us. In order to be able to add text to the plot, we must first prevent the call to Ngl.map from creating a plot and closing the graphic output. This happens with the resources nglDraw and nglFrame which have to be set to False. But then you have to make sure that at the end of the script both the plot is drawn and the graphic output is closed.


In [12]:
def add_lon_labels(wksa,map,res):
#-- List the longitude values where you want labels.  It's assumed that longitude=0
#-- is at the bottom of the plot, and 180W at the top. You can adjust as necessary.
  lon_values = np.arange(-180,180,30)
  nlon       = lon_values.shape[0]
  lat_values = np.zeros(nlon,'f') + res.mpMinLatF

#-- Get the NDC coordinates of these lat,lon labels. We'll use this information 
#-- to place labels *outside* of the map plot.
  xndc, yndc = Ngl.datatondc(map,lon_values,lat_values)

#-- Set an array of justification strings to use with the "txJust" resource
#-- for each label, based on which quadrant it appears in.
  just_strs  = ["BottomCenter",                 #-- top of plot
                "BottomRight","BottomRight",    #-- upper left quadrant
                "CenterRight",                  #-- left of plot
                "TopRight","TopRight",          #-- lower left quadrant
                "TopCenter",                    #-- bottom of plot
                "TopLeft","TopLeft",            #-- lower right quadrant
                "CenterLeft",                   #-- right of plot
                "BottomLeft","BottomLeft"]      #-- upper right qudrant

#-- Create an array of longitude labels with "W" and "E" added.
  lon_labels = []
  for i in range(nlon):
      if lon_values[i] == -180:
         lon_labels.append("{:g}W ~C~ ".format(abs(lon_values[i]))) #-- move the label upward
      elif lon_values[i] < 0:
         lon_labels.append("{:g}W ".format(abs(lon_values[i])))     #-- add W and move to the left

      elif lon_values[i] > 0:
         lon_labels.append(" {:g}E".format(lon_values[i]))          #-- add E and move to the right
      else:
         lon_labels.append(" ~C~{:g}".format(lon_values[i]))        #-- move label downward

#-- Loop through each label and add it.
  txres = Ngl.Resources()
  txres.txFontHeightF = 0.01
  for i in range(nlon):
     txres.txJust = just_strs[i]
     Ngl.text_ndc(wksa,lon_labels[i],xndc[i],yndc[i],txres)

        
#-- main program part
wks2 = Ngl.open_wks('png', 'plot_maps2.png')

mpres =  Ngl.Resources()

mpres.nglDraw               =  False
mpres.nglFrame              =  False

mpres.mpFillOn              =  True
mpres.mpOceanFillColor      = 'transparent'
mpres.mpLandFillColor       = 'gray90'
mpres.mpInlandWaterFillColor = 'gray90'

mpres.mpProjection          = 'Stereographic'   #-- set projection
mpres.mpEllipticalBoundary  =  True             #-- map projection area is limited to an ellipse 
                                                #--     inscribed within the normal rectangular 
mpres.mpLimitMode           = 'LatLon'
mpres.mpMaxLatF             =  90.              #-- maximum latitude; northern hemisphere
mpres.mpMinLatF             =  30.              #-- minimum latitude
mpres.mpCenterLatF          =  90.              #-- center latitude

mpres.pmTickMarkDisplayMode = 'Never'           #-- turn off default ticmkark object, don't draw the box

map = Ngl.map(wks2,mpres)

Ngl.draw(map)                                   #-- draw the map in memory

add_lon_labels(wks2,map,mpres)                  #-- call previous defined function, add lon labels to map

Ngl.frame(wks2)                                 #-- close the graphics output

Image(filename='plot_maps2.png')


Out[12]:

In [ ]: