PyNGL > tutorial examples > 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11


Example 5 - contour plots over maps

This example reads in some netCDF files and creates four contour plots over different map projections. Resources are used to change aspects of both the contours and the maps.

To find out more about netCDF, see http://my.unidata.ucar.edu/content/software/netcdf/

To run this example, you must have Numerical Python installed in your Python implementation. Numerical Python (also known as "NumPy") is a Python module allowing for efficient array processing.

This example reads in a netCDF file, so you will need to have the Nio module (this module comes with PyNGL). netCDF is a self-documenting and network-transparent data format - see the netCDF User Guide for details.

There are two ways to run this example:

execute

    pynglex ngl05p
or download
ngl05p.py
and type:
python ngl05p.py

Output from example 5

Frame 1 Frame 2 Frame 3 Frame 4

(Click on any frame to see it enlarged.)


  0. #
  1. #  Import NumPy.
  2. #
  3. import numpy
  4. 
  5. #
  6. #  Import Nio.
  7. #
  8. import Nio
  9. 
 10. #
 11. #  Import Ngl support functions.
 12. #
 13. import Ngl
 14. #
 15. #  Open three netCDF files and get variables.
 16. #
 17. data_dir  = Ngl.pynglpath("data")
 18. cdf_file1 = Nio.open_file(data_dir + "/cdf/941110_P.cdf","r")
 19. cdf_file2 = Nio.open_file(data_dir + "/cdf/sstdata_netcdf.nc","r")
 20. cdf_file3 = Nio.open_file(data_dir + "/cdf/Pstorm.cdf","r")
 21. 
 22. psl = cdf_file1.variables["Psl"]   
 23. sst = cdf_file2.variables["sst"]  
 24. pf  = cdf_file3.variables["p"]  
 25. 
 26. psl_lon  =  cdf_file1.variables["lon"][:]
 27. psl_lat  =  cdf_file1.variables["lat"][:]
 28. psl_nlon =  len(psl_lon)
 29. psl_nlat =  len(psl_lat)
 30. 
 31. sst_lon  =  cdf_file2.variables["lon"][:]
 32. sst_lat  =  cdf_file2.variables["lat"][:]
 33. sst_nlon =  len(sst_lon)
 34. sst_nlat =  len(sst_lat)
 35. 
 36. pf_lon  =  cdf_file3.variables["lon"][:]
 37. pf_lat  =  cdf_file3.variables["lat"][:]
 38. pf_nlon =  len(pf_lon)
 39. pf_nlat =  len(pf_lat)
 40. 
 41. #
 42. #  Open a workstation.
 43. #
 44. wks_type = "ps"
 45. wks = Ngl.open_wks(wks_type,"ngl05p")
 46. 
 47. #----------- Begin first plot -----------------------------------------
 48.  
 49. resources = Ngl.Resources()
 50. 
 51. resources.sfXCStartV = min(psl_lon)
 52. resources.sfXCEndV   = max(psl_lon)
 53. resources.sfYCStartV = min(psl_lat)
 54. resources.sfYCEndV   = max(psl_lat)
 55. 
 56. map = Ngl.contour_map(wks,psl,resources)
 57. 
 58. #----------- Begin second plot -----------------------------------------
 59. 
 60. ic = Ngl.new_color(wks,0.75,0.75,0.75)   # Add gray to the color map
 61. 
 62. resources.mpProjection = "Orthographic" # Change the map projection.
 63. resources.mpCenterLonF = 180.           # Rotate the projection.
 64. resources.mpFillOn     = True           # Turn on map fill.
 65. resources.mpFillColors = [0,-1,ic,-1]   # Fill land and leave oceans
 66.                                           # and inland water transparent.
 67. 
 68. resources.vpXF      = 0.1    # Change the size and location of the
 69. resources.vpYF      = 0.9    # plot on the viewport.
 70. resources.vpWidthF  = 0.7
 71. resources.vpHeightF = 0.7
 72. 
 73. mnlvl = 0                        # Minimum contour level.
 74. mxlvl = 28                       # Maximum contour level.
 75. spcng = 2                        # Contour level spacing.
 76. ncn   = (mxlvl-mnlvl)/spcng + 1  # Number of contour levels.
 77. 
 78. resources.cnLevelSelectionMode = "ManualLevels" # Define your own
 79. resources.cnMinLevelValF       = mnlvl          # contour levels.
 80. resources.cnMaxLevelValF       = mxlvl
 81. resources.cnLevelSpacingF      = spcng
 82. 
 83. resources.cnLineThicknessF     = 2.0   # Double the line thickness.
 84. 
 85. resources.cnFillOn           = True  # Turn on contour level fill.
 86. resources.cnMonoFillColor    = True  # Use one fill color.
 87. resources.cnMonoFillPattern  = False # Use multiple fill patterns.
 88. FillPatterns = numpy.zeros([ncn+1],'i')-1
 89. FillPatterns[ncn-1:ncn+1] =  17
 90. resources.cnFillPatterns     = FillPatterns
 91. resources.cnLineDrawOrder      = "Predraw" # Draw lines and filled
 92. resources.cnFillDrawOrder      = "Predraw" # areas before map gets
 93.                                              # drawn.
 94. 
 95. resources.tiMainString = ~F26~" + cdf_file2.title
 96. 
 97. resources.sfXCStartV = min(sst_lon)   # Define where contour plot
 98. resources.sfXCEndV   = max(sst_lon)   # should lie on the map plot.
 99. resources.sfYCStartV = min(sst_lat)
100. resources.sfYCEndV   = max(sst_lat)
101. 
102. resources.pmLabelBarDisplayMode = "Never"  # Turn off the label bar.
103. 
104. map = Ngl.contour_map(wks,sst[0,:,:],resources) # Draw contours over a map.
105. 
106. #----------- Begin third plot -----------------------------------------
107. 
108. del resources
109. resources = Ngl.Resources()
110. 
111. if hasattr(pf,"_FillValue"):
112.   resources.sfMissingValueV = pf._FillValue
113. 
114. resources.tiXAxisString = "~F25~longitude"
115. resources.tiYAxisString = "~F25~latitude"
116. 
117. resources.cnFillOn              = True     # Turn on contour fill.
118. resources.cnLineLabelsOn        = False    # Turn off line labels.
119. resources.cnInfoLabelOn         = False    # Turn off info label.
120. 
121. resources.nglSpreadColorEnd     = -2       # Don't include gray in contours.
122. 
123. resources.sfXCStartV = min(pf_lon)   # Define where contour plot
124. resources.sfXCEndV   = max(pf_lon)   # should lie on the map plot.
125. resources.sfYCStartV = min(pf_lat)
126. resources.sfYCEndV   = max(pf_lat)
127. 
128. resources.mpProjection = "LambertEqualArea"  # Change the map projection.
129. resources.mpCenterLonF = (pf_lon[pf_nlon-1] + pf_lon[0])/2
130. resources.mpCenterLatF = (pf_lat[pf_nlat-1] + pf_lat[0])/2
131. 
132. resources.mpLimitMode = "LatLon"    # Limit the map view.
133. resources.mpMinLonF   = min(pf_lon)
134. resources.mpMaxLonF   = max(pf_lon)
135. resources.mpMinLatF   = min(pf_lat)
136. resources.mpMaxLatF   = max(pf_lat)
137. resources.mpPerimOn   = True        # Turn on map perimeter.
138. 
139. resources.pmTickMarkDisplayMode = "Never"  # Turn off map tickmarks.
140. 
141. resources.tiMainString = "~F26~January 1996 storm" # Set a title.
142. 
143. resources.vpXF      = 0.1    # Change the size and location of the
144. resources.vpYF      = 0.9    # plot on the viewport.
145. resources.vpWidthF  = 0.7
146. resources.vpHeightF = 0.7
147. 
148. resources.nglFrame = False # Don't advance frame.
149. 
150. #
151. #  Extract the dataset from pf and scale by 0.01, making sure to
152. #  retain the original missing values.
153. #
154. pfa = pf[0,:,:]
155. if hasattr(pf,"_FillValue"):
156.   pfa = 0.01*(pfa*numpy.not_equal(pfa,pf._FillValue)) +   \
157.         pf._FillValue*numpy.equal(pfa,pf._FillValue)
158. else:
159.   pfa = 0.01*pfa
160. #
161. # draw contours over map.
162. #
163. map = Ngl.contour_map(wks,pfa,resources) # Convert pf to "mb" and
164. 
165. txres = Ngl.Resources()
166. txres.txFontHeightF = 0.025  # for a text string.
167. txres.txFontColor   = 4
168. Ngl.text_ndc(wks,"~F25~Pressure (mb)",.41,.185,txres)
169. Ngl.frame(wks)   # Advance the frame.
170. 
171. #---------- Begin fourth plot ------------------------------------------
172. 
173. del resources.tiXAxisString  # Delete some resources you don't
174. del resources.tiYAxisString  # need anymore.
175. del resources.nglFrame
176. 
177.
178. cmap = numpy.array([[1.00, 1.00, 1.00], [0.00, 0.00, 0.00], \
179.                     [.560, .500, .700], [.300, .300, .700], \
180.                     [.100, .100, .700], [.000, .100, .700], \
181.                     [.000, .300, .700], [.000, .500, .500], \
182.                     [.000, .400, .200], [.000, .600, .000], \
183.                     [.000, 1.00, .000], [.550, .550, .000], \
184.                     [.570, .420, .000], [.700, .285, .000], \
185.                     [.700, .180, .000], [.870, .050, .000], \
186.                     [1.00, .000, .000], [0.00, 1.00, 1.00], \
187.                     [.700, .700, .700]],'f')
188. 
189. rlist = Ngl.Resources()
190. rlist.wkColorMap = cmap
191. Ngl.set_values(wks,rlist)
192. 
193. resources.mpFillOn              = True         # Turn on map fill.
194. resources.mpFillAreaSpecifiers  = ["Water","Land","USStatesWater"]
195. resources.mpSpecifiedFillColors = [17,18,17]
196. resources.mpAreaMaskingOn       = True            # Indicate we want to
197. resources.mpMaskAreaSpecifiers  = "USStatesLand"  # mask land.
198. resources.mpPerimOn             = True            # Turn on a perimeter.
199. resources.mpGridMaskMode        = "MaskLand"      # Mask grid over land.
200. resources.cnFillDrawOrder       = "Predraw"       # Draw contours first.
201. 
202. resources.cnLevelSelectionMode = "ExplicitLevels" # Define own levels.
203. resources.cnLevels             = numpy.arange(985.,1046.,5.)
204. 
205. resources.lbTitleString  = "~F25~pressure (mb)" # Title for label bar.
206. resources.cnLinesOn      = False         # Turn off contour lines.
207. resources.lbOrientation  = "Horizontal"  # Label bar orientation.
208. 
209. #
210. #  Extract the dataset from pf and scale by 0.01, making sure to
211. #  retain the original missing values.
212. #
213. pfa = pf[1,:,:]
214. if hasattr(pf,"_FillValue"):
215.   pfa = 0.01*(pfa*numpy.not_equal(pfa,pf._FillValue)) +   \
216.         pf._FillValue*numpy.equal(pfa,pf._FillValue)
217. else:
218.   pfa = 0.01*pfa
219. 
220. map = Ngl.contour_map(wks,pfa,resources)
221. 
222. del map
223. del resources
224. del rlist
225. del txres
226. 
227. Ngl.end()

Explanation of example 5

Line 3:

  import numpy

Import the Numerical Python module. You must have this module installed in your Python implementation. This module is used for efficient array processing. The names of the functions in the Numerical Python package are not exposed by this import, meaning that all functions and attributes in that package will have to be qualified with "numpy".

The Numerical Python package is also known as "NumPy".

Line 8:

  import Nio

Import the Nio module for a netCDF reader. This module comes with the PyNGL package. netCDF is a self-documenting and network-transparent data format - see the netCDF User Guide for details.

Line 13:

  import Ngl

Import all of the Ngl functions. The Ngl module must be on your Python search path.

Line 17:

  data_dir  = Ngl.pynglpath("data")

The built-in function Ngl.pynglpath returns the full pathname for a given PyNGL system directory, or the default value for a particular internal parameter.

Lines 18-20:

  cdf_file1 = Nio.open_file(data_dir + "/cdf/941110_P.cdf","r")
  cdf_file2 = Nio.open_file(data_dir + "/cdf/sstdata_netcdf.nc","r")
  cdf_file3 = Nio.open_file(data_dir + "/cdf/Pstorm.cdf","r")

These lines open three different netCDF files in read only mode.

Lines 22-24:

  psl = cdf_file1.variables["Psl"]   
  sst = cdf_file2.variables["sst"]  
  pf  = cdf_file3.variables["p"]  

These assignments associate Python NumPy objects with netCDF variables. No data is actually read in making these assignments.

Lines 26-27:

  psl_lon  =  cdf_file1.variables["lon"][:]
  psl_lat  =  cdf_file1.variables["lat"][:]

These assignments read the data associated with the netCDF variables lat and lon in cdf_file1 and return NumPy arrays.

Lines 31-32:

  sst_lon  =  cdf_file2.variables["lon"][:]
  sst_lat  =  cdf_file2.variables["lat"][:]

These assignments read the data associated with the netCDF variables sst_lat and sst_lon in cdf_file2 and return NumPy arrays.

Lines 36-37:

  pf_lon  =  cdf_file3.variables["lon"][:]
  pf_lat  =  cdf_file3.variables["lat"][:]

These assignments read the data associated with the netCDF variables pf_lat and pf_lon in cdf_file3 and return NumPy arrays.

Lines 44-45:

  wks_type = "ps"
  wks = Ngl.open_wks(wks_type,"ngl05p")

Open a workstation for drawing the plots.

Line 47:

  #----------- Begin first plot -----------------------------------------

Draw a contour plot over a geographic map.

Lines 51-54:

  resources.sfXCStartV = min(psl_lon)
  resources.sfXCEndV   = max(psl_lon)
  resources.sfYCStartV = min(psl_lat)
  resources.sfYCEndV   = max(psl_lat)

In order to overlay any plot on a map plot, you must specify the latitude and longitude values of where you want the plot to be overlaid on the map. This is done by specifying the X axis coordinates of the overlay plot in longitude coordinates, and the Y axis coordinates of the overlay plot in latitude coordinates.

For a contour plot, if your grid is equally spaced, use the ScalarField resources sfXCStartV and sfXCEndV for setting the minimum and maximum values of the X axis, and sfYCStartV and sfYCEndV for setting the minimum and maximum values of the Y axis. If your grid is not equally spaced, then use the resource arrays sfXArray and sfYArray as illustrated in example 2, to define the whole range of values for both axes. In this example, the *StartV and *EndV resources are being used to define the minimum and maximum latitude and longitude coordinates.

Note: If you don't set any ScalarField resources for determining the minimum and maximum values of the X and Y axes, then the minimum values default to 0.0, and the maximum values default to n-1 and m-1 respectively, where n is the number of points of psl in the X direction, and m is the number of points of psl in the Y direction. This causes the contour plot to be overlaid at the latitude/longitude corners (0.,0.) and (m-1,n-1) which doesn't really make sense.

Line 56:

  map = Ngl.contour_map(wks,psl,resources)

Create and draw a contour plot of the psl variable over a map. The default map projection is cylindrical equidistant. The first argument of the Ngl.contour_map function is the workstation variable returned from the previous call to Ngl.open_wks. The next argument is the NumPy 2-dimensional scalar field to be plotted and should be of NumPy type float, double, or integer. The last argument is the resource list. Note that the contour plot covers the full map. This is because the latitude values you specified in the previous resouce settings go from -90 to 90, and the longitude values go from -180 to 180 (verify this by using printing them out. It is important to note that the Ngl.contour_map function is actually creating two plots, the contour plot and the map plot. The map plot is what's returned from the function, and the contour plot is created behind the scenes. When you overlay one plot on another, the plot being overlaid is called the "base plot," and the plot that is overlaying the base plot is called the "overlay plot." The Ngl.* functions that create such overlay plots always return the base plot as the function value.

Line 58:

  #----------- Begin second plot -----------------------------------------

Draw a contour plot of the first time step of sst (sea surface temperature) over an orthographic projection, and set some resources to fill some of the contour levels with a stipple pattern, to mask the contours over land and to make the plot slightly larger. The concept of the drawing orders of contour and map components is introduced (for the purpose of getting the masking effect that you want).

Line 60:

  ic = Ngl.new_color(wks,0.75,0.75,0.75)

Add a shade of gray to the end of the current color map. ic contains the index location of the new color added.

Lines 62-63:

  resources.mpProjection = "Orthographic" # Change the map projection.
  resources.mpCenterLonF = 180.           # Rotate the projection.

Using the mpProjection resource, change the map projection to "Orthographic" (the default is "CylindricalEquidistant") and rotate the globe so that the center longitude is 180 (the default is 0). There are two kinds of map resources, one for map projections ("MapTransformation"), and one for all other map resources ("MapPlot"). Resources from both groups start with "mp" and are documented in the "MapTransformation and MapPlot resource descriptions" sections.

Lines 64-65:

  resources.mpFillOn     = True           # Turn on map fill.
  resources.mpFillColors = [0,-1,ic,-1]   # Fill land and leave oceans

Turn on the filling of geographical areas in the map with mpFillOn set to True. Each element of the mpFillColors array represents a specific geographic region to fill. Specify the colors for oceans, land, and inland water, respectively, by setting this array to various color index values (the first element is a special one that you don't need to worry about for now). The color index "-1" (also known as "transparent") is a special value indicating you don't want any fill, so in the array above, you are specifying that you don't want oceans and inland water to be filled, and you do want to fill land gray (color index ic is the gray we added to the color map earlier). There are actually six more elements of mpFillColors to set, but since you only want to fill land in this case, you don't need to worry about setting the rest of the elements of this array.

If you don't set mpFillColors, then default color index values are provided.

Lines 68-71:

  resources.vpXF      = 0.1    # Change the size and location of the
  resources.vpYF      = 0.9    # plot on the viewport.
  resources.vpWidthF  = 0.7
  resources.vpHeightF = 0.7

Set some resources to change the size and location of the plot you want to draw in the viewport. The viewport is thought of as the canvas that you draw on, whose lower left corner is at (0.,0.) and upper right corner is at (1.,1.) (NDC coordinates). To position and resize a plot on a viewport, use NDC coorindates to specify the upper left corner of the plot and the height and/or width of the plot. The defaults of vpXF, vpYF, vpWidthF, and vpHeightF are 0.2, 0.8, 0.6, and 0.6 respectively.

Viewport resources are part of the "View" group and start with "vp". They are documented in the View resource descriptions section.

Lines 73-81:

  mnlvl = 0                        # Minimum contour level.
  mxlvl = 28                       # Maximum contour level.
  spcng = 2                        # Contour level spacing.
  ncn   = (mxlvl-mnlvl)/spcng + 1  # Number of contour levels.
  
  resources.cnLevelSelectionMode = "ManualLevels" # Define your own
  resources.cnMinLevelValF       = mnlvl          # contour levels.
  resources.cnMaxLevelValF       = mxlvl
  resources.cnLevelSpacingF      = spcng

Set some resources to define your own contour levels. Setting the resource cnLevelSelectionMode to "ManualLevels" means that the resources cnLevelSpacingF, cnMinLevelValF, and cnMaxLevelValF are used to determine the contour levels. Contour levels are created starting with cnMinLevelValF, and spaced at intervals of the value of cnLevelSpacingF until cnMaxLevelValF is reached. The contour levels are stored in the array resource cnLevels, and in this case, are equal to (0,2,4,...,26,28).

The default of cnLevelSelectionMode is "AutomaticLevels", which means that the contour levels are chosen for you at "nice" values. The resource cnLevelSpacingF can be set by itself in this mode to determine the contour level spacing.

Lines 85-90:

  resources.cnFillOn           = True  # Turn on contour level fill.
  resources.cnMonoFillColor    = True  # Use one fill color.
  resources.cnMonoFillPattern  = False # Use multiple fill patterns.
  FillPatterns = numpy.zeros([ncn+1],'i')-1
  FillPatterns[ncn-1:ncn+1] =  17
  resources.cnFillPatterns     = FillPatterns

Set some resources for filling contour regions greater than 26 with a stipple fill pattern. Note that there is always one more fill area than there are contour levels. This is because all but the last index of cnFillPatterns specifies the fill pattern for any region containing a data value less than the corresponding value of cnLevels, while the last index of cnFillPatterns specifies the fill pattern for regions containing data values greater than the value of cnMaxLevelValF. Since cnLevels has the values (0,2,4,...,28), this means index 0 of cnFillPatterns is for all regions containing values less than 0, index 1 is for region values greater than 0, but less than 2, etc. Index 14 of cnFillPatterns is for region values greater than 26, but less than 28, and index 15 is for region values greater than 28.

To stipple all regions whose values are greater than 26, set the last two elements of cnFillPatterns to 17 (ncn is the number of contour levels, which was calculated above). The rest of the contour levels are set to transparent (index -1).

Lines 91-92:

  resources.cnLineDrawOrder      = "Predraw" # Draw lines and filled
  resources.cnFillDrawOrder      = "Predraw" # areas before map gets

In order to understand how overlaying a plot on a map works, you need to understand something about the drawing order of the various components of the two plots (the map plot and the overlay plot). Also, by being able to specify different drawing orders for the various components of both plots, you can get different masking effects.

[Take a deep breath.]

There are three drawing orders available: "Predraw", "Draw", and "Postdraw". Components drawn during the "Predraw" phase are drawn before components drawn in the "Draw" phase, which, in turn, are drawn before components in the "PostDraw" phase.

The contour plot has three components for which you can specify a drawing order: contour lines, contour filled areas, and contour line labels. The map plot has five components: map outlines, map labels, latitude/longitude grid lines, map fill, and a perimeter.

By default, when a contour plot is drawn over a map plot, all of the contour plot components, the map filled areas, and the map perimeter are drawn during the "Draw" phase, and the map outlines, grid lines, and map labels are drawn during the "Postdraw" phase. Note that only the components that are drawn by default or explicitly set by you are drawn (for example, map filled areas are not drawn by default).

If you set both mpFillOn and cnFillOn to True (as you have done in this case), then you also have to manage the drawing order of the contour and map filled areas, otherwise one will completely cover the other (since they are both drawn during the "Draw" phase). For example, let's assume you want to fill the land areas with a color, and draw filled contours with contour lines over the ocean only. In this case, you want to draw the contour components before you draw the filled land areas, so the land areas effectively mask the contour filled areas. This is accomplished by setting the contour draw order resources cnLineDrawOrder and cnFillDrawOrder to "Predraw" to force these components to be drawn before the filled map areas.

Note that cnLabelDrawOrder is not being set to anything. This is because the contour line labels just happen fall over the oceans areas mostly, and thus it is not necessary to specify that they get drawn in the "Predraw" phase.

Lines 97-100:

  resources.sfXCStartV = min(sst_lon)   # Define where contour plot
  resources.sfXCEndV   = max(sst_lon)   # should lie on the map plot.
  resources.sfYCStartV = min(sst_lat)
  resources.sfYCEndV   = max(sst_lat)

Set these four ScalarField resources to indicate the latitude and longitude values for overlaying the contour plot on the map.

Line 104:

  map = Ngl.contour_map(wks,sst[0,:,:],resources) # Draw contours over a map.

Create and draw a contour plot of the first time step of the sst variable over an orthographic map projection. If you watch the frame as it is being drawn, you will see the contour lines and areas being drawn first, then the filled land areas, and then the contour line labels.

Line 106:

  #----------- Begin third plot -----------------------------------------

Draw a contour plot of the first time step of the pf (pressure) variable over a Lambert equal area projection, and set some resources to fill all of the contour levels and to limit the area of the map view.

Lines 108-109:

  del resources
  resources = Ngl.Resources()

Start with a new list of resources.

Lines 111-112:

  if hasattr(pf,"_FillValue"):
    resources.sfMissingValueV = pf._FillValue

Specify the missing value for the scalar filed data if there is one.

Line 121:

  resources.nglSpreadColorEnd     = -2       # Don't include gray in contours.

The last color in the current colormap is gray, so to make sure this color is not included in the fill colors for contours, set this resource to -2. The default is -1, which indicates the last color in the color map.

Lines 123-126:

  resources.sfXCStartV = min(pf_lon)   # Define where contour plot
  resources.sfXCEndV   = max(pf_lon)   # should lie on the map plot.
  resources.sfYCStartV = min(pf_lat)
  resources.sfYCEndV   = max(pf_lat)

Set these four ScalarField resources to indicate the latitude and longitude values for overlaying the contour plot on the map.

Lines 128-130:

  resources.mpProjection = "LambertEqualArea"  # Change the map projection.
  resources.mpCenterLonF = (pf_lon[pf_nlon-1] + pf_lon[0])/2
  resources.mpCenterLatF = (pf_lat[pf_nlat-1] + pf_lat[0])/2

Change the map projection to "LambertEqualArea" and change the center longitude and latitude values to be the center of the latitude/longitude ranges defined by pf's coordinate variables, lat and lon.

Lines 132-136:

  resources.mpLimitMode = "LatLon"    # Limit the map view.
  resources.mpMinLonF   = min(pf_lon)
  resources.mpMaxLonF   = max(pf_lon)
  resources.mpMinLatF   = min(pf_lat)
  resources.mpMaxLatF   = max(pf_lat)
  resources.mpPerimOn   = True        # Turn on map perimeter.

Since the pf data does not cover the whole map, zoom in on the part of the map that does contain the data.

These values should indicate that the longitude values range from -140 to -52.5, and that the latitude values range from 20 to 60, which is the area surrounding the United States.

When mpLimitMode is set to "LatLon", the resources mpMinLonF, mpMaxLonF, mpMinLatF, and mpMaxLatF are used to determine the limits of the maximum viewable portion of the map in latitude/longitude coordinates. When you zoom in on a map in this manner, the zoomed portion of the map is enlarged to fit the viewport specified.

Lines 143-146:

  resources.vpXF      = 0.1    # Change the size and location of the
  resources.vpYF      = 0.9    # plot on the viewport.
  resources.vpWidthF  = 0.7
  resources.vpHeightF = 0.7

Change the size and location of the plot within the viewport.

Line 148:

  resources.nglFrame = False # Don't advance frame.

nglFrame is a special resource recognized only by the Ngl.* suite of plotting functions.

By default, the frame of the workstation is automatically advanced unless you set nglFrame to False. If you want to annotate the plot with text strings after you draw it, then you don't want to advance the frame just yet.

Lines 154-159:

  pfa = pf[0,:,:]
  if hasattr(pf,"_FillValue"):
    pfa = 0.01*(pfa*numpy.not_equal(pfa,pf._FillValue)) +   \
          pf._FillValue*numpy.equal(pfa,pf._FillValue)
  else:
    pfa = 0.01*pfa
  #

Extract the first time step data from pf and scale by 0.01, making sure to retain the original missing values. NumPy arrays, such pfa can be multiplied just as if they were Python variables.

Line 163:

  map = Ngl.contour_map(wks,pfa,resources) # Convert pf to "mb" and

Create and draw a filled contour plot of the first time step of the pf variable over a Lambert equal area map projection. Note that the pressure values have been converted from Pascals to millibars above, by multiplying all the pf values with 0.01.

Lines 165-168:

  txres = Ngl.Resources()
  txres.txFontHeightF = 0.025  # for a text string.
  txres.txFontColor   = 4
  Ngl.text_ndc(wks,"~F25~Pressure (mb)",.41,.185,txres)

The procedure Ngl.text_ndc allows you to draw text anywhere within the viewport. The first argument of Ngl.text_ndc is the workstation object returned from the previous call to Ngl.open_wks and the second argument is the string to draw. The next two arguments are the X and Y locations of the text in NDC coordinates, and the last argument is the resource list. The text string is centered around the X and Y locations that you specify, unless you set some resources to do otherwise.

Text resources are part of the "TextItem" group and start with the letters "tx". They are documented in the TextItem resource descriptions section. You are using resources here to change the default font height and color of the text string (the default values are 0.05 and 1, respectively). The "~F25~" part of the string is a text function code which changes the font to "Times-Roman." Text function codes are discussed in example 3.

It is important not to confuse TextItem resources with Title resources described in previous examples. Title resources are specifically for controlling the look of the main title at the top of the plot, and the labels for the X and Y axes. TextItem resources are for generic text to be placed anywhere within the viewport.

Line 169:

  Ngl.frame(wks)   # Advance the frame.

Since you set nglFrame to False, you need to advance the frame by calling Ngl.frame. The object wks is the one returned from a previous call to Ngl.open_wks.

Line 171:

  #---------- Begin fourth plot ------------------------------------------

Draw a contour plot of the second time step of the pf variable over a Lambert equal area projection, and set some resources to fill the contour levels, to limit the area of the map view, and to mask the contours over everything but the United States.

Lines 173-175:

  del resources.tiXAxisString  # Delete some resources you don't
  del resources.tiYAxisString  # need anymore.
  del resources.nglFrame

Delete some resources we don't need anymore.

Lines 178-187:

  cmap = numpy.array([[1.00, 1.00, 1.00], [0.00, 0.00, 0.00], \
                      [.560, .500, .700], [.300, .300, .700], \
                      [.100, .100, .700], [.000, .100, .700], \
                      [.000, .300, .700], [.000, .500, .500], \
                      [.000, .400, .200], [.000, .600, .000], \
                      [.000, 1.00, .000], [.550, .550, .000], \
                      [.570, .420, .000], [.700, .285, .000], \
                      [.700, .180, .000], [.870, .050, .000], \
                      [1.00, .000, .000], [0.00, 1.00, 1.00], \
                      [.700, .700, .700]],'f')

Define a new color map.

Lines 189-191:

  rlist = Ngl.Resources()
  rlist.wkColorMap = cmap
  Ngl.set_values(wks,rlist)

Attach the new color map to the output workstation.

Lines 193-197:

  resources.mpFillOn              = True         # Turn on map fill.
  resources.mpFillAreaSpecifiers  = ["Water","Land","USStatesWater"]
  resources.mpSpecifiedFillColors = [17,18,17]
  resources.mpAreaMaskingOn       = True            # Indicate we want to
  resources.mpMaskAreaSpecifiers  = "USStatesLand"  # mask land.

To draw contours over the United States only and fill the rest of the map areas with a color, you need to set some resources to do the filling and masking. You need to set map fill (mpFillOn) and masking (mpAreaMaskingOn) to True, and you also need to specify which areas to fill (mpFillAreaSpecifiers) and which areas to mask (mpMaskAreaSpecifiers). The areas "Water", "Land", "USStatesLand", etc., are from a set of predefined string constants that define map areas by category. The way area masking works is that you first specify what areas to fill, and then you specify what areas to "subtract" or mask. In this case, you are specifying that you want to fill all the map areas except for the United States land areas (the Great Lakes will be filled).

Line 199:

  resources.mpGridMaskMode        = "MaskLand"      # Mask grid over land.

Draw the map grid lines over everything but land. There are other pre-defined strings available for mpGridMaskMode, and they are specified in the documentation for that resource. The default is "MaskNone" which means to draw the grid lines over the whole map.

Line 200:

  resources.cnFillDrawOrder       = "Predraw"       # Draw contours first.

The way area masking works for maps is that a "hole" is left in the areas of the map that you specified with the mpMaskAreaSpecifiers resource, so if you draw the filled contours first and then the map, the filled contours are visible through this "hole."

Lines 202-203:

  resources.cnLevelSelectionMode = "ExplicitLevels" # Define own levels.
  resources.cnLevels             = numpy.arange(985.,1046.,5.)

Set cnLevelSelectionMode to "ExplicitLevels" to indicate that you want to define your own contour levels with the cnLevels resource. The numpy.arange method returns an array of evenly spaced floating point numbers. The first argument is the starting value, the second argument is the ending value, and the third argument is the spacing between values. In this case, numpy.arange returns an array of 13 elements equal to (985.,990.,995.,...,1040.,1045.). The specified end value is slightly larger than the actual end point so there is no problem with exact matching of floating point numbers.

Lines 213-218:

  pfa = pf[1,:,:]
  if hasattr(pf,"_FillValue"):
    pfa = 0.01*(pfa*numpy.not_equal(pfa,pf._FillValue)) +   \
          pf._FillValue*numpy.equal(pfa,pf._FillValue)
  else:
    pfa = 0.01*pfa

Read the data for time step 1 of the netCDF variable pf into the NumPy array pfa. Scale the data by 0.01, making sure to leave the missing values unchanged. Recall that when the data are read into a NumPy array the attribute information associated with the netCDF variable pf is lost, so the attribute check has to be done on pf.

Line 220:

  map = Ngl.contour_map(wks,pfa,resources)

Create and draw a filled contour plot of the second time step of the pf variable over a Lambert equal area map projection. Also, convert pf from Pascals to millibars in the same step.