Graph Tutorial 1. Introduction 2. The Components of a Graph Attributes: xs ys 2a. Traces and Trace Sets Attributes: linecolor (*) linestyle (*) linewidth (*) 2b. Title Attributes: title titlefg titlefont titlejustify 2c. Subtitle Attributes: subtitle subtitlefg subtitlefont subtitlejustify 2d. Footnote Attributes: footnote footnotefg footnotefont footnotejustify 2e. Legend Attributes: legend legend (*) legendbg legendfg legendfont legendstyle xlegend ylegend legendhlthickness legendshadowthickness 2f. x-Axis and y-Axis Titles Attributes: x/X/y/Ytitle (**) x/X/y/Ytitlefg (**) x/X/y/Ytitlefont (**) x/X/y/Ytitlejustify (**) y/Ytitlestyle (**) 2g. Axes Attributes: axis x/X/y/Yfg (**) grid gridfg gridstyle gridwidth rule rulewidth y/Ymode (**) 2g1. Axis Ticks Attributes: x/X/y/Yinc (**) x/X/y/Ymajorticksize (**) x/X/y/Yminorticks (**) x/X/y/Yminorticksize (**) x/X/y/Ytickstyle (**) 2g2. Axis Labels Attributes: x/X/y/Ylabelfont (**) x/X/y/Ylabeljustify (**) x/X/y/Ylabelout (**) x/Xsublabel (**) x/Xsublabeljustify (**) 2g3. Controlling Tick Mark Location and Label Formatting Attributes: x/X/y/Ylabel (**) x/y/X/Yextent (**) x/y/X/Ylabelheight (**) x/X/y/Ylabelwidth (**) x/Xsublabelout (**) 2h. Alternate Axes Attributes: axis x/yaxis (*,**) 2i. Zero Axes Attributes: zero zerofg zerostyle zerowidth 3. Trace Styles Attributes: barwidth fillcolor (*) font gradient (*) style (*) symbol (*) symbolsize (*) 3a. Text Traces Attributes: title (*) titlefg (*) titlefont (*) 4. Graph Attributes Attributes: bg bottom fg left refer right top y/Ybottom (**) y/Ytop (**) x/Xleft (**) x/Xright (**) x/Xmin (**) x/Xmax (**) y/Ymin (**) y/Ymax (**) 5. User Interactions 5a. Zooming 5b. Vertical Cursor and Cross Hairs Attributes: legendstyle 5c. Referencing a Graph, Line Trace, or Trace Point Attributes: coordinate/Coordinate refer referpoint selectable selected 5d. Selecting the Legend or a Text Trace 5e. Repositioning the Legend and Traces 5f. Copying and Deleting Traces Attributes: delete 5g. Editing and Creating Text Traces Attributes: addtexttrace copytextrace delete (as callback function) mode textactivate 5h. Modifying and Creating Numeric Traces Attributes: addtrace copytrace movelimit (*) selected (*) selectdistance 6. Monitoring Performance Variable: s.QUIET (*) Trace set attributes, or trace attributes for short. All the others are graph attributes. (**) An attribute with x/X/y/Y prefixed to its name is one that is separately defined for all four axes. The four axes are: the normal x-axis at the bottom of the graph, referred to as "x"; the normal y-axis at the left of the graph, referred to as "y"; the alternate x-axis at the top of the graph, referred to as "X"; and the alternate y-axis at the right of the graph, referred to as "Y". For example, x/X/y/Ytitle means there are four attributes: xtitle, Xtitle, ytitle, and Ytitle, one for each of the axes; x/yaxis means there are two attributes, xaxis and yaxis. 1. Introduction ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ The purpose of this tutorial is to familiarize the reader with the graph display class in the A+ screen management system. In general, only those aspects of screen management specific to graphs are discussed here. See the general screen management tutorial to learn how the more widely applicable functions apply to graphs. The tutorial is made up of descriptions and A+ examples. You should set up your Emacs environment to have two visible buffers, one holding the tutorial and the other an A+ session. If you are currently reading this in Emacs, simply press F4. To bring individual expressions from the tutorial into the A+ session, place the cursor on the expression and press F2. It is assumed that the expressions and functions are brought into the A+ session when you first encounter them. If you need more help on running Emacs and A+ see the "Getting Started" tutorial. Once you have an active A+ session, load the screen management system by entering $load s That is, place the cursor on the above expression and press F2. At various points in the exercises, you will refresh the A+ session by exiting with $off, pressing F4 to start A+ again, and then loading the screen management system. Session refreshings will be indicated as follows: $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s You may make mistakes when running the tutorial and it may become difficult to get back to a place where you can continue. At that point you should simply go back to the latest session refresh sequence and start over from there. Two more things before we start. First of all, by default graphs appear in the upper left corner of the screen. To avoid having the graphs overlay the tutorial, move the Emacs screen to the lower right, or put the tutorial in the bottom Emacs buffer and the A+ session in the top (you can do this by pressing F5 and then F6; you may have to do it more than once.) Secondly, even though the default sizes of the examples may be quite small, don't resize them unless told to do so, because the resizing may change the details of the graphs. In the examples we usually display the graphs first and then set their attributes so that you can see the effects. In practice, however, you set the attributes before displaying the graph. 2. The Components of a Graph ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ A graph is a layout composed of one or more trace sets. The simplest trace set is a vector v, whose elements are plotted as the y-coordinates with x-coordinates É#v. That is, the points (i,v[i]) are plotted for all i from 0 to (#v)-1. vû 53 14 27 2 31 85 30 11 67 50 gû`v show `g is `graph At this point you should see a window with "A+" in the grey title bar, and a gray graph area below it. The graph area has a title area with "g" in it, an x-axis and a y-axis, a legend, and a trace. This is the default appearance of the graph. Each of these components can be modified by setting the appropriate attributes, and there are other components that do not appear in the default. And, of course, there can be more than one trace on a graph. We will look at all of these components in this section. There are two attributes that allow us to control the size of the graph. We will use these attributes for resizing to ensure that the assumptions about the appearance of the graphs are correct. `g has (`xs`ys;(300;200)) ã This may have no effect, i.e., ã this may be the default size. 2a. Traces and Trace Sets The present graph g has only one trace set, i.e., one component variable v. However, like any container, it can have more than one. For example, wû(É#v)*2 gûg,`w You should now see two traces on the graph, and an updated legend. The more general form of a trace set is a matrix rather then a vector, because then the x-coordinates as well as the y-coordinates can be specified. The individual coordinates are arranged as rows of the matrix, with the x-coordinates along the first column and y-coordinates along the second. For example, xû4 2Ò8 10 4 24 1 5 6 60 x 8 10 4 24 1 5 6 60 gûg,`x You should now see three traces on the graph, and an updated legend. Note that the new trace is indicated in the legend by "x:0", instead of simply "x". The reason for this is that matrix trace sets can provide more than one trace on the graph. For example, if we catenate a new column onto x as follows: xûx(,@1 0) 40 20 50 80 you will see a fourth trace and a new row in the legend, indicated by "x:1". The 3-column matrix x provides two traces to the graph, both with the same x-coordinates. One trace is defined by columns 0 and 1 of x (the one indicated by "x:0" in the legend), and the other is defined by columns 0 and 2 (and indicated by "x:1" in the legend). All traces in a trace set share the same x-coordinates, which are in column 0 of the matrix. Note that in the default case, the traces in a trace set share the same color, but are distinguished by their line styles. Both line color and line style are trace set attributes that can be set. For example: `w has (`linecolor;`yellow) `w has (`linestyle;`dot) A full list of colors can be found in the A+ reference manual. The line styles are `solid, `dash (e.g., the trace indicated by "x:1" in the legend), `dot and `dotdash. For example: `w has (`linestyle;`dotdash) (Toggle back and forth between the last two expressions to see the difference in the two line styles.) Also, `dot1 through `dot5 give various intervals between dots, with `dot1 the smallest, `dot5 the largest, and `dot3 the same as `dot. `w has (`linestyle;`dot1) `w has (`linestyle;`dot2) `w has (`linestyle;`dot3) `w has (`linestyle;`dot4) `w has (`linestyle;`dot5) Analogously, there are `dash1 through `dash5 (different length dashes) and `dotdash1 through `dotdash5. The line colors and line styles can be set individually for all traces in a trace set by specifying these attributes to have vectors of values. `x has (`linecolor;`white `dodgerblue) `x has (`linestyle;`dot `solid) The last attribute affecting the appearance of line graphs allows the line width to specified, which is useful for emphasis: `v has (`linewidth;2) Note that the width of the corresponding line segment in the legend also changed. The units of line width are pixels. The last thing to be illustrated in this section is that a trace set with multiple visible traces behaves differently in a graph with a single trace set and in a graph with multiple visible trace sets. We will use a separate graph and locate it 350 pixels to the right, for simultaneous viewing. First, return the original graph to its default values: `x has (`linecolor;; `linestyle;); `v has (`linewidth;); xxû4 2Ò8 10 4 24 1 5 6 60 ggû`xx show `gg is `graph; `gg has (`x;350); xxûxx(,@1 0) 40 20 50 80 The two traces contributed by x to the graph g, which is a graph with multiple trace sets, have the same color, but different line styles; color is used to differentiate among trace sets. On the other hand, the two traces contributed by xx to the graph gg, which has only one trace set, have different colors, but the same line style. free `gg Most of the attributes set so far have been on the trace sets, but three (the size parameters `xs and `ys and the horizontal position parameter `x) have been on the graph itself. This distinction is sometimes made explicit by our referring to attributes as "trace attributes" or "graph attributes." There are other visual forms a trace can take besides these various line styles; see "3. Trace Styles." 2b. Title The "g" that appears at the top of the gray plot area in our current example is the title of the graph. A more meaningful title can be specified using the `title attribute: `g has (`title;"Graph Tutorial Example") Both color and the font can also be set, and the title can be justified. There may be a delay in changing the font. Wait for the change before proceeding. (A list of recommended fonts can be found in the A+ Reference Manual.) `g has (`titlefg;`yellow) `g has (`titlefont;"helvetica-bold-20") `g has (`titlejustify;`left) ã or `right `g has (`titlejustify;`center) The title can have more than one line: `g has (`title;("Graph Tutorial Example";"Components of a Graph")) Note that the plot area composed of the axes and traces was automatically resized to accommodate the two rows of the title. The title can be removed by setting it to the empty vector: `g has (`title;"") 2c. Subtitle One graph component that does not appear in the default form of a graph is the subtitle. The subtitle appears between the title and the plot area. Since it has color and font settings separate from those for the title, it can be used for more effective title presentations. For example, put the first row of the title back: `g has (`title;"Graph Tutorial Example") and put the second row back as the subtitle: `g has (`subtitle;"Components of a Graph") `g has (`subtitlefg;`blue) `g has (`subtitlefont;"Times-Roman-15") `g has (`subtitlejustify;`left) ã or `right `g has (`subtitlejustify;`center) Subtitles, like titles, can have more than one row, and are removed by setting their value to "". 2d. Footnote The footnote is another component that does not appear in the default form of a graph. `g has (`footnote;"Morgan Stanley Co.") `g has (`footnotefg;`yellow) `g has (`footnotefont;"Times-BoldItalic-15") `g has (`footnotejustify;`center) ã or `right `g has (`footnotejustify;`left) Footnotes are removed by setting their value to "". 2e. Legend The text in the legend can be set for each trace set: `v has (`legend;"solid red") `w has (`legend;"broken yellow") `x has (`legend;("solid blue";"broken blue")) Note that if the text for a legend entry is the empty character vector, that entry is removed. `v has (`legend;"") `v has (`legend;"solid red") At this point you may want to resize the graph window, since otherwise the legend will now take up a large portion of the plot area. `g has (`xs`ys;(600;500)) The legend box can also be repositioned within the plot area. `g has (`legend;`br) ã Bottom right `g has (`legend;`tc) ã top center `g has (`legend;`tl) ã top left (where we started) Other settings are `tr, `bl, and `bc. (Note that we just set the `legend attribute for the graph g, while just above are settings of the `legend attribute for trace sets.) In addition, you can specify the position of the upper left corner of the legend box, as percentages of the horizontal and vertical lengths of the graph window. They take effect when `legend has the value `xy: `g has (`xlegend `ylegend;(25;75)) ã the (x,y) percentages `g has (`legend;`xy) Now that the `legend attribute has been set to `xy, settings of `xlegend and `ylegend take effect immediately: `g has (`xlegend;50) Note that the legend cannot be partially hidden by the choice of `xlegend and `ylegend. For example, if these coordinates are set to (95,95) one might expect that only the upper left corner of the legend would be visible. However, this is not the case: `g has (`xlegend `ylegend;(95;95)) ã the (x,y) percentages The specified position is respected as far as possible, consistent with keeping the legend completely visible. The values of `xlegend and `ylegend are integers between 0 and 100 or, alternatively, fractions between 0 and 1. The legend can also be strung out horizontally: `g has (`legend;`tl) `g has (`legendstyle;`hor) The original configuration is: `g has (`legendstyle;`ver) Other attributes control the colors and font of the legend. Specifically, the background color of the legend: `g has (`legendbg;`white) the foreground color, or color of the text in the legend: `g has (`legendfg;`blue) the font of the text in the legend: `g has (`legendfont;"Times-Roman-15") and, finally, even the pixel width of the legend's highlight and shadow thicknesses (the defaults are 1): `g has (`legendshadowthickness;3) `g has (`legendhlthickness;2) The legend can be made to blend into the graph: `g has (`legendbg;0Ø`bg of `g) `g has (`legendshadowthickness;0) `g has (`legendhlthickness;0) The legend can be removed by setting the legend position to `none: `g has (`legend;`none) 2f. x-Axis and y-Axis Titles Titles for axes are two other components that do not appear in the default form of a graph. `g has (`xtitle;"0 to 9") `g has (`ytitle;"0 to 81") Let's make them big enough to be easily seen: `g has (`xtitlefont;"Times-Roman-25") `g has (`ytitlefont;"Times-Roman-25") Note that the x-axis title is positioned below the x-axis and the y-axis title is above the y-axis. The y-axis title can be repositioned vertically along the y-axis as follows: `g has (`ytitlestyle;`ver) The axis titles can be justified: `g has (`xtitlejustify;`left) `g has (`xtitlejustify;`right) `g has (`xtitlejustify;`center) `g has (`ytitlejustify;`top) `g has (`ytitlejustify;`bottom) `g has (`ytitlejustify;`center) Return to the original position with: `g has (`ytitlestyle;`hor) The y-axis title can now be justified right and left: `g has (`ytitlejustify;`left) `g has (`ytitlejustify;`right) `g has (`ytitlejustify;`center) Notice that there seems to be no difference in right and center justification of the y-axis title. We can set the left margin so you can see the difference: `g has (`left;20) `g has (`ytitlejustify;`left) `g has (`ytitlejustify;`right) `g has (`ytitlejustify;`center) `g has (`left;0) We'll have more to say about margins later. The colors of the axis titles can be set separately: `g has (`xtitlefg;`red) `g has (`ytitlefg;`yellow) 2g. Axes Most of the settable attributes in good graphics packages deal with axes, and this one is no different. There are four parts to an axis: the rule which extends the length of the axis; the tick marks; the labels on the tick marks; and the grid lines of the graph associated with the tick marks. Each of these parts can be controlled with the appropriate attributes. In addition, there are a few attributes that affect the overall appearance of the axes. First of all, we can control the color of the axes: `g has (`xfg;`yellow) `g has (`yfg;`red) We can also control the thickness of the axis rules: `g has (`rulewidth;2) As you can see, the thickness of both axes rules and tick marks are affected. The units of the axis thickness are pixels. A rule width of 0 has special meaning. Although it looks no different from 1 on the screen, it has the effect of drawing the rules more efficiently, and more importantly, perhaps, there is a noticeable difference when a graph is printed. `g has (`rulewidth;0) More interesting, perhaps, is the control one has over the style of the axes. We will go through all the possibilities. For example, we can have an x-axis only or a y-axis only. `g has (`axis;`x) `g has (`axis;`y) `g has (`axis;`xy) Vertical grid lines can be placed at the major x-axis tick marks. `g has (`grid;`x) Likewise, horizontal grid lines can be placed at the major y-axis tick marks. `g has (`grid;`y) Both horizontal and vertical grid lines are also possible: `g has (`grid;`xy) Both the widths (in pixels) and colors of the gridlines can be set: `g has (`gridwidth;2) `g has (`gridfg;`green) A grid width of 0 has the same effects as a rule width of 0: `g has (`gridwidth;0) There is a `rule attribute whose default value is `axis, meaning that any axes that appear have rules. This attribute can also be set to values like those for `grid, indicating which axes have rules. For example, we can have a graph with an ordinary y-axis and just the x-axis rule: `g has (`axis;`y) `g has (`rule;`xy) An interesting effect is obtained by removing the rule from the y-axis: `g has (`rule;`x) The graph can have ascending values or descending values: `g has (`ymode;`descend) `g has (`ymode;`ascend) 2g1. Axis Tick Marks We will use an uncluttered graph to illustrate the details of tick-mark and label attributes. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s vû 53 14 27 2 31 85 30 11 67 50 gû`v show `g is `graph `g has (`xs`ys;(300;200)) ã This may have no effect, i.e., ã this may be the default size. The lengths of both the major and minor tick marks can be set. The unit of length is pixels. Let's first look at the default values to get a sense of their scale. `xmajorticksize of `g < 10 ã A+ output `xminorticksize of `g < 6 ã A+ output The tick marks can be made smaller, leaving a larger plot area. For example: `g has (`xminorticksize;2) `g has (`xmajorticksize;5) The number of minor tick marks that appear between major tick marks can be specified, for the x-axis and y-axis separately. In the present example, 4 minor tick marks between major tick marks on the y-axis would put a mark at every increment of 5: `g has (`yminorticks;4) It often improves the appearance of a graph to remove the minor tick marks, which can be done by setting their number to 0. For example: `g has (`xminorticks;0) The number of major tick marks can also be specified, if somewhat indirectly, by specifying the increment between major tick marks. For example: `g has (`yinc;40) `g has (`xinc;2) And, finally, we can control the style of the tick marks: pointing away from the plot area, into the plot area, or straddling the axis: `g has (`ytickstyle;`in) ã The tick marks point inwards `g has (`xtickstyle;`inout) ã The tick marks straddle the axis `g has (`xtickstyle;`out) ã The tick marks point outwards The latter is the default. Graphs with tick style `in are effective because the plot area is larger, and the inward pointing ticks rarely decrease the usable plot area. 2g2. Axis Labels We have control over two aspects of the axis labels: the font in which they are set and their format. At this point it is useful to switch to an example with realistic data. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s xû0à "/usr/local/aplus-fsf-4.22/doc/tutorials/graphs/graph_data.m"; This data is high, low, open, close information taken at, roughly, 5-minute intervals over a 5-day period in Tokyo. The market day is partitioned into 5-minute increments and x contains one row for each period. A timestamp, which is in column 0, is the time of the last reading for the 5-minute period in which it falls. The timestamps are Unix timestamps. The data in columns 1 through 4 of a given row are associated with the 5-minute time period in which the timestamp in column 0 lies. They represent, starting with column 1, the high value of all readings taken during the 5-minute period, the low value, the open, and the close. At this point we need only one of the traces: yûx[;0 1] gû`y show `g is `graph `g has (`xs`ys;(300;200)) ã This may have no effect, i.e., ã this may be the default size. You will notice that the data on the graph appears clustered in several areas, and these clusters are connected by relatively long line segments. The clusters represent periods of market activity, while the long line segments represent periods during which the market is closed. In applications, these long segments would be factored out to give the graph a uniform appearance, but that is not a concern here. Let's look at the timestamp format on the x-axis labels first. Since this is daily data, we start with the seven-day format, which uses abbreviated names for the days: `g has (`xlabelout;`day7_u) Note that the major tick marks indicate the beginning of every other day, and the minor tick marks therefore mark the remaining days. Let's look at days of the month or days of the year, which are integers indicating the number of days since the beginning of the month or year: `g has (`xlabelout;`day31_u) The minor tick marks now represent half days. `g has (`xlabelout;`day365_u) Once again, the minor tick marks represent days. The time span between major tick marks, and therefore the meaning of the minor tick marks, depends to a large extent on the sizes of the labels, because these sizes determine the number of labels the graph can accommodate. We have some indirect control over the number of labels that appear and their format, because we can specify the font for the labels. (More direct control is described below in "2g3. Controlling Tick Mark Location and Label Formatting".) For example: `g has (`xlabelout;`day7_u) Check the default label font, and then set it to a smaller pixel size. `xlabelfont of `g `g has (`xlabelfont;"Helvetica-Bold-7") You should now see a major tick for each weekday. Of course the labels are very hard to read. Another possibility is to simply choose the size of the graph appropriately. First reset the axis font: `g has (`xlabelfont;"Helvetica-Bold-12") and then resize the graph: `g has (`xs`ys;(800;300)) There are two month-only formats, one that uses names and the other the numbers 1 through 12, and there are two year-only formats using 2 digits and 4 digits. These formats are not particularly interesting for data which is all from the same month, but for completeness here they are: `g has (`xlabelout;`m_u) `g has (`xlabelout;`m12_u) `g has (`xlabelout;`y2_u) `g has (`xlabelout;`y4_u) The next format gives a text form of day, month and year, while the four that follow give various abbreviated forms: `g has (`xlabelout;`mdy_u) `g has (`xlabelout;`mdy2_u) `g has (`xlabelout;`mdy4_u) `g has (`xlabelout;`dmy2_u) `g has (`xlabelout;`dmy4_u) The remaining time formats are hours, minutes, and seconds, so to get major tick marks with these units, restrict the data to a single day, as follows: yû50Ùy The market hours are 9:30 to 11:00 and 1:30 to 3:30. Test the following formats: `g has (`xlabelout;`hrmin) `g has (`xlabelout;`hrmin24) `g has (`xlabelout;`hr) `g has (`xlabelout;`hr24) To get major tick mark labels in minutes, further restrict the data as follows: yû12Ùy This data is not fine enough to exhibit variations in seconds, but here are the remaining time formats: `g has (`xlabelout;`min) `g has (`xlabelout;`sec) `g has (`xlabelout;`minsec) `g has (`xlabelout;`hrminsec) `g has (`xlabelout;`hrminsec24) Finally, you can remove the labels altogether: `g has (`xlabelout;`) In addition to the primary x-axis labels, there are sublabels that provide a second level of text. Sublabels are useful when all the label text does not fit conveniently on one line, and we will see examples of this in the next section. For now, go back to the original graph of this section: yûx[;0 1] `g has (`xs`ys;(300;200)) `g has (`xlabelout;`day31_u) `g has (`xsublabelout;`m_u) ã The sublabels automatically appear. One last point on x-axis formatting. The labels and sublabels can be justified relative to the tick marks: `g has (`xlabeljustify;`right) `g has (`xlabeljustify;`left) `g has (`xlabeljustify;`center) `g has (`xsublabeljustify;`right) `g has (`xsublabeljustify;`left) `g has (`xsublabeljustify;`center) The sublabels are removed in the same way as labels: `g has (`xsublabelout;`) Turning now to the y-axis, which in this example represents bond prices, there are the following formats: `g has (`ylabelout;`32nd) `g has (`ylabelout;`64th) `g has (`ylabelout;`128th) `g has (`ylabelout;`320th) `g has (`ylabelout;`328th) y-axis labels can also be justified: `g has (`ylabeljustify;`top) `g has (`ylabeljustify;`bottom) `g has (`ylabeljustify;`center) Finally, we have three generally applicable label formats. For convenience we will use the present example for illustration, even though these formats are not appropriate for the data. The first of the three displays the decimal part of the number as a fraction: `g has (`ylabelout;`frac) The last two provide conventional floating point and fixed point formats: `g has (`ylabelout;`float) `g has (`ylabelout;`fixed) The number of decimal digits that appear can be specified for the fixed format: `g has (`ylabelout;(`fixed;2)) The default label format is `float. 2g3. Controlling Tick Mark Location and Label Formatting In addition to the variety of label formats illustrated above, you can also specify your own format, much as you specify the format of any data that appears on the screen. Furthermore, you have complete control over the tick mark locations and the text of the labels for those tick marks. Let's start with a clean slate. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s The screen management system provides ways for programmers to control the formatting of tabular data on the screen. Each array on the screen can be controlled separately. The control mechanisms for data on the screen are: Ê a formatting parameter for the dyadic primitive format function î can be specified for an array, and will be applied to every displayed element; Ê a formatting parameter for the system function _fmt can be specified, and will be applied to every displayed element; Ê a function can be specified that will be called for every displayed element. The same rules apply to labels on tick marks, only now the data elements being formatted are tick values. For example: yû98+0.01«+?20Ò100 gû`y show `g is `graph `g has (`ylabelout;6.3) ã A valid format parameter of î A second example: `g has (`ylabelout;"f10.4") ã A valid format parameter of _fmt `ylabelout can also be specified as a function. See the discussion of the of the `out attribute in the A+ Reference Manual. Complete control over ticks and tick labels is provided by the `ylabel attribute. We'll begin by adjusting the window of the current graph slightly, just to make sure the bottom and top ticks that are created below will appear. `g has (`ymin `ymax;(97.9;99.1)) The value of the `ylabel attribute is a four-element nested vector of the form ã (ticks;labels;sizes;widths) where - ticks is a numeric vector representing the tick values, or locations on the axis where the tick marks occur; - labels is either a nested vector of character vectors, where iØlabels is the label for the tick value i#ticks, or a character matrix, where i#labels is the label for the tick value i#ticks; - sizes is a vector of numbers between 0 and 1, where the length of the i-th tick mark is i#ticks times the current size of the major ticks (that size is controlled by the `majorticksize attribute); - widths is a vector of integers, where i#widths is the width, in pixels, of the grid line at the ith tick mark. Continuing the previous example: ticksû98+.2«É6 labelsû("one";"two";"three";"four";"five";"six") sizeû0 .2 .4 .6 .8 1 widthû0 1 2 3 4 5 `g has (`ylabel;(ticks;labels;size;width)) You should see tick marks at locations 98, 98.2,...,99 with labels "one" through "six". The tick marks lengths are 0, 2,...,10 pixels (10 is the value of the `majorticksize attribute). And, finally, there are grid lines of width 0, 1,...,5 pixels. As you can see, the possibilities are boundless for creating major and minor tick marks with various label and grid line strategies. In this example all four quantities have the same length, but that is not required. If more labels are given than there are tick marks, the extras are ignored. If fewer are given, the missing ones are considered to be blank. In particular, tick marks without labels are obtained by specifying one label, and making that one all blank. `g has (`ylabel;(ticks;" ";size;width)) If either size or width has fewer elements than ticks, those elements are used cyclically, in the manner of the A+ Reshape primitive. `g has (`ylabel;(ticks;labels;size[1 3 5];width[2 4])) It is not necessary to specify all four components; only ticks must be present. If labels is missing, the default format is used, or the setting of the labelout attribute if there is one. `g has (`ylabel;(ticks;size[1 3 5];width[2 4])) If only one of size and width is present, which it is can (almost) always be determined by the values: widths must be whole numbers, while sizes are 0, 1, or fractions in between. The one ambiguous case is a vector of 0's and 1's, and that is taken to be a width specification. `g has (`ylabel;(ticks;0 1)) Like `ylabelout, `ylabel can be assigned a function that will be called whenever tick marks and labels are needed for a graph, e.g., each time a graph is zoomed (see "5a. Zooming"). When called, the function must produce a four-element vector like the one described above. There are interesting interactions between xlabel settings and sublabels. Suppose the x-axis in the present example represents dates and define: `g has (`xlabel;(2«É10;10 3Ò"JanAprJulOct")) Each group of labels "Jan through "Oct" represents a year, and we can use the sublabel attribute to put year designations under the groups: `g has (`xsublabel;(3 11 19;3 4Ò"199219931994")) When a graph is zoomed, a section of the view is blown up to fill the entire plot area. If `ylabel is assigned a fixed value, as in the above example, then these are the only tick marks that can be used for the zoomed view. Some of them may fall in the range of the zoomed view, but some may not. If the area of the original graph chosen for zooming contained none of these tick values, no tick marks would appear. But if `ylabel is assigned a function, that function will be called to determine new tick locations and labels for the zoomed view. There are several graph attributes that can be referenced in the `ylabel function that produce information helpful in determining tick values and labels. `yextent of `g is a three-element vector containing the minimum value along the y-axis, the maximum value, and a scale factor. As a result of the last expression you should see: < 97.9 99.1 107.5 although the third element might be different. 97.9 is the minimum value and 99.1 the maximum value along the y axis, which we set above. The scale factor is such that (99.1-97.9)«107.5 is the length of the y-axis in pixels. Resize the graph, evaluate `yextent of `g again, and you should see a new scale factor. It should be easy to understand that the minimum and maximum values are necessary for determining tick values. But what is the point of the scale? Well, you don't want so many tick values that the labels overrun each other. Since you know the length of the y-axis in pixels, once you determine the number of tick marks, you know the distance between tick marks in pixels. The labelheight attributes tell you the height in pixels of all labels, and therefore you can determine whether or not they overlap. For example: `xlabelheight of `g Analogously, xlabelwidth attributes tell you the width of labels in pixels, which can be used, for example, to see that x-axis labels don't overrun one another. However, the situation is more complicated for x-axis labels, since both the label texts and font characters can have different widths. Therefore, to determine the width of a proposed label, the text of the label is part of the query: (`xlabelwidth;"testlabel") of `g It is also possible to determine the widths of several labels at once, either as the rows of a character matrix or as the elements of a nested vector of character vectors: (`xlabelwidth;3 5Ò"one two three") of `g or (`xlabelwidth;("one";"two";"three")) of `g Now that we have specified the y-axis labels and can determine their widths, we can easily create a nice effect for these labels: `g has (`ylabeljustify;`top) `g has (`ymajorticksize;Ó/0Ø(`ylabelwidth;labels) of `g) `g has (`ylabeljustify;`bottom) 2h. Alternate Axes The last two graph components have to do with arranging traces with different scales on the same graph. Neither of these components appear in the default form of a graph. The components are the alternate x-axis and the alternate y-axis. We begin by demonstrating how these components can be made to appear and disappear. The default axis configuration consisting of an x-axis on the bottom and a y-axis on the left can be specified as follows: `g has (`axis;`std) It is also possible to have a alternate x-axis at the top of the graph and an alternate y-axis to the right. In fact, any or all of these four can be used, or none. For example: `g has (`axis;`box) ã All four axes `g has (`axis;`xYy) ã Three axes; the alternate x-axis is ã missing. Instead of `xYy, as in the last example, any of `xyY, `Yxy, `xy, `YX, etc. can be used, and the axis designators (x, y, X, Y) can appear in any order. `g has (`axis;`) ã No axes. There are also interesting effects when just the rules for certain axes are used. For example: `g has (`axis;`std) ã Standard x-axis and y-axis. `g has (`rule;`XY) ã Include rules on the top and right. or `g has (`axis;`) ã No axes. `g has (`rule;`box) ã Enclosing box made up of axis rules. In these examples the alternate axes have the same scales as the corresponding default axes, but in practice they are most useful when they have different scales. This is because it is often useful for traces with values in different scales to appear on the same graph: for example, two traces of bond prices and another of their spreads, where the prices are plotted on the y-axis and the spreads on the alternate y-axis. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s p1û98.8 99.6 101.3 99.1 100.7 p2û101.8 101.2 99.9 100.5 99.6 sûp1-p2 gû`p1 `p2 `s show `g is `graph `p2 has (`linecolor;`yellow) `g has (`xs`ys;(300;200)) ã This may have no effect, i.e., ã this may be the default size. You can see that the two price traces are clustered around 100 and the spread is clustered around 0, which is to be expected. When they are all plotted on the same scale, the graph has very poor resolution. Even worse, it does not make sense to plot them on the same scale. The spread should be plotted on a separate graph, or on a separate scale on the same graph. The alternate y-axis can be used for this purpose, as follows: `s has (`yaxis;`Y) Setting the `yaxis attribute for a trace set to be the alternate y-axis modifies the graph so that the trace set is plotted on a second, independent y-axis appearing on the right of the plot area. Note that removing the spread trace set from those to be plotted on the left y-axis enabled that axis to be rescaled. The default value for the `yaxis attribute is `y, which causes the trace set to be plotted on the original left y-axis. `s has (`yaxis;`y) `s has (`yaxis;`Y) Note that specifying `yaxis to be the alternate y-axis caused that axis to appear. The automatic appearance of the alternate y-axis is due to the setting of the `axis attribute for g, which is `std, the default. For any other setting, the traces will be rescaled but alternate axes will not appear automatically. `s has (`yaxis;`y) `g has (`axis;`xy) ã The graph looks the same as the `std setting. `s has (`yaxis;`Y) ã Rescale the traces, but no alternate y-axis. `s has (`yaxis;`y) `g has (`axis;`std) `s has (`yaxis;`Y) ã Rescale the traces,and get alternate y-axis. The `std value for the axis attribute can be said to be passive, however. Setting axis to `std does not cause the graph to be redrawn: `g has (`axis;`xy) ã Active: removes the alternate y-axis. `s has (`yaxis;`y) `s has (`yaxis;`Y) ã Rescale the traces, but no alternate y-axis. `g has (`axis;`std) ã Passive: still no alternate y-axis. `p2 has (`linecolor;`yellow) ã Forced redrawing shows the axis. Grid lines can drawn for either the y-axis or the alternate y-axis, but not both: `g has (`grid;`y) `g has (`grid;`Y) `g has (`grid;`Yy) `g has (`grid;`yY) All attributes for the alternate y-axis are the counterparts of y-axis attributes, and therefore are not illustrated here. They are all listed at the beginning of the tutorial. The x-axis can be controlled in the same was as the y-axis. Again, we content ourselves with the listing of the attributes at the beginning of the tutorial, except to note these combined forms: `g has (`grid;`xy) `g has (`grid;`xY) `g has (`grid;`Xy) ã Accepted, but no vertical grid lines at `g has (`grid;`XY) ã this time, because no alternate x-axis. `g has (`grid;`none) 2h. Zero Axes An additional one or two axes can be included on a graph, each passing through 0 on the appropriate axis. The values of the zero attribute are `none, `x, `X, `y, `Y, `xy, `xY, `Xy, and `XY: `g has (`zero;`xY) The width, color, and style of these axes can be controlled: `g has (`zerowidth;5) `g has (`zerofg;`seagreen) `g has (`zerostyle;`dash3) The values for width are 0 through 10. Those for style are `dot1 through `dot5, `dotdash1 through `dotdash5, `dash1 through `dash5, and `solid. `g has (`zero;`none) 3. Trace Styles ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ So far we have dealt only with graphs composed of line segments. In this section the other graph styles available will be illustrated. We will use the same data as earlier on. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s xû0à "/usr/local/aplus-fsf-4.22/doc/tutorials/graphs/graph_data.m"; We can restrict our attention to a single day. xû50Ùx yûx[;0 1] gû`y show `g is `graph `g has (`xs`ys;(800;300)) `g has (`xlabelout;`hrmin24) `g has (`ylabelout;`32nd) The default graph style is `line. The first set of variations in style are scatter, line-scatter, and bar chart: `y has (`style;`scatter) `y has (`style;`linescatter) ã `ls for short is accepted `y has (`style;`step) `y has (`style;`stepscatter) ã `ss for short is accepted `y has (`style;`bar) Just as you saw for `line, if the trace set has more than two columns then more than one trace is drawn. For example: yûx[;0 1 2] There are now two visible bar graphs, colored the same as if they were line or scatter plots. `y has (`style;`line) `y has (`style;`bar) However, in the case of bar graphs, these colors are default fill colors, not default line colors. We can set the fill colors: `y has (`fillcolor;`yellow `pink) Note that the legend samples for the two traces appear to be quite different from the traces themselves, in that fairly prominent red and green borders appear in the legend, whereas the borders in the traces, if they appear at all, may be narrow and faint. We can bring out the borders in the traces by limiting the graph to fewer points. yû5Ùy The borders should be visible now. They have the same line color characteristic that line graphs have: `y has (`fillcolor;`red `green) `y has (`linecolor;`yellow `pink) Neither of these settings may be easy to see except in the legend, but they still hold if we change the style of the graph: `y has (`style;`scatter) Note that the fillcolor setting is used for the symbols in a scatter plot; in a linescatter plot, the linecolor settings apply to the line segments and the fillcolor settings apply to the symbols. `y has (`style;`linescatter) The symbols that appear in scatter and linescatter traces can be any of the values shown in the following statements: `y has (`symbol;`square `squarefilled) `y has (`symbol;`circle `circlefilled) `y has (`symbol;`diamond `diamondfilled) `y has (`symbol;`cross `xsym) `y has (`symbol;`triangle `trianglefilled) `y has (`symbol;`star) ã If too few, used cyclically. The size of the symbols (in pixels) can be specified: `y has (`symbolsize;50) `y has (`symbolsize;10) The symbol can also be set to any character vector or symbol: `y has (`symbol;"Vertex") `y has (`symbol;`Open`High) This is where the font attribute of the trace set comes into play. `y has (`font;"Courier50") ã This may take a moment to do. `y has (`symbol;`cross`circle) Let's return to the bar graphs: `y has (`style;`bar) The border in a bar graph is only 1 pixel thick, and the thickness cannot be changed. In a graph with many bars, the border may even be eliminated: yûx[;0 1] ã No borders yû5Ùy ã Borders present One last point about these trace styles. The bars and their borders in a bar chart can be individually colored using the `gradient attribute, which cycles through the specified colors, and if none were specified (i.e., a null specification) then through the colors in s.FILLCOLORS and s.LINECOLORS: `y has (`gradient;1) `y has (`fillcolor;) `y has (`linecolor;) (The borders do not show now because the default values of s.FILLCOLORS and s.LINECOLORS are the same.) The gradient attribute applies to scatter plots as well: `y has (`style;`scatter) (Of course, bars and symbols can be colored individually by making the fillcolor and linecolor attributes of the trace set functional; then the colors can be related to the data values. See "Functional Attributes" in the A+ Reference Manual). The remaining graph styles to be illustrated with this data take advantage of the full range of high, low, open, and close information in the data. We will stay with the bar chart for the moment: `y has (`style;`bar) `y has (`gradient;0) yû5Ùx `y has (`fillcolor;`red `blue `white `green) You should see four bar chart traces. The first, in red and appearing on the left in each group, is the open for time period. The second is the high and is in blue, the third is the low and is in white, and the fourth is the close and is in green. These four traces can be combined in one high-low-open-close chart: `y has (`linestyle;`solid) `y has (`linecolor;`red) `y has (`style;`ohlc) Each line extends from the low to the high and has ticks pointing left at the opening and right at the close. This style often looks better with wider lines: `y has (`linewidth;3) Note that the line width also applies to the length of the open and close tick marks on the vertical line segments. The other style that uses the complete high, low, open, and close data is candlestick. `y has (`style;`candle) Again, each one extends from low to high, but the range between open and close is indicated by a box, the candle (the rest being the wick). Since there is only one line color, if the close exceeds the open, the candle is hollow; otherwise it is filled. The fill color can be specified, but using the `linecolor attribute instead of `fillcolor: `y has (`linecolor;`red `pink `white `green) As you can see, the first color, red, is the color of the fill when the open exceeds the close, the second is the color of the vertical line segments (the wicks), the third is the border color of the filled areas, and the fourth is the color of the fill when the open is less than the close. Because the line color attribute is responsible for all color variations, it is easy to switch meaningfully among graph types. `y has (`style;`ohlc) `y has (`style;`scatter `line `linescatter `bar) When the value of `style has more than one element, it must be restricted to styles that require only one y-coordinate, i.e., one column of the trace-set matrix. If fewer than four values are supplied for these attributes, they are used cyclically. If we then set two styles on the current graph: `y has (`style;`line `bar) we see that the first and third traces are line graphs, while the second and fourth are bar graphs. Finally, we have high-low, high-low-close, and close graphs. High-low graphs naturally use three-column matrices, high-low-close four-column, and close graphs two-column. These styles can be applied to the current five-column y, however: the high-low graph will use columns 0, 2, and 3; the high-low-close graph will use columns 0, 2, 3, and 4; and the close graph will use columns 0 and 4. `y has (`style;`highlow) ã `hl is accepted for short `y has (`style;`highlowc) ã `hlc is accepted for short `y has (`style;`close) ã `c is accepted for short In the case of a high-low graph, the data y can also have four columns, in which case the first three are used as the x-coordinates, highs, and lows. For close graphs the data can also have three or four columns, and the first and last column are used in each case. It is often useful in complicated graphs to be able to remove some traces at certain points in an application, and then later put them back. This can accomplished by setting their style to `none, or simply ` for short. `y has (`style;`scatter `line `linescatter `bar) `y has (`style;`scatter `line `none `bar) `y has (`style;`scatter `line `linescatter `) Finally, there is a style for drawing arbitrary line segments, and two other styles related to filling in areas, and for those we will use different traces. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s There are times when you want a trace made of disconnected line segments. This can be done when the number of line segments is small by using separate traces, but even then the set of lines cannot be moved or copied as a group. The segment style solves this problem. The argument must be a two-column matrix of coordinate points. The points are grouped in pairs to form line segments: the first two rows form the first segment, the second two rows the next segment, and so on. For example: xû10 2Ò0 0 1 1 0 1 1 2 0 2 1 3 0 3 1 4 0 4 1 5 x 5 2 2Òx ã Show the segments even better. gû`x show `g is `graph In this view `x is an ordinary line trace. But: `x has (`style;`segment) Moving on to the styles that fill in areas: xû(É10)*2 `x has (`style;`fill) The fill style connects the first and last points of a trace and then fills in the resulting closed polygon with the fillcolor. `x has (`fillcolor;`blue) You should now be able to distinguish the fillcolor from the linecolor border, but even so, for this example we will set: `x has (`linecolor;`white) There is a complement to this graph, obtained by filling in underneath the curve: `x has (`style;`area) Both areas can be put on one graph. `x has (`style;`line) xûô(É#x),x~x `x has (`style;`fill `area) `x has (`fillcolor;`red `blue) Now give both traces the `fill style: `x has (`style;`fill) Since both traces have the same values, only one shows in the graph. This is not true, however, if they are both `area graphs: `x has (`style;`area) Area graphs are cumulative; the top of the red graph actually represents the trace x[;1] plus the trace x[;2]. We can see this by making a third trace which is this sum, and displaying it as a `line graph by default. It will lie along the top of the red area: yûx[;0],@0 x[;1]+x[;2] gûg,`y If we made this separate trace set an area graph, it would be cumulative also: `y has (`style;`area) `y has (`style;`line) A variation of the area graph is the stack graph, which is a stacked bar chart: `x has (`style;`stack) 3a. Text Traces Some of the traces on a graph can be textual, and thereby used to annotate various aspects of a graph. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s xû0à "/usr/local/aplus-fsf-4.22/doc/tutorials/graphs/graph_data.m"; yûx[;0 1] gû`y show `g is `graph `g has (`xs`ys;(800;300)) `g has (`xlabelout;`day7) `g has (`ylabelout;`32nd) All trace sets have titles, but only those titles associated with certain trace sets are visible: namely, trace sets whose style is `text and which have only one coordinate point. (Actually, although it would normally be pointless, the trace set can contain more than one trace and points can be added -- and ignored by A+ -- after the title is displayed.) For example: zû1 2Ò719900000 107.3 gûg,`z `z has (`style;`text) Note that a text trace does not appear in the legend. The default title of a trace set is its name, and you should now see "z" on the graph. We can set the title to the name of the contract with the data y: `z has (`title;`Contract_JYU2) `z has (`title;"Contract: JYU2") The appearance of titles can be modified by specifying their font and color: `z has (`titlefont;"Helvetica-Bold-20") `z has (`titlefg;`yellow) The value of z, which is the coordinate of the title, marks the lower left corner of the text. 4. Graph Attributes ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ The attributes illustrated here are the background color of a graph, the coordinate window, and margins. We continue with the current example. The color midnight blue is commonly used for the background color in graphics packages: `g has (`bg;`midnightblue) Now, however, the axes and legend must be recolored in order to be visible. The foreground color fg applies to all axes, axis labels, legend titles, and legend border whose colors have not been explicitly set. `g has (`fg;`white) Another interesting background color is: `g has (`bg;`green4) `g has (`fg;`black) The color name green, and many others (see the A+ Reference Manual) can be modified with the digits 1 through 4, indicating the degree of grayness in the color. green4 is the most gray of the four, and muted colors are best for graph backgrounds. `g has (`bg;`green3) `g has (`bg;`green2) `g has (`bg;`green1) `g has (`bg;`green4) `g has (`fg;`white) The margins of the area consisting of the plot area, axes and labels, and axis titles can be controlled; their values are in percentages, i.e., integers between 0 and 100, or nonnegative fractions less than 1. First put axis titles on the graph: `g has (`xtitle;"x-axis title") `g has (`ytitle;"y-axis title") `g has (`ytitlestyle;`ver) `g has (`left;20) `g has (`left;0) `g has (`right;0.2) `g has (`right;0) `g has (`bottom;20) `g has (`bottom;0) `g has (`top;0.2) `g has (`top;0) By default, the extreme values of traces touch the boundaries of plot areas; however, there is a margin around the plot area that can be specified, in percentages or fractions. For example: `g has (`xleft;5) `g has (`xright;0.05) `g has (`ybottom;5) `g has (`ytop;0.05) Note that the plot area for traces whose scales are the alternate axes can be specified separately using `Xleft, `Xright, `Ybottom, and `Ytop. The coordinate window can also be specified. This is particularly useful when Ê lining up traces on the alternate y-axis with those on the y-axis; Ê having more direct control, in terms of data, over the margins to accommodate new data. The lower left corner has coordinates (`xmin,`ymin) and the upper right corner has coordinates (`xmax,`ymax). (Ä/y),Ó/y ã xmin, ymin, xmax, ymax. 719746439 106.59 720372715 107.54 ã The output is reproduced here ã for convenience. These values define the default coordinate window. If we set the window to these values, the trace will once again fit tightly in the window. `g has (`rule;`box) `g has (`xmin `ymin `xmax `ymax;(719746439;106.59;720372715;107.54)) Now, move the mouse pointer to the graph and press any one of the arrow keys. As you see, the graph window moves over the graph. (If you click the key too quickly and the window keeps moving, just press any key to stop it.) This is particularly useful for time-series data. The window can be set to show only the most important part of the series, while the user can still see the rest by using the arrow keys. If only `xmin and `xmax have been set, then only horizontal motion is possible, and if only `ymin and `ymax have been set, then only vertical motion is possible. 5. User Interactions ¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢¢ A+ graphics provides a rich set of user interactions for customizing the display, editing the traces (and thereby the data), and examining the details of the traces. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s xû0à "/usr/local/aplus-fsf-4.22/doc/tutorials/graphs/graph_data.m"; yûx gû`y `g is `graph `g has (`xs`ys;(800;300)) `g has (`xlabelout;`hrminsec) `g has (`xsublabelout;`mdy_u) `g has (`ylabelout;`32nd) zû1 2Ò719900000 107.3 gûg,`z `z has (`title;"Contract: JYU2") `z has (`style;`text) show `g 5a. Zooming In the current example, the useful data is in clusters which take up a very small total area. We can use zooming to look at the details of one of these clusters. Pick one and imagine a box around it. Move the pointer to a corner of that imaginary box and press and hold the left button. As you move the pointer a zoom box will appear, anchored to the spot where the pointer was when the button was pressed, and attached to the moving pointer. Move the pointer to a spot where the zoom box encloses a cluster of data (or almost does) and release the mouse button. The graph will be redrawn for the data within the zoom box only. In this example there is no need to zoom further because the detail of the cluster you enlarged should be apparent. When there are many points, however, you may have to zoom several times to see all the details. Or you may simply zoom again to neaten up the view, perhaps for printing. While in the zoomed state you may want to look at the details of another data cluster. One way to do this is to "unzoom" and then zoom again on the new cluster. Another way is provided, however. While zoomed, the graph window acts like a view window that can be moved over the original graph using the arrow keys. Try it. To "unzoom," i.e., to get back to the original graph, put the pointer on the graph and double-click the left button. If you start the zooming process and change your mind while manipulating the zoom box, simply move the pointer near the anchor point or outside the graph object entirely and release the button. 5b. Vertical Cursor and Cross Hairs Zooming is only one way to examine the finer structure in a graph. There are also vertical line and cross hair scans. Put the pointer on the graph, and then press and hold the middle button. You will see three new things: a vertical line running through the pointer; a modified legend box that now displays y-coordinate values, in addition to trace identifiers and trace segments; and a new box (next to the pointer) that displays the x-coordinate. As the pointer moves and the vertical line sweeps across the graph, the line passes over x-coordinates for which there are data values. As this happens the values in the boxes change to the corresponding x-coordinate and y-coordinate values. When the pointer is in an area outside the range of the x-values, the displayed x-values vary continuously and y-values are not shown. You can display this variant of the legend even when you are not in the vertical cursor mode. The displayed values in the legend will be those in the last elements or rows of all the trace sets. `g has (`legendstyle;`lastvalue) If you press the Control key and then press and hold the middle button, you will see a somewhat different display: there are cross hairs instead of a vertical line cursor; the legend is unmodified; both the x- and y-coordinates are displayed in a new box, near the intersection of the cross hairs. As the pointer moves, the intersection point of the cross-hairs cursor moves with it and the changing coordinates are displayed in the box. Both coordinates vary continuously in the appropriate scale units as the cursor moves. You can release the Control key once the cross hairs appear. If there are alternate axes in use, then at any time that the vertical or cross-hairs cursor is active, press the right button (in addition to the middle) to see the alternate coordinates displayed in the moving box as the cursor moves. 5c. Referencing a Graph, Line Trace, or Trace Point Both a graph and its traces have refer events that can have active callback functions. For example, define the following generic callback function, which simply prints out the value of its static data argument, the trace set (if any) associated with the event, and the (x-axis, y-axis) coordinates of the pointer when certain events happen: gcbf{s;c;v}:Õ(s;`selected of c,v;`coordinate of `g) (Use "`Coordinate of `g" when it is appropriate to query the coordinate values of the alternate axes.) Set the refer attribute on the graph as follows: `g has (`refer;(gcbf;`refer)) Now put the mouse pointer anywhere within the window border of the graph and press the left mouse button. You will see `refer displayed in your A+ session, showing that the refer event callback function was called, together with the coordinates of the pointer position when the refer attribute happened. In practice, the callback function would be defined to do something meaningful. A refer event can occur on a trace if Ê its style is line, Ê the trace is the only one in its trace set, Ê the trace set has two columns, meaning that the x-coordinates are explicitly specified, and Ê when the mouse pointer is on a line segment connecting two data points, you double-click the left mouse button. But first the trace must be selectable: yûx[;0 1] `y has (`selectable;1) `y has (`refer;(gcbf;`refertrace)) Now put the mouse pointer anywhere on a line segment and double-click the left mouse button. You will see `refertrace displayed in your A+ session when you have successfully selected the trace; you will also see that the pointer is now a red arrow when it is near the selected trace and cross hairs away from it. Note that a new `refer appears just above the `refertrace in your A+ session, because a refer event was caused by the first click of the double click. To revert to the unselected state, move the pointer onto the graph but outside that object, and double-click the left button. Finally, a referpoint event occurs when the mouse pointer is on a trace point and the left mouse button is pressed: yûx `y has (`referpoint;(gcbf;`referpoint)) The selected attribute of the trace will hold the (row index, column index) of the referenced point. Put the mouse pointer on a trace point and press the left mouse button. Unlike refer events on traces, referpoint events occur no matter how many traces there are in a trace set, and no matter what the trace style. For example, set: `y has (`style;`ohlc) and zoom the graph until you see distinct vertical segments. Put the mouse pointer on one of the segments and press the left mouse button to get a referpoint event. To get back to where we were, move the mouse pointer off the traces and double-click the left mouse button to undo the zooming. Then yûx[;0 1] `y has (`style;`line) 5d. Selecting the Legend or a Text Trace. Before a text trace can be selected, it must be made selectable: `z has (`selectable;1) To select either the legend or a text trace, move the pointer onto it and double-click the left button. The legend or text trace will then be displayed with its background and foreground (i.e., text) colors reversed. To revert to the unselected state, move the pointer onto the graph but outside that object, and double-click the left button. A refer event does not occur when the legend is selected. Try selecting the legend and text trace and reverting to the unselected state. 5e. Repositioning the Legend and Traces It is often useful to be able to reposition a legend or text annotation that is covering an important part of a graph. There are also important instances of repositioning numeric traces, such as trendlines. To reposition an object, first select it and, with the pointer on the object, press the left button and hold it. As you move the pointer, either the object or an outline of it moves with the pointer. When you release the left button, the object will stay in its last position. Note that for any trace to be moved, it must be selectable; that is, its selectable attribute must have the value 1. For numeric traces, only a line trace that is the only trace in its trace set can be selected, and therefore only such a numeric trace can be moved. yûx[;0 1] Try repositioning the legend and the traces. Note that when a trace is moved, the value of the corresponding variable changes accordingly. 5f. Copying and Deleting Trace Sets To copy a trace set, first select it, then put the pointer on it, and press and hold the Shift key and then the left mouse button. Move the pointer in order to position the copy; either the trace or an outline of it will move with the pointer. When the left button is released, a copy of the trace will appear at the last position of the pointer. (You can then release the Shift key.) If you look at the graph variable g, you will see that it now has a new element, in addition to `y and `z and any elements from previous trace copies. Execute the following to see the new element: g A+ has created a new trace set variable to accommodate the copied text trace, and chosen its name to be the first one available from a list that begins `a, `b, `c, ... . The new element of g is the symbol form of that name. To delete a trace, first activate the default delete behavior as follows: `g has (`delete;1) Now select a trace and press the Meta-Delete key (on an IBM keyboard, Alt-Delete). The trace will disappear. It has been deleted and its variable removed from g. As with repositioning, a trace must be selectable to copy or delete it. 5g. Editing and Creating Text Traces Before we begin this section, restore the graph as follows: yûx[;0 1] gû`y`z You can edit a text trace on the screen. Simply move the pointer onto the text, hold down the Meta (diamond) key (Alt on IBM keyboards), and press the middle mouse button. An edit window will appear around the text and you can now delete and insert characters. Press the Return key when editing is complete. If you then examine the title of the text trace you will see the modified text. Try editing the text trace in the current example and then check: `title of `z We can monitor the editing of text traces: `z has (`textactivate;(gcbf;`text_activate)) Edit the text again; when you press Return at the end of the editing process the callback function is executed. If the pointer is on the graph but not on the text of a text trace when the Meta key and middle button are pressed, an empty edit box will appear. The text entered in this box will be the title of a new text trace; the data of the new trace will be a matrix with shape 1 2 holding the user coordinates of the pointer location when the edit box was initialized. If you change your mind at any time while editing or creating a text trace, simply press the Esc key to abort the editing and restore the previous status. Try bringing up the edit box for a new text trace and entering some text. Press the Return key when entry is done. Then enter g Just as when copying text traces, you will find a new name (symbol) appended to g. Examine the title and data of the new text trace. Text traces created in this way are automatically selectable, and therefore can be moved, copied, and deleted. You can use the mode attribute to initiate the creation of a text trace at the point indicated by the coordinate attribute: `g has (`coordinate;719974911 107.45) `g has (`mode;`addtexttrace) Now enter some text in the new trace, but don't press Return. `g has (`mode;`normal) This setting of mode terminates interactive entry. The third setting is `addtrace, which begins interactive entry of a line trace. A user can terminate an interaction begun by a setting of mode, and an entry initiated by the user can be terminated by a setting of mode. You also have control over the behavior when users add, copy, and delete text traces. For example, using the generic callback function defined above we can monitor the adding and copying of text traces: `g has (`addtexttrace;(gcbf;`add_text_trace)) `g has (`copytexttrace;(gcbf;`copy_text_trace)) Now attempt to copy the text trace on the graph (see "5f. Copying and Deleting Trace Sets"). When the copy sequence is completed, you will see `copy_text_trace appear in your A+ session, indicating that the function gcbf was called, and the coordinates of the pointer at the time the copy event occurred. The copy will not be made, naturally, since the default meaning of the copy sequence has been superseded by the call to gcbf. Of course, you can redefine gcbf to put a copy of the text trace z at the coordinates given by `coordinate of `g. The same behavior occurs when you complete the procedure for creating a new text trace, as described earlier in this section. The default behavior can be restored as follows: `g has (`addtexttrace;) The control of trace deletion is similar, as in: `g has (`delete;(gcbf;`delete)) Now select the text trace and press Meta-Delete. 5h. Modifying and Creating Numeric Traces It is also possible to modify numeric traces. To do this you must place the pointer near a data point, so first zoom in on one of the clusters. Place the pointer on a data point (i.e., a vertex of the graph) and press and hold the right button. Small cross hairs under the pointer and a box containing the x- and y-coordinates of the point should appear and the connecting line segments should change color. As you move the pointer the cross hairs will move up and down vertically, remaining parallel with pointer. Release the button and the graph will be modified to show the data point moved to the location of the cross hairs when the button was released. The value of the trace set variable will have changed accordingly. The `selected attribute of the trace will hold the (row index, column index) pair of the moved point. Try modifying various points of the graph and examine the changed values of the trace set variable. There are two attributes associated with modifying numeric traces on the screen. As you may have noticed, it is not necessary to place the pointer exactly on the data point to be moved. It is only necessary to get close to the data point, and the required closeness can be specified: `g has (`selectdistance;50) The default value for this attribute is 10, and 50 is a bit large, but you can now see quite easily the general behavior of the data point selection algorithm. In effect, an imaginary region based on the value of this attribute is placed around the data point, and if the pointer falls in that region, the data point is selected. Experiment with selecting data points with this large value of the selectdistance attribute. Secondly, the constraint that only the y-coordinate is modified, which is useful for avoiding small, unwanted changes is the x-coordinates, is an attribute value: `movelimit of `y < `x ã This is the default If this attribute is set to `y, then only the x-coordinate can be modified, and if it is set to `none then both coordinates can be modified. The default is `x. Note that this attribute is effective for two-column trace sets only; in all other trace sets, only the y-coordinate can be modified, because either there are no explicit x-coordinates to be modified or each x-coordinate is paired with several y-coordinates and moving it would affect several points. Line traces can created on the screen. Place the mouse pointer on the graph, press and hold the Control key, and then press and hold the left mouse button. As you move the mouse pointer a line will appear with one end anchored at the spot where you first pressed the left mouse button, and the other attached to the pointer. Release the mouse button and the line segment will become fixed, with small knobs at the two ends. You can rotate the line segment and change its length by putting the mouse pointer on either knob, pressing and holding the left mouse button, and moving the knob. You can reposition it in a parallel fashion by putting the pointer on the line away from the knobs, pressing and holding the left mouse button, and moving the line. You can make more line segments by putting the mouse pointer on the knob at either end, pressing and holding the Shift key and then the left mouse button, and then moving the pointer. Release the mouse button to get a new line segment. (Once the line segment connected to the pointer appears, the Shift key can be released.) Double-click the left mouse button to fix the line segments as a new trace. If at any time you change your mind about creating a new line trace, press the Esc key. Or, if you change your mind about adding a new line segment to a trace you are creating, but are already in the process of doing so, move the pointer so the ends of that line segment are close together, and release the button. Line traces created in this way are automatically selectable, and therefore can be moved, copied, and deleted. As with text traces, the programmer has control over how users add, copy, and delete line traces. For example, using the generic callback function defined above, we can monitor the adding and copying of line traces: `g has (`addtrace;(gcbf;`add_line_trace)) `g has (`copytrace;(gcbf;`copy_line_trace)) Deleting traces is the same as for text traces. As with text traces, in practice the callback function would be defined to carry out some action reasonable for the application at hand. 6. Monitoring Performance It may be necessary to improve the performance of your application by improving its interface to graphics. Many actions cause a graph to be completely redrawn, and some of those redrawings may be unnecessary. A different sequence of actions may reduce the amount of redrawing, Also, if the last point in a trace is modified only that modification should take place on the graph, i.e., there should not be a complete redrawing. The s.QUIET variable is a tool for monitoring performance. If it is set to 0 (the default), then whenever the graph is redrawn, updated, or printed, an A+ comment to that effect appears in the A+ session log. s.QUIET can have any of four values and four corresponding sets of messages are displayed by the screen management system: Ê -1: None. Ê 2: Severe errors. Ê 1: Moderate and severe errors. Ê 0: Information, warnings, and moderate and severe errors. Restricting the messages to the ones you need under the particular execution circumstances can greatly reduce clutter in the A+ session log. You have seen the information messages that are displayed. We will now show the error messages. We start fresh. $off ã Exit from A+ Press F4 to start A+ again, then move the cursor back to the tutorial buffer, on the next line. $load s yû98+0.01«+?20Ò100 gû`y `g is `slot Since g is not a slotfiller, this attempted binding is a severe error, whose level is recognizable by the two exclamation points. `g is `graph `g has (`unknownattribute;0) Since there is no such attribute, this attempted setting is a moderate error, whose level is recognizable by the single exclamation point. Back to performance. Now we will show the graph and then set some attributes and adjust a data point. After each action, you should see an information message, redraw: show `g `g has (`ylabelout;`float) `y has (`style;`scatter) y[¢1+#y]ûy[¢1+#y]+0.01 One way to reduce the number of redrawings is to set attributes before showing the graph. For example: free `g Now define g to be a graph, but do not show it: `g is `graph Set the two attributes that were set above and adjust a data point again: `g has (`ylabelout;`float) `y has (`style;`scatter) y[¢1+#y]ûy[¢1+#y]+0.01 Now show the graph: show `g In this sequence the graph is drawn only once, while in the first sequence it was drawn four times. This is better style as well, since the graph will not appear to go through a series of incremental changes to get to its final state. Now let's leave some room to append points to y and accordingly make the width of the graph (attribute xs) 50% larger, to accommodate the longer axis: `g has (`xmax;30; `xs;1.5 « >`xs of `g) When there is room for additional points and the append form of assignment is used, then adding points does not cause the entire graph to be redrawn, but only a portion, in an append operation. We will time the first two actions, to show the efficiency of appending over redrawing, even in a simple one-trace graph: time yûy,98.3 ã Not an append assignment; redraw. time y[,]û98.4 ã An append assignment; no redraw. y[,]û98.6 98.5 98.8 ã Likewise. y[,]û12Ò98.9 98.8 ã Run out of space; redraw.