This page shows:
- How to draw graphs in TeX
- How to create dvi files
only for certain page ranges of a TeX document.
1. Drawing Graphs in TeX
It's not hard to draw reasonably nice graphs in TeX, without recourse
to \special's, postscript or pdf inclusions. An advantage to doing
so is that your dvi file won't need to be accompanied by
additional files, and won't need anything beyond a dvi reader
to be viewable and printable. Sometimes, as with proposals
submitted to NSF via FastLane, this can make a big difference.
(FastLane claims to accept such multiple file submissions, but
often times out while processing them, making them de facto
unacceptable. It seems to have no trouble when graphics are included
natively, as described here.) Another advantage is that any text included
in the graphic can be handled by TeX and is thus both of high quality
and completely compatible stylistically with the rest of your document's
text. A disadvantage is that the dvi files can
be relatively big. Another is that producing graphics this way
is not as flexible compared with using a true drawing program to produce
postscript.
But it may be easier to produce graphics in TeX than it is
using a drawing program, and the results aren't bad. Here's a
link
to an example figure, Lissajous.jpg, created by the routines described below.
This example required plotting 1888 individual points, plus the axes.
The text is handled in the usual way by TeX.
Creating such figures and including them in your TeX documents involves
creating the data (this can be done using a Perl program given below),
and including a few TeX commands in your TeX or LaTeX file.
Here's how. (The necessary commands are defined in the macro file
generalgraphingmacroRevised4.
Commands are also defined there for other kinds of plotting.
The command \ptplt a b plots a point at the coordinates (a, b).
The command \segplt a b c erects a vertical line segment
of height "a" at the point (b, c). This was used to plot
the following example.
This also reduces the amount of data and reduces
the size of the resulting dvi file. Finally, \rectplt a b c d
constructs a rectangle whose lower left corner is (a, b)
and whose upper right corner is (a+c, b+d).)
You must first include the file that defines the routines that will be used.
Near the beginning of the TeX file of your document (in a LaTeX file,
right before \begin{document}), put:
\input generalgraphingmacroRevised4
The file, named generalgraphingmacroRevised4 (some systems require all input files to
end in .tex, in which case it must be named generalgraphingmacroRevised4.tex),
must be put in a place your implementation of TeX can find it.
The easiest thing is to put it in the same place where the file
that calls it is (i.e., the same place as the TeX file of your document).
Here is a link to see the contents of
generalgraphingmacroRevised4,
which you can copy and save to your own copy of the file generalgraphingmacroRevised4.
At the point in your TeX document that you want to put
a figure or graph, you must put in the appropriate commands.
Here is what they were for the example Lissajous.jpg, above
(LaTeX would work the same way):
\def\mydata{polardata}
\def\xscale{100}
\def\yscale{100}
\def\xmin{-1.5}
\def\ymin{-1.5}
\def\xmax{1.5}
\def\ymax{1.5}
\penwidth1pt
\penheight1pt
\vskip1in\hskip1in\hbox{\vbox{
\parindent0in
\myput 1 1 {$x=\hbox{sin}(2t), y=\hbox{cos}(3t)$}
\putincaption 0 20 {{\bf Figure 1.} A polar curve, demonstrating
how this graphing routine works.}
\putinaxes $x$ $y$
\putinticx 5 -.3 -.3
\putinticx 5 -.6 -.6
\putinticx 5 .3 .3
\putinticx 5 .6 .6
\putinticy 5 0 .7 .7
\putinticy 5 0 -.7 -.7
\input\mydata
}}
Here's a discussion of each line:
- \def\mydata{polardata}: \mydata contains the name of the file from which the data
to be graphed is read. In this case the filename is "polardata". It should be put
where TeX can find it. Keep it with your main TeX document, for example. Also,
as mentioned before, some systems require all input files
end in .tex, in which case it would have to have been named polardata.tex.
I show below how to create the data file polardata.
- \def\xmin{-1.5}, \def\ymin{-1.5}, \def\xmax{1.5}, \def\ymax{1.5}: These define the region
\xmin <= x <= \xmax, \ymin <= y <= \ymax of the plane that will be included
in the graph. In the example here,
the graph is given parametrically by x = sin(2t), y = cos(3t), and
we will get that part of the graph which lies in the box
-1.5 <= x <= 1.5, -1.5 <= y <= 1.5 (which in fact is all of the graph).
- \def\xscale{100}, \def\yscale{100}: These define the horizontal
and vertical scale factors. You should set \xscale = width/(\xmax - \xmin)
and \yscale = height/(\ymax - \ymin), where width is the actual
width in points you want the graph to use on the page and height is the actual
height in points you want the graph to use on the page.
- WARNING: Because TeX uses integer arithmetic (TeX has no floating point) scaling which
is too large or too small won't work. Also, because there is a maximum size in pts in TeX, data
values bigger than 15000 or so don't work. When such data or scaling is needed, it can be handled
by preprocessing the data. For example, to graph data where the coordinates lie in the range
of 20000 where say the scaling factors are .01, instead in the file \mydata
change the coordinate to 2000.0 and the scale to .1.
- \penwidth1pt, \penheight1pt: When data is plotted,
each data point is actually a little rectangle. These control
the size of those rectangles. For a graph with a lot of vertical variation,
you might want to increase \penheight a bit, for example. This will make horizontal
parts of the graph a bit thicker, but also connect up the dots on vertical parts
somewhat better. (You could also modify the basic macros to make
\penwidth and \penheight functions that change, depending on what the graph is doing.
This would give better results with fewer data points, but would require making some
assumptions, on the differentiability of the data, for example.)
One thing to note is that changing the scale by \xscale or \yscale does not affect
\penwidth or \penheight, since it is often desirable for
the thickness of what is being plotted to be
independent of the scale of the graph. (A curve graphed from x=0 to x=100
shouldn't be 10 times thicker than one graphed from x=0 to x=10.) If you want
\penwidth or \penheight to scale along with everything else, you can
set the values of \penwidth or \penheight by hand.
- \vskip1in\hskip1in\hbox{\vbox{\parindent0in: These allow you to move the figure
around on the page. To move it down 2 inches, use \vskip2in; to move it over 3 inches,
use \hskip3in. The \parindent0in keeps TeX from adding extra space, as it would when it
indents a paragraph.
By the way, TeX doesn't keep track of how big the figure is.
Thus you have to put a big enough \vskip in after your figure to keep it from overlapping
text that follows the figure.
- \myput 1 1 {$x=\hbox{sin}(2t), y=\hbox{cos}(3t)$}: The command \myput allows you to
put text on your figure. The command \myput x y c puts whatever text is given in c
on the graph at coordinates (x, y). The coordinates (x, y) are not page coordinates,
but coordinates on the original graph. This gives very nice control of where
the text will be put, but it won't appear if the coordinates are outside the rectangle
which bounds the points to be plotted (given by \xmin, etc.).
- \putincaption 0 20 {{\bf Figure 1.} A polar curve, demonstrating
how this graphing routine works.}: This puts in a caption. The parameter 0 is a horizontal shift
that moves the caption left 0 points. It also widens the box containing the caption in an
attempt to keep it centered. The parameter 20 is a vertical shift
that moves the caption down 20 points. Changing this allows you to control how close to the figure
your caption will be.
- \putinaxes $x$ $y$: This puts in coordinate axes. The axes are drawn through the origin (0, 0),
so won't appear if (0, 0) is not in the region to be plotted. The parameters $x$ and $y$
can by changed to whatever names you want the axes to be given (or to {} if no name is
desired).
- \putinticx 5 .6 .6, \putinticy 5 0 .7 .7: These put in tic marks. Thus
\putinticx 5 .6 .6 puts a tic mark of height 5pt at x-coordinate x = .6, and attaches
text to the tic mark (the text in this case is also .6, given by the second .6).
The command \putinticy does the same for the vertical axis, except the first parameter,
5 in this case, now specifies the width of the tic and the second specifies the x-coordinate
of the tic (in case you want to adjust its position a little).
- \input\mydata: This reads in the data to be plotted.
Here's how I created the data in the file polardata which gave the
figure shown in Lissajous.jpg above.
Each line of the file is of the form
\ptplt -.33 -1.44837
and there is one such line for each point to be plotted. The line
\ptplt -.33 -1.44837 specifies that the point (-.33, -1.44837)
should be plotted.
If your system has perl implemented, you can use the following
perl program.
Just copy the text to a file, say makegraphdata.prl. (Under UNIX you
need to make it executable by entering at the UNIX prompt
in a terminal window "chmod 700 makegraphdata.prl";
then you can run it by entering "./makegraphdata.prl", or, depending on
how your pathnames are handled, just "makegraphdata.prl".)
This perl program writes (to standard output; i.e., to
the terminal window) one line of the form \ptplt f(i) g(i)
for each value of i from $MinParameter to $MaxParameter.
The pair (f(i), g(i)) define the graph parametrically in terms of the variable i.
For your own figure you need to write parametric equations
x = f(i), y = g(i), and determine what range i must run over.
Set the range by editing the program given here so that it assigns
appropriate values to $MinParameter and to $MaxParameter,
and so that f and g are defined as you want.
(For the lissajous figure given in my example,
the basic parametric equations I used are
f(t) = sin(2*t) and g(t) = cos(3*t).
In order to keep the file size down, I truncated decimal places
I didn't need by actually using f(t) = int(1000*sin(2*t))/1000
and g(t) = int(1000*cos(3*t))/1000. In order that the graph
included a full cycle, I chose 0 <= t <= 2Pi = 6.29,
and to get a small enough step size for good resolution,
I replaced t by t = i/300, and so used 0 <= i <= 3*629 = 1887.)
(As an another example, suppose you want to graph y = x3.
Then set f = t and y = t3. Choose an appropriate range
for t, then substitute i in for t to get a good step size. The size
you need may require trial and error, depending on how big your graph ends up
being.)
2. Controlling Page Output in TeX
There are times when it is desirable to extract from a larger
document a dvi file for certain pages only. (For example, you might
be submitting a proposal to FastLane. You might want to
have just one TeX file for the whole proposal, but FastLane requires
separate dvi files for different parts of the proposal.)
Here's how to create dvi files for given page ranges of a TeX document.
I'll give separate (but similar) macros for LaTeX and plainTeX.
In either case, the macro asks if you want to print the whole file,
or just part of it. In the first case, you get a dvi file just as if
the macro weren't there. In the second case, it will ask
you what page to start at and what page to end at. These
are physical pages (the macro can't know how you number the pages,
but it does know when each successive page is shipped out to the dvi
file). The output you get is the same as if you didn't use the macro,
except that you get the pages in the desired range only.
Note: In case of LaTeX, you should run the file a few times
under the "whole file" option, to make sure all of the internal references
and whatnot are defined correctly.
Here is the LaTeX version of the macro. Put it in your LaTeX
file right before \begin{document}:
\newcounter{spage}
\newcounter{epage}
\newcounter{abpage}
\immediate\write16{}
\message{You must process your whole file a couple}
\message{of times to resolve internal references.}
\immediate\write16{Do you want to process the whole file?(y/n)}
\message{Waiting for response ...}\read-1 to\Answer
\def\shortanswer#1#2...:.{#1}
\immediate\write16{}
\immediate\write16{}
\def\switchAy{y}
\def\switchAY{Y}
\def\noanswer{\par }
\ifx\Answer\noanswer
\message{I assume that means no, so specify your page range:}\def\switchA{n}\else
\edef\answer{\expandafter\shortanswer\Answer...:.}
\ifx\answer\switchAy
\message{I assume that means yes...}\def\switchA{y} \else
\ifx\answer\switchAY
\message{I assume that means Yes...}\def\switchA{y} \else
\message{I assume that means no, so specify your page range:}\def\switchA{n}\fi\fi\fi
\ifx\switchA\switchAy\else
\typein[\startdpage]{Enter starting page number:}
\typein[\enddpage]{Enter ending page number:}
\setcounter{spage}{\startdpage}
\setcounter{epage}{\enddpage}
\newcounter{gab}
\newbox\eatbox
\let\myshipout=\shipout
\def\noshipout{\setbox\eatbox=}%
\def\shipout{\addtocounter{gab}{1}%
\ifnum\thegab<\thespage\noshipout\else
\ifnum\thegab>\theepage\noshipout\else
\myshipout\fi\fi}\nofiles
\fi
Now here's the plainTeX version, which likewise needs to go at the beginning of your TeX file:
\newcount\gab
\newcount\startpage
\newcount\endpage
\newbox\eatbox
\global\gab0
\immediate\write16{Do you want to process the whole file?(y/n)}
\message{Waiting for response ...}\read-1 to\Answer
\def\shortanswer#1#2...:.{#1}
\immediate\write16{} \immediate\write16{}
\def\switchAy{y}
\def\switchAY{Y}
\def\switchAn{n}
\def\noanswer{\par }
\ifx\Answer\noanswer
\message{I assume that means no, so specify your page range:}\relax
\def\switchA{n}
\else
\edef\answer{\expandafter\shortanswer\Answer...:.}
\ifx\answer\switchAy
\message{I assume that means yes...}\relax
\def\switchA{y}\relax
\else
\ifx\answer\switchAY
\message{I assume that means Yes...}\relax
\def\switchA{y}\relax
\else
\message{I assume that means no, so specify your page range:}\relax
\message{Enter starting page number: }\read-1 to\startpage
\immediate\write16{}
\message{Enter ending page number: }\read-1 to\endpage
\let\myshipout=\shipout
\def\noshipout{\deadcycles0\setbox\eatbox=}%
\def\shipout{\global\advance\gab by1\relax
\ifnum\gab<\startpage\noshipout\else
\ifnum\gab>\endpage\noshipout\else
\myshipout\fi\fi}
\fi
\fi
\fi