@device(PostScript)
@make(report)
@DefineFont(HeadingFont,
        P=<RawFont "NewCenturySchlbkBoldItalic">,
        B=<RawFont "NewCenturySchlbkBold">,
        I=<RawFont "NewCenturySchlbkBoldItalic">,
        R=<RawFont "NewCenturySchlbkRoman">)



@Counter(MajorPart,TitleEnv HD0,ContentsEnv tc0,Numbered [@I],
          IncrementedBy Use,Announced)
@Counter(Chapter,TitleEnv HD1,ContentsEnv tc1,Numbered [@1. ],
          IncrementedBy Use,Referenced [@1],Announced)
@Counter(Appendix,TitleEnv HD1,ContentsEnv tc1,Numbered [@I. ],
          IncrementedBy,Referenced [@I],Announced,Alias Chapter)
@Counter(UnNumbered,TitleEnv HD1,ContentsEnv tc1,Announced,Alias 
           Chapter)
@Counter(Section,Within Chapter,TitleEnv HD2,ContentsEnv tc2,
          Numbered [@#@:.@1 ],Referenced [@#@:.@1],IncrementedBy
          Use,Announced)
@Counter(AppendixSection,Within Appendix,TitleEnv HD2,
          ContentsEnv tc2,
          Numbered [@#@:.@1 ],Referenced [@#@:.@1],IncrementedBy 
          Use,Announced)
@Counter(SubSection,Within Section,TitleEnv HD3,ContentsEnv tc3,
          Numbered [@#@:.@1 ],IncrementedBy Use,
          Referenced [@#@:.@1])
@Counter(Paragraph,Within SubSection,TitleEnv HD4,ContentsEnv tc4,
          Numbered [@#@:.@1 ],Referenced [@#@:.@1],
          IncrementedBy Use)
@modify(CopyrightNotice, Fixed -1 inch, Flushright)
@Modify(Titlebox, Fixed 3.0 inches)
@Modify(hd1, below .2 inch, facecode B, size 20, spaces kept, pagebreak off)
@Modify(hd2, below .2 inch, facecode B, size 16, spaces kept)
@Modify(hd3, below .2 inch, facecode B, size 12, spaces kept)
@Modify(Description, Leftmargin +20, Indent -20,below 1 line, above 1 line)
@Modify(Tc1, Above .5,  Facecode B)
@Modify(Tc2, Above .25, Below .25, Facecode R)
@Modify(Tc3,Facecode R)
@Modify(Tc4,Facecode R)
@Modify(Itemize,Above 1line,Below 1line)
@Modify(Insert,LeftMargin +2, RightMargin +2)
@Style(Font NewCenturySchoolBook, size 11)
@Style(Spacing 1.1, indent 0)
@Style(leftmargin 1.0inch)
@Style(justification yes)
@Style(BottomMargin 1.5inch)
@Style(ChangeBarLocation Right)
@Style(ChangeBars=off)
@style(date "March 8, 1952")
@pageheading(immediate)
@pagefooting(left="MIT Project Athena",
center="@value(page)",right="Revision A, Nov. 1984")
@begin(Titlepage)
@Begin(Titlebox)
@begin(MajorHeading, size 36, Flushright)
Using QPICTR
@end(Majorheading)
@blankspace(3 lines)
@begin (format, size 14, flushright)
James L. Fulton
MIT Project Athena
Revision A
November 1984
@end(format)
@end(titlebox)
@CopyrightNotice(Massachusetts Institute of Technology)
@Set(page=-1)

@end(titlepage)
@newpage

@set(page=1)

@chapter(Introduction to QPICTR)

One of the most common uses of graphics software is the plotting of arrays of
numbers.  To make this as easy as possible, Penplot supplies a package
specfically designed for doing this type of plotting.  The QPICTR subroutine
and its associated functions produce scaled and annotated plots of arrays of
data in a single subroutine call.  It provides a powerful, quick, and easy way
to graph data.

QPICTR produces a complete, annotated graph on any Penplot device.  The
routine scales the X- and Y-axes of the graph independently so that the curves
fit neatly on the plot.  A box is drawn around the plotting area and tic marks
are drawn and annotated.  The range of values plotted on the axes is made
somewhat larger than the actual range of the data so that the axes may be
labelled aesthetically.

Data points are represented by elements of an array.  Each row of the array
is treated as a separate curve, allowing one or more curves to be plotted
in a single call to QPICTR.  Although QPICTR is designed to produce nice graphs
with a minimum of information, the user has control over many different
features of the plot:

@begin(itemize)

the selection of the curves to be plotted.

the choice of a curve to be used as the independent variable for
cross-plots.

logarithmic or linear (including semi-log) scaling of the X and Y axes.

user defined or automatic scaling.

labels and annotation of the axis and curves, including choice of color,
dashed line pattern, and data point marking pattern.

@end(itemize)

@chapter(How to Call QPICTR)

A single call to QPICTR may plot between 1 and 99 different curves.  The data
for each curve are stored as rows in an array that is passed to QPICTR.
Because QPICTR is just another Penplot routine (in the same sense as MOVE or
DRAW), it must be called after the user has called one or more device
initialization routines (e.g. VT125, VS100, etc.).  The subroutine requires at
three arguments but may have more.

The user must specify an array of data points, the number of rows in the array,
and the number of points to be plotted for each curve.  In addition, the user
may use optional trailing arguments to give information that is used to
customize the plot.  The format for calling QPICTR from Fortran is as follows:

@begin(example)
CALL VT125
CALL QPICTR (ARRAY, NROWS, NPTS, Q-Functions...)
@end(example)

where

@begin(description)

ARRAY@\is a REAL*4 array of points to be plotted.

NROWS@\is an INTEGER*4 giving the number of rows in ARRAY.  If NROWS is
negative then QPICTR assumes that the ARRAY is a REAL*8 (double precision)
array.  For more information see the section on Plotting Double Precision
and Complex Arrays.

NPTS@\is an INTEGER*4 giving the number of points to plot for each
curve.  NPTS must be less than or equal to the number of columns in ARRAY.

Q-Functions...@\are the functions that are used to modify the
default actions of QPICTR.  They are explained in greater detail in the
following section.

@end(description)

By default QPICTR will call ENDPLT at the end of the plot.  This can be
overridden by the QMOVE Q-Function (see below).  In most cases there is
no need to call anything in Penplot other than QPICTR and a device
intialization routine.

@chapter(Tailoring A QPICTR Plot -- Q-Functions)

The call described above will produce a plot that is automatically scaled on
the Y-axis, and is normalized along the X-axis between 0. and 1.  Although the
basic call to QPICTR will produce a simple, but understandable, graph, there are number of 
features that are available through the use of Q-Functions.  These additional
'arguments' are simply function calls that modify internal parameters that
QPICTR uses in preparing a plot.  Thus, the order of the Q-Functions does not
matter (except when QINIT is used to reset all of the QPICTR defaults).  For
example, if a user wanted to plot an array of points such that rows 1, 3, and 5
would be plotted against row 4 (ignoring row 2), the following code fragment
could be used:

@begin(example,group, leftmargin +.5inch)

        REAL*5 A(5,50)
        INTEGER*4 IROWLIST(3)
        DATA IROWLIST /1, 3, 5/
C
C  Fill in the data for array A.
C
        CALL VT125
        CALL QPICTR (A, 5, 50, QYLIST(3,IROWLIST), QX(4))
        END

@end(example)

QYLIST and QX are described below.  Additional examples are available at
the end of this section.

Although QPICTR will generally produce a proper graph with a a minimum
of tailoring, there are a number of features that can be used to customize
the graph that is created.  The Q-Functions listed below may be used in
any combination and provide a great deal of flexibility in controlling how
the curves are plotted.

@begin(description)

QY(number of the row to be plotted)@\QY takes an INTEGER*4 argument which
is the number of the row of data to be plotted.  If two or more curves are to
be plotted on the same graph, use QYLIST.  If neither QY nor QYLIST are called,
all NROWS rows of the array will be plotted.

QYLIST(number of curves to be plotted, array of row numbers)@\QYLIST
selects a list of curves to be plotted.  The first argument is an INTEGER*4
specifying the number of rows that will be plotted.  The second argument is an
INTEGER*4 array that contains the numbers of the rows to be plotted.  In the
example given above, IROWLIST contains the rows to be plotted (1, 3, and 5)
and the number (3) is the size of the array.

QX(row to be used as the X-axis)@\QX takes an INTEGER*4 which is the
number of the row of data to be used as the X-axis.  If the number is not
between 1 and NROWS or if the QX function is not used, the X-axis will range
between 0. and 1.  In the example given above, the fourth row of the array is
used as the range of values to be plotted as the X-axis.

QXLAB(X-axis label)@\QXLAB takes a CHARACTER string to be used for a title
on the X-axis.  Both uppercase and lowercase letters and numbers may be used,
but only the first 40 characters will be plotted.  The title will be 
centered below the axis.

QYLAB(Y-axis label)@\QYLAB takes a CHARACTER string to be used for a title
on the Y-axis.  Both uppercase and lowercase letters and numbers may be used,
but only the first 40 characters will be plotted.  The title will be 
centered along the axis.

@begin(multiple)
QMOVE(move code)@\QMOVE controls the opening and closing of the plot
before and after the call to QPICTR.  The argument is one of the following
INTEGER*4 numbers:
@begin(description)
00@\A new and separate plot is created for this plot.  The plot is opened
(i.e. initialized) at the begining and closed (i.e. ENDPLT is called) at
the end of the call to QPICTR.

01@\A new plot is created for this plot, @i[but] the plot is NOT closed at
the end to allow further calls to QPICTR to add new data to the plot.

10@\No new file is opened for this plot, and all of the data is added to the
existing plot.  The plot is closed (i.e. ENDPLT is called) at the end.

11@\No new plot is opened, and the existing plot is NOT closed after the call
to QPICTR.
@end(description)
The default is 00; a new plot is begun at the start of each call to QPICTR and
ENDPLT is called at the end of the plot.  By combining calls to QMOVE and
QLABEL, multiple calls to QPICTR can plot data onto the same graph.  At the
end of this section are are several examples of how this might be done.
@end(multiple)

@begin(multiple)
QLABEL(value)@\QLABEL is used to modify the type of labelling and
annotation that is used.  It takes an INTEGER*4 argument of which the least
significant digit is one of the numbers listed below:
@begin(description)
0@\No frame is drawn around the plot.  This is primarily used in multiple
calls to QPICTR.

1@\A simple box with tic marks annotated only at the corners is drawn around
the plot.

2@\A simple box with tic marks annotated on the X- and Y- axes is drawn
around the plot.  This is the default if neither QXLAB nor QYLAB is given.

3@\This draws the same box as in 2, but also reads labels for the X- and
Y-axes from the standard input (usually your terminal).

4@\This draws the same box as in 2, but also uses the values of the
QXLAB and QYLAB functions as labels for the X- and Y-axes respectively.
If QXLAB or QYLAB is given, but QLABEL is not, QPICTR will assume a QLABEL
value of 4 by default.

9@\This draws a simple box with tic marks but no annotation.
@end(description)
There are several ways in which each of the above values can be
modified.  Below is a list of options that may be used by adding the 
indicated number(s) to the digit chosen above.
@begin(description)
+10@\The individual curves are not annotated.

+100@\The actual X- and Y-axis (Y=0 and X=0) are drawn if they fall within
the boundaries of the plot.

+1000@\Instead of connecting the data points with lines, a mark (such as a
little circle, square, X, etc.) will be drawn over the point.  Adding @i[N]
thousand causes curves 1 through N-1 to be drawn with lines and the remaining
curves (N and above) to be drawn with marks.  The QMARKLIST Q-Function can be
used to specify which marks should be used for which curves.  In the examples
section is a chart showing the marks that are available.
@end(description)
@end(multiple)

@begin(multiple)
QISCL(value)@\QISCL specifies how the plot should be scaled.  Like
QLABEL it takes an INTEGER*4 value which specifies one of several different
options:
@begin(description)
-2@\Use the arrary of numbers given by QXSCL to set the scales for the plot.
If QXSCL is given, but QISCL is not, this is the default.

1@\Have QPICTR automatically scale the plot.  If neither QXSCL nor QISCL is
given, this is the default.

2@\Automatically scale the plot, but return the minimum and maximum datapoints 
in the array passed to QXSCL.  Note that this means that the elements in this
array are changed by the call to QPICTR.    
@end(description)
In addition, the user may specify semi-log or log-log scaling.  When a log
scale is used for an axis, an integral number of decades are drawn
with ten tick marks per decade.  Note that zero values cannot be plotted and
cause the autoscale routine to begin with the decade 1.0E-38.  The following
options can be used to specify log scaling by adding the value listed below
to -1, 1, or 2:
@begin(description)
+10@\Use a log scale on the X-axis.

+20@\Use a log scale on the Y-axis.
@end(description)
Thus, the possible values that may be given to QISCL are: -2, 8, 18, 28,
1, 11, 21, 31, 2, 12, 22, and 32.
@end(multiple)

QXSCL(array of bounds)@\QXSCL gives the scale to be used in making
the graph.  The argument is a REAL*4 array containing the the left, right,
bottom, and top bounds respectively.  Any points which do not fit within the
ranges specified by the array are ignored.  For this to take effect, QISCL
should be called with -2, 8, 18, or 28.

QFTIME(value)@\QFTIME is used to specify a REAL*4 value which is to be
the final time (i.e. maximum value) to be plotted on the X-axis.  By default,
QPICTR normalizes the X-axis between 0. and 1.; QFTIME is used to change the
upper bound.

QCURVLAB(string of curve labels)@\QCURVLAB modifies the labels used to
identify the different curves.  The argument to QCURVLAB is a CHARACTER string
of up to 100 characters.  This string is broken down into pairs of characters
which are used to label the curves.  For example, if 'ABCDEF' were passed to
QCURVLAB cthe first curve would be labelled 'AB', the second would be labelled
'CD', the third would be labelled 'EF'.  By default QPICTR uses the number of
the curve within the data array as the curve label (e.g. ' 1', ' 2', and ' 3').

QNAME(title for the QPICTR plot)@\QNAME is used to give a title to the
plot produced by QPICTR.  It takes a string of up to 60 characters and
centers the label at the top of the graph.

QCOLOR(axis color, label color, curves color)@\QCOLOR is used to specify
the pen colors to be used in plotting the axis, label, and curve sections of
the graph.  The arguments are INTEGER*4 numbers which are passed to PEN before
the appropriate section of the graph is plotted.  By default all three parts
are plotted in the brightest color (i.e. CALL PEN (3)).  QCOLOR allows the user
to specify a single color to use for all of the curves; to plot
different curves in different colors, use the QPENLIST Q-Function.

QPENLIST(number of curves, array of PEN values)@\QPENLIST is used to
specify the pen color to be used when plotting the individual curves.  It 
requires an INTEGER*4 giving the number of curves for which a pen color is
to be specified and an array of INTEGER*4 numbers with at least that many
elements.  Each element of the array gives a value that is used in a call
to PEN before the corresponding curve is plotted (i.e. CALL PEN (i)).  By
default, QPICTR will plot all curves in the curve color specified by QCOLOR
(the default is the brightest color).  To reset the PENLIST if QPICTR is being
called more than once, give zero (0) as the number of curves.  Curve
annotations are done in the same colors as the curve.

QLINELIST(number of curves, array of LINE values)@\QLINELIST is used to
specify dashed line patterns to be used when plotting the individual curves.
It requires an INTEGER*4 giving the number of curves for which a pattern is to
be specified and an array of INTEGER*4 numbers with at least that many
elements.  Each element of the array gives a value that is used in a call to
LINE before the corresponding curve is plotted (i.e. CALL LINE (i)).  By
default, QPICTR will plot all curves as solid lines.  To reset the LINELIST if
QPICTR is being called more than once, give zero (0) as the number of curves.
In any case, curve annotations are always done in solid lines.

QMARKLIST(number of curves, array of MARK values)@\QMARKLIST is used to
specify the mark to be used whenever QLABEL with an argument of 1000 or more
(i.e. mark plots, don't connect points by lines); by default, QPICTR uses the
curve number in selecting a mark.  QMARKLIST takes an INTEGER*4 that is the
number of curves for which a mark is to be specfied and an INTEGER*4 array of
mark numbers.  The examples section contains a chart listing the various marks
that can be used.

QINIT(dummy value)@\QINIT resets all of the QPICTR defaults.  It should
appear at the beginning of a list of Q-Functions.

@end(description)


@chapter(Miscellaneous Notes on QPICTR)

Once a Q-Function has been called, it remains in effect for all subsequent
QPICTR calls in the current program until one of the following happens:

@begin(itemize)

its effect is undone by another call to a Q-Function.

the QINIT function is called.  Note the QINIT is the only Q-Function whose
position on the call line is important.

@end(itemize)

The new QCOLOR, QPENLIST, and QLINELIST routines provide powerful ways of
distinguing curves.  In general, the only reason now to do multiple calls
(using QMOVE and QLABEL) to QPICTR is to change the independent variable of
the plot.

The QPENLIST, QLINELIST, QMARKLIST, and QYLIST all take a first argument that
is described as the number of curves for which there is data.  QPICTR takes
this number and uses it to figure out how many elements to read from the array
of values that each of these Q-Functions requires.  If you give an invalid
number of curves as the first argument (i.e. too few or too many) or try to
pass a list of numbers (e.g. 0., 10., 0., 100. instead of an array) you will
probably get a 'Bus error' or 'Segmentation fault' system error message.


@chapter(Calling QPICTR from Languages Other Than Fortran)

Fortran stores the elements of an array such that the row index varies fastest
(column-major order).  Most other languages (for example, C and Pascal) store
arrays such that the column index varies fastest (row-major order).  People
calling QPICTR from languages other than Fortran must be careful to make sure
that they understand that the difference in how arrays are stored will make
Fortran appear to swap the rows and columns.  The following example shows the
results of passing two-dimensional arrays from C to Fortran:

The C program:
@begin(example)
#include <stdio.h>

main()
{
        register int i,j;
        int a[2][2];
        a[0][0] = 1;
        a[0][1] = 2;
        a[1][0] = 3;
        a[1][1] = 4;
        
        printf ("Inside C code.\n");
	printf ("Note order how the numbers ");
        printf ("increase across rows.\n");
        for (i=0; i<=1; i++) {
                for (j=0;j<=1;j++) {
                        printf ("%d\t", a[i][j]);
                        }
                printf ("\n");
                }
        printf ("\n");

        sub_ (a);
        }
@end(example)

The Fortran subroutine:
@begin(example,group)
        subroutine sub (a)
        integer a(2,2)
        write (6,*) 'Inside Fortran.'
	write (6,*) 'Note how numbers increase now.'
        write (6,*) a(1,1), a(1,2)
        write (6,*) a(2,1), a(2,2)
        return
        end
@end(example)

The Output from the above Program:
@begin(example)
Inside C code.
Note order how the numbers increase across rows.
1        2        
3        4        

  Inside Fortran.  
  Note how numbers increase now.
  1  3
  2  4
@end(example)

@chapter(Plotting Double Precision and Complex Arrays)

In addition to plotting arrays of REAL*4 numbers, QPICTR can also plot DOUBLE
PRECISION (REAL*8) and COMPLEX arrays, saving the user the trouble of copying
the numbers into a dummy REAL*4 array.  QPICTR figures out what type of data it
is dealing with by looking at the contents of the NROWS argument.  If NROWS is
negative QPICTR assumes that the ARRAY of data points is DOUBLE PRECISION.
Thus, the following methods can be used to plot the different types of arrays:
@begin(description)
REAL*4@\This is the normal way of using QPICTR.  Set NROWS to be the number
of rows in ARRAY.

DOUBLE PRECISION@\Set NROWS to be @i[minus] the number of rows in ARRAY.
QPICTR will plot the most significant portion of each element.

COMPLEX@\Set NROWS to be twice the number of rows in ARRAY.  Then, the 
REAL part of the Jth COMPLEX row of data corresponds to curve number
2*J-1.  The IMAGINARY part of the Jth COMPLEX row corresponds to curve number
2*J.
@end(description)
These methods work because of the way Fortran stores arrays of numbers.  They
are useful if you must deal with double precision or complex numbers (either
explicitly or through the use of the IMPLICIT statement) since it saves the
time and space that would be needed to copy rows of data into REAL*4 arrays.
Again, note that only the most significant portion of each data point will be
plotted.

@chapter(Using One-Dimensional Arrays)

When only one row of data is needed in a plot, it is not necessary to use a
two-dimensional array.  A one-dimensional array may be used because it
is stored the same way as a two-dimensional array with only one row.  Thus,
POINTS(200) may be used instead of POINTS(1,200) if it makes the program 
easier to understand.  In either case, NROWS should be one (1).


@chapter(Variable Numbers of Points per Curve and Singularities)

If you are cross-plotting several curves it is possible to let each
curve have a different number of points.  The usused abscissa points
should be set to 1.0E+38 since points that are off the scale of the plot
are not used.

If your curve has a singularity at some point, set the X-axis value 
near the point to be 1.0E+38.  This will make the automatic scaling
routine ignore the invalid Y-value.


@chapter(Differences Between Athena QPICTR and JCF QPICTR)

Although QPICTR was originally developed at the JCF, the version that is
used on Athena differs from the old version in several ways:

@begin(itemize)

You must call a device routine (VT125, VS100, TERMINAL, etc.) @i[before]
calling QPICTR.  This feature allows you to specify only the devices that
you wish to use.

The QPOS subroutine has been removed.  Instead, users should now use the
Penplot LOCATE routine to place their plots on the page.

The QPLOT and PICTR subroutines are not supported by Athena.

The QXSCL routine requires an array instead of a list of numbers.

The QY routine takes only ONE curve number.  To plot more than one curve
in a single call to QPICTR, use the QYLIST function.

The QCOLOR, QPENLIST, QLINELIST, and QMARKLIST functions were added by Project
Athena.

If either QXLAB or QYLAB is called but QLABEL is not, Athena QPICTR will
assume a QLABEL value of 4 (indicating that QXLAB and QYLAB should be used to
label the plot).  Under the JCF version, omitting the call to QLABEL would
cause the labels not to be plotted; the Athena version fixes this.

If QXSCL is called, but QISCL is not, Athena QPICTR will assume a QISCL value
of -2 (indicating that QXSCL should be used in scaling the plot).  Under the
JCF version, omitting the call to QISCL would cause the scaling bounds to be
ignored; the Athena version fixes this.

@end(itemize)


@chapter(QPICTR Examples)

[Must include MARKDEMO, TLOG, TQ?, and possibly TLINE]
