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


Example 7 - two XY plots on one frame

This example illustrates the use of the Ngl implementations of theFitgrid routines Ngl.ftcurvp and Ngl.ftcurvpi and creates two XY plots on the same frame. It also illustrates how to draw text and polylines in a specified area of the viewport.

The function Ngl.ftcurvp calculates an interpolatory spline under tension through a sequence of functional values for a periodic function, and Ngl.ftcurvpi calculates an integral of an interpolatory spline between two specified points.

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.

There are two ways to run this example:

execute

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

Output from example 7

Frame 1

(Click on the frame to see it enlarged.)


  0. #
  1. #  Import NumPy
  2. #
  3. import numpy
  4. 
  5. #
  6. #  Import Ngl support functions.
  7. #
  8. import Ngl
  9. 
 10. xi = [  0.000, 0.210, 0.360, 0.540, 1.000, 1.500, 1.970, 2.300, \
 11.         2.500, 2.700  ]
 12. yi = [  0.000, 2.600, 3.000, 2.500, 0.000,-1.000, 0.000, 0.800, \
 13.         0.920, 0.700  ]
 14. 
 15. npts   = 201
 16. xl     =  -1.0
 17. xr     =   5.0
 18. inc    = (xr-xl)/(npts-1)
 19. xo     = numpy.arange(xl,xr+0.0001,inc) # Create output X coordinate array.
 20.                                         # Add a small amount to xr to make
 21.                                         # sure xr is the final value in the
 22.                                         # range.
 23. period = 3.0
 24. yo = Ngl.ftcurvp(xi, yi, period, xo)  # Interpolate.
 25. 
 26. yint = numpy.zeros(npts,'f')
 27. for i in xrange(npts):
 28.   yint[i] = Ngl.ftcurvpi(0., xo[i], period, xi, yi)
 29. 
 30. cmap = ["white","black","red","green","blue","yellow"]
 31. rlist = Ngl.Resources()
 32. rlist.wkColorMap = cmap
 33. 
 34. wks_type = "ps"
 35. wks = Ngl.open_wks(wks_type,"ngl07p",rlist) # Open an X11 workstation.
 36. txres = Ngl.Resources()   # Set up variable for TextItem resources.
 37. xyres = Ngl.Resources()   # Set up variable for XyPlot resources.
 38. gsres = Ngl.Resources()   # Set up variable for GraphicStyle resources.
 39. 
 40. xyres.nglFrame               = False     # Don't advance the frame.
 41. xyres.nglMaximize            = False     # Don't advance the frame.
 42. 
 43. xyres.tmXTBorderOn           = False     # Don't draw top axis.
 44. xyres.tmXTOn                 = False     # Don't draw top axis tick marks.
 45. xyres.tmBorderThicknessF     = 1.0       # Default thickness is 2.0
 46. 
 47. xyres.tmXBLabelFont          = 21        # Change font and size of
 48. xyres.tmXBLabelFontHeightF   = 0.025     # X axis labels.
 49. xyres.tmXBMajorLengthF       = 0.015     # Default is 0.02.
 50. xyres.tmXBMajorThicknessF    = 1.0       # Default is 2.
 51. xyres.tmXBMinorLengthF       = 0.0075    # Default is 0.01.
 52. xyres.tmXBMinorPerMajor      = 4         # # of minor tick marks per major.
 53. xyres.tmXBMode               = "Manual"  # Set tick mark mode.
 54. xyres.tmXBTickStartF         = -1.0
 55. xyres.tmXBTickEndF           = 5.0
 56. xyres.tmXBTickSpacingF       = 1.0
 57. xyres.tmXMajorGridThicknessF = 1.0       # Default is 2.0
 58. 
 59. xyres.tmYLLabelFont          = 21        # See explanations for X axes
 60. xyres.tmYLLabelFontHeightF   = 0.025     # resources.
 61. xyres.tmYLMajorLengthF       = 0.015
 62. xyres.tmYLMajorThicknessF    = 1.0
 63. xyres.tmYLMinorPerMajor      = 0
 64. xyres.tmYLMode               = "Manual"
 65. xyres.tmYLTickStartF         = -2.0
 66. xyres.tmYLTickEndF           = 3.0
 67. xyres.tmYLTickSpacingF       = 1.0
 68. xyres.tmYRBorderOn           = False    # Don't draw right axis.
 69. xyres.tmYROn                 = False    # Don't draw right axis tick marks.
 70. 
 71. xyres.trXMaxF   = xr  # Specify data limits for X and Y axes.
 72. xyres.trXMinF   = xl
 73. xyres.trYMaxF   =  3.0
 74. xyres.trYMinF   = -2.0
 75. 
 76. xyres.vpHeightF = 0.25 # Define height, width, and location of plot.
 77. xyres.vpWidthF  = 0.80
 78. xyres.vpXF      = 0.13
 79. xyres.vpYF      = 0.85
 80. 
 81. xy = Ngl.xy(wks,xo,yo,xyres) # Plot the interpolated values.
 82. 
 83. xyres.xyMarkLineMode = "Markers"  # Set line mode to "Markers".
 84. xyres.xyMarkerColor  = "blue"     # Set markers to blue.
 85. xyres.xyMarkerSizeF  = 0.025      # Make markers larger.
 86. 
 87. xy = Ngl.xy(wks,xi,yi,xyres) # Plot the original points with markers.
 88. 
 89. txres.txFont        = 21                  # Change the default font.
 90. txres.txFontHeightF = 0.03                # Set the font height.
 91. Ngl.text(wks,xy,"Function",1.5,2.5,txres) # Label the plot.
 92. 
 93. xx = [xl,xr]   # Create data for a polyline for marking
 94. yy = [0.0,0.0] # the Y = 0.0 line in each graph.
 95. 
 96. gsres.gsLineColor = "red"            # Set polyline color to red.
 97. Ngl.polyline(wks,xy,xx,yy,gsres)     # Draw polyline at Y=0.
 98. 
 99. #----------- Begin second plot, same frame--------------------------------
100. 
101. xyres.vpYF             = 0.37    # Set Y location of plot.
102. 
103. xyres.trYMinF          = -1.0    # Set minimum Y axis value.
104. xyres.trYMaxF          =  4.0    # Set maximum Y axis value.
105. 
106. xyres.tmYLTickStartF   = -1.0    # Define tick mark spacing
107. xyres.tmYLTickSpacingF =  1.0    # along Y axis.
108. xyres.tmYLTickEndF     =  4.0
109. 
110. xyres.xyMarkLineMode   = "Lines" # Set line mode to "Lines".
111. 
112. xy = Ngl.xy(wks,xo,yint,xyres)  # Plot the integrals.
113. 
114. txres.txFontHeightF = 0.03                              # Set font height.
115. Ngl.text(wks,xy,"Integral (from X = 0.)",0.8,3.5,txres) # Label plot.
116. 
117. Ngl.polyline(wks,xy,xx,yy,gsres) # Draw polyline at Y=0.
118. 
119. txres.txFontHeightF = 0.04  # Change the font height.
120. 
121. Ngl.text_ndc(wks,"Demo for ftcurvp, ftcurvpi",.5,.95,txres)
122. 
123. xperiod1 = [.41,   .2633, .2633, .2633, .2833, .2633, .2833, .2633, .2633]
124. xperiod2 = [.5166, .6633, .6633, .6633, .6433, .6633, .6433, .6633, .6633]
125. yperiod  = [.503,  .503,  .523,  .503,  .513,  .503,  .493,  .503,  .4830]
126. 
127. Ngl.polyline_ndc(wks,xperiod1,yperiod,gsres)  # Draw a period legend.
128. Ngl.polyline_ndc(wks,xperiod2,yperiod,gsres)  # between the two plots.
129. 
130. txres.txFontHeightF = 0.024                # Set font height.
131. Ngl.text_ndc(wks,"Period",0.465,0.5,txres) # Label the period legend.
132. 
133. Ngl.frame(wks)        # Advance the frame.
134. 
135. del xy        # Clean up.
136. del txres
137. del gsres
138. del xyres
139. 
140. Ngl.end()

Explanation of example 7

Lines 10-13:

  xi = [  0.000, 0.210, 0.360, 0.540, 1.000, 1.500, 1.970, 2.300, \
          2.500, 2.700  ]
  yi = [  0.000, 2.600, 3.000, 2.500, 0.000,-1.000, 0.000, 0.800, \
          0.920, 0.700  ]

Create two 1-dimensional arrays of 10 points each containing the input data. This example illustrates how you can use Python lists for 1-dimensional data input to PyNGL functions, instead of NumPy arrays. However, recall that NumPy arrays are required for higher dimensional arrays.

Lines 15-22:

  npts   = 201
  xl     =  -1.0
  xr     =   5.0
  inc    = (xr-xl)/(npts-1)
  xo     = numpy.arange(xl,xr+0.0001,inc) # Create output X coordinate array.
                                          # Add a small amount to xr to make
                                          # sure xr is the final value in the
                                          # range.

Create the output X coordinate array using the NumPy arange function (a small increment is added to the upper limit to insure that that floating point arithmetic roundoff does not eliminate the right end point). The arange function creates a range of evenly spaced floating point numbers given the floating point value to start at, the floating point value to end with, and the increment between the points.

Lines 23-24:

  period = 3.0
  yo = Ngl.ftcurvp(xi, yi, period, xo)  # Interpolate.

Calculate an interpolatory spline under tension through a sequence of functional values for a periodic function using the function Ngl.ftcurvp. The variable xi is a Python list (10 elements) containing the abscissae for the input function, yi. The variable period is a scalar value specifying the period of the input function, and xo is a Python list containing the abscissae for the interpolated values. Ngl.ftcurvp returns a 1-dimensional NumPy array that contains the interpolated functional values at the points specified in xo.

Note that the output X coordinate array you are specifying goes from -1.0 to 5.0, while the input X array you specified earlier only goes from 0.0 to 2.7. Since Ngl.ftcurvp takes as input the period of the function, it uses this period to repeat values that fall outside the input X range specified.

Lines 26-28:

  yint = numpy.zeros(npts,'f')
  for i in xrange(npts):
    yint[i] = Ngl.ftcurvpi(0., xo[i], period, xi, yi)

Calculate an integral of an interpolatory spline between two specified points using the function Ngl.ftcurvpi. The first argument to Ngl.ftcurvpi is a scalar value containing the lower limit of the integration, the second argument is a scalar value containing the upper limit of the integration, and the third argument is a scalar value specifying the period of the input function. The last two arguments are lists (both 10 elements each) containing the abscissae for the input function and the input function itself.

Lines 30-32:

  cmap = ["white","black","red","green","blue","yellow"]
  rlist = Ngl.Resources()
  rlist.wkColorMap = cmap

Define a color map using named colors. There are 650 valid color names.

Note: you can mix and match color names with RGB values, as long as you enclose each entry in double quotes. In this case all elements of the color map specification must be strings. The syntax for specifying an RGB triple in this context is a bit strange (due to compatibility issues with the supporting software). The form of an RGB triple in this case is:

   "(/rval,gval,bval/)"
     
For example, if you want a white background, a black foreground, and some other colors defined by RGB values, then you can define your color map as follows:
   cmap = ["white","black","(/.56,.50,.70/)","(/.30,.30,.70/)",   \
           "(/.10,.10,.70/)","(/.00,.10,.70/)","(/.00,.30,.70/)",\
           "(/.00,.50,.50/)","(/.00,.70,.10/)","(/.06,.68,.00/)"]
     
For more information on named colors, see "Creating your own color map using named colors and RGB values".

Lines 36-38:

  txres = Ngl.Resources()   # Set up variable for TextItem resources.
  xyres = Ngl.Resources()   # Set up variable for XyPlot resources.
  gsres = Ngl.Resources()   # Set up variable for GraphicStyle resources.

Create some resource lists to contain attributes for text, XY plots, and general output primitives.

Line 40:

  xyres.nglFrame               = False     # Don't advance the frame.

Since you are drawing two XY plots on one page, and then drawing markers and text on top, you don't want the frame to be advanced automatically after each XY plot is drawn.

Line 41:

  xyres.nglMaximize            = False     # Don't advance the frame.

Turn off the feature that maximizes plot size, otherwise the each of the two plots will be drawn at maximum size and centered on the frame.

Lines 43-45:

  xyres.tmXTBorderOn           = False     # Don't draw top axis.
  xyres.tmXTOn                 = False     # Don't draw top axis tick marks.
  xyres.tmBorderThicknessF     = 1.0       # Default thickness is 2.0

These resources control the tick marks on the X axes and the border thickness. By default, the border and tick marks are put on both the bottom and the top of the plot, so setting both tmXTBorderOn and tmXTOn to False turns off the drawing of the top border and tick marks ("XT" stands for "X Top").

Lines 47-48:

  xyres.tmXBLabelFont          = 21        # Change font and size of
  xyres.tmXBLabelFontHeightF   = 0.025     # X axis labels.

Changes the font and size of the X axis labels.

Lines 49-52:

  xyres.tmXBMajorLengthF       = 0.015     # Default is 0.02.
  xyres.tmXBMajorThicknessF    = 1.0       # Default is 2.
  xyres.tmXBMinorLengthF       = 0.0075    # Default is 0.01.
  xyres.tmXBMinorPerMajor      = 4         # # of minor tick marks per major.

Some resources for controlling the major and minor tick mark appearance on the X axis.

Lines 53-57:

  xyres.tmXBMode               = "Manual"  # Set tick mark mode.
  xyres.tmXBTickStartF         = -1.0
  xyres.tmXBTickEndF           = 5.0
  xyres.tmXBTickSpacingF       = 1.0
  xyres.tmXMajorGridThicknessF = 1.0       # Default is 2.0

Setting tmXBMode to "Manual" allows you to define where to place major tick marks. Starting with the value tmXBTickStartF, major tick marks are placed at intervals separated by a distance of tmXBTickSpacingF until tmXBTickEndF is exceeded.

Lines 59-67:

  xyres.tmYLLabelFont          = 21        # See explanations for X axes
  xyres.tmYLLabelFontHeightF   = 0.025     # resources.
  xyres.tmYLMajorLengthF       = 0.015
  xyres.tmYLMajorThicknessF    = 1.0
  xyres.tmYLMinorPerMajor      = 0
  xyres.tmYLMode               = "Manual"
  xyres.tmYLTickStartF         = -2.0
  xyres.tmYLTickEndF           = 3.0
  xyres.tmYLTickSpacingF       = 1.0

These resources are the same as those for the X axis described above, only they apply to the left Y axis. The drawing of the right Y axis is turned off by setting both tmYRBorderOn and tmYROn to False ("YR" stands for "Y Right").

Lines 71-74:

  xyres.trXMaxF   = xr  # Specify data limits for X and Y axes.
  xyres.trXMinF   = xl
  xyres.trYMaxF   =  3.0
  xyres.trYMinF   = -2.0

There are many different kinds of resources that you can set for putting the data through some kind of transformation. One set of these, the MapTransformation resources, was introduced in example 5. There are other types of non-map transformation resources that you can set for reversing the data in the X or Y axis direction and setting the upper or lower bounds of the axis values (Transformation resources), and using log scaling (LogLinTransformation resources). There's also a set of IrregularTransformation resources for managing forward and reverse transformations in an irregular rectangular coordinate space.

To control the X and Y axis limits of the data values, you need to use the Transformation resources trXMinF, trXMaxF, trYMinF, and trYMaxF, which are documented in the Transformation resource descriptions.

The first curve you are about to plot goes from -1.0 to 5.0 in the X direction, and from -1.01 to 3.02 in the Y direction. The second curve goes from 0.0 to 2.7 in the X direction and -1.0 to 30 in the Y direction. By setting trXMinF to xl (-1.0), trXMaxF to xr (5.0), trYMinF to -2.0 and trYMaxF to 3.0, only the data from the curves that go from -1.0 to 5.0 in the X direction and -2.0 to 3.0 in the Y direction are plotted. Note that for the second curve, these limits are actually outside the range of the actual data values.

Lines 76-79:

  xyres.vpHeightF = 0.25 # Define height, width, and location of plot.
  xyres.vpWidthF  = 0.80
  xyres.vpXF      = 0.13
  xyres.vpYF      = 0.85

Set some resources to change the size and location of the first plot drawn in the viewport. The viewport is discussed in more detail in example 5.

Line 81:

  xy = Ngl.xy(wks,xo,yo,xyres) # Plot the interpolated values.

Draw an XY plot of the interpolated values.

Lines 83-87:

  xyres.xyMarkLineMode = "Markers"  # Set line mode to "Markers".
  xyres.xyMarkerColor  = "blue"     # Set markers to blue.
  xyres.xyMarkerSizeF  = 0.025      # Make markers larger.
  
  xy = Ngl.xy(wks,xi,yi,xyres) # Plot the original points with markers.

Draw an XY plot of the original points using markers, right on top of the first XY plot you just drew. Since the only thing you changed from the first plot to the second plot was a few resources for setting the line mode to "Markers" and the data in the Ngl.xy arguments, this second plot is drawn in the exact same place as the first plot, and has the same tick marks and X/Y axis values. (Remember, the frame advance resource nglFrame was previously set to False.)

Lines 89-91:

  txres.txFont        = 21                  # Change the default font.
  txres.txFontHeightF = 0.03                # Set the font height.
  Ngl.text(wks,xy,"Function",1.5,2.5,txres) # Label the plot.

Put a label on the two plots you just created using Ngl.text. The procedure Ngl.text is similar to Ngl.text_ndc(, only the position of text is specified according to the data space of the plot (rather than NDC coordinates), which is passed as the second argument to Ngl.text. In this case, you are passing in xy, which is the value returned from the last call to Ngl.xy.

Lines 93-97:

  xx = [xl,xr]   # Create data for a polyline for marking
  yy = [0.0,0.0] # the Y = 0.0 line in each graph.
  
  gsres.gsLineColor = "red"            # Set polyline color to red.
  Ngl.polyline(wks,xy,xx,yy,gsres)     # Draw polyline at Y=0.

Using Ngl.polyline, draw a polyline for marking the Y = 0.0 line. The first argument of Ngl.polyline is the workstation object returned from a previous call to Ngl.open_wks, and the second argument is the plot id of the plot to draw the polyline on (returned from a previous call to one of the Ngl.* plotting functions). To draw the polyline on the XY plots you just drew, pass xy as the plot id. The next two arguments are the X and Y locations of each point defining the polyline to plot (they must be in the same data space as the data in xy), and the last argument is a resource list. You are using resources here to change the default color of the polyline.

The procedure Ngl.polyline is part of a set of procedures for drawing output primitives. The other primitive procedures draw markers (Ngl.polymarker, Ngl.polymarker_ndc), filled areas (Ngl.polygon, Ngl.polygon_ndc), and text (Ngl.text, Ngl.text_ndc). Output primitive resources (with the exception of text resources) belong to the "GraphicStyle" group and start with the letters "gs". Each resource is documented with its type and its default value in the GraphicStyle resource descriptions section. The text resources belong to the "TextItem" group as described in example 5.

Note: Using Ngl.polyline to draw a line at Y = 0.0 is not really necessary in this case. You could have made this line a part of the XY plot by creating a second curve and passing it to Ngl.xy along with the first curve drawn above. Ngl.polyline is being used here just to show how to use it.

Line 99:

  #----------- Begin second plot, same frame--------------------------------

Draw another XY plot on the same frame, below the first XY plot you just drew. For a given X coordinate, the plotted Y value is the integral from 0 to X of the function in the first XY plot.

Line 101:

  xyres.vpYF             = 0.37    # Set Y location of plot.

To draw the second XY plot below the first XY plot, change the value of vpYF to change the Y position of the second plot.

Lines 103-104:

  xyres.trYMinF          = -1.0    # Set minimum Y axis value.
  xyres.trYMaxF          =  4.0    # Set maximum Y axis value.

Change the minimum and maximum values of the lower and upper bounds of the Y axis.

Lines 106-108:

  xyres.tmYLTickStartF   = -1.0    # Define tick mark spacing
  xyres.tmYLTickSpacingF =  1.0    # along Y axis.
  xyres.tmYLTickEndF     =  4.0

Create some "nice" values for the tick marks. If you don't set these resources, then you get tick marks at values that PyNGL selects, which in this case end up being at -1, 0, 1, 2, and 3 (no tick mark at 4).

Lines 110-112:

  xyres.xyMarkLineMode   = "Lines" # Set line mode to "Lines".
  
  xy = Ngl.xy(wks,xo,yint,xyres)  # Plot the integrals.

Change the line drawing mode back to "Lines" and draw a new XY plot of the integral values.

Lines 114-115:

  txres.txFontHeightF = 0.03                              # Set font height.
  Ngl.text(wks,xy,"Integral (from X = 0.)",0.8,3.5,txres) # Label plot.

Label the XY plot you just drew using Ngl.text in the data space of the new XY plot just created.

Line 117:

  Ngl.polyline(wks,xy,xx,yy,gsres) # Draw polyline at Y=0.

Draw a polyline for marking the Y = 0.0 line.

Lines 119-121:

  txres.txFontHeightF = 0.04  # Change the font height.
  
  Ngl.text_ndc(wks,"Demo for ftcurvp, ftcurvpi",.5,.95,txres)

Put a label at the top of the viewport using the Ngl.text_ndc procedure which allows you to draw text anywhere in the viewport. The first argument of Ngl.text_ndc is the workstation variable 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. You are using resources here to change the font height from the default.

Lines 123-131:

  xperiod1 = [.41,   .2633, .2633, .2633, .2833, .2633, .2833, .2633, .2633]
  xperiod2 = [.5166, .6633, .6633, .6633, .6433, .6633, .6433, .6633, .6633]
  yperiod  = [.503,  .503,  .523,  .503,  .513,  .503,  .493,  .503,  .4830]
  
  Ngl.polyline_ndc(wks,xperiod1,yperiod,gsres)  # Draw a period legend.
  Ngl.polyline_ndc(wks,xperiod2,yperiod,gsres)  # between the two plots.
  
  txres.txFontHeightF = 0.024                # Set font height.
  Ngl.text_ndc(wks,"Period",0.465,0.5,txres) # Label the period legend.

Draw and label a period legend (two arrows with the word "period" between them) below the first plot indicating the period of the input function. Since the legend falls outside either of the XY plots, you need to use Ngl.polyline_ndc to draw it in NDC space.

The procedure Ngl.polyline_ndc is similar to Ngl.polyline, only the X and Y positions of each point in the line are specified in NDC coordinates instead of in a plot's data space coordinates.

Line 133:

  Ngl.frame(wks)        # Advance the frame.

Now that you've drawn all the components of the frame, call frame to advance the frame of the workstation.