Go to the first, previous, next, last section, table of contents.


Command Reference

This is the reference manual to SM's commands


Abort

Syntax: ABORT

ABORT closes the current device without producing any hardcopy. If you are writing an output file it will be removed. You are left talking to the null device, so you probably want to follow ABORT with a DEVICE command.


Angle

Syntax: ANGLE expr

For most purposes only the first element of the expr is used, let's call it D as it's an angle in degrees.

ANGLE will cause text from LABEL to come out D degrees anti-clockwise from horizontal. It also causes points to be rotated counter-clockwise by D degrees.

If D is non-zero it will force axis and other labels to be written with SM's internal fonts, and will overrule the tendency to put x-axis labels horizontal, and y-axis labels vertical.

For plotting points the full vector of values is used, with the point rotated by the value of expr. If more points are specified than the dimension of expr, the first element will be used for the excess.

The current value of ANGLE is (almost) always available as the variable $angle (it is one of the special variables that are affected by the DEFINE variable | command).


Apropos

Syntax: APROPOS pattern

Apropos lists all macros whose name or introductory comments match the given pattern. Probably the most common use for the command is simply to look for a word -- e.g. APROPOS histogram.

If your system supports it, APROPOS will also search the help files for the given pattern (in this case matches may not extend over more than one line). If VERBOSE is zero only the line containing the match is printed; if VERBOSE is one or more then a couple of lines on each side of the match are printed too. If the pattern matches more than once each match will be printed, merged together if appropriate and separated by line of dashes otherwise. If you use `q' to stop looking at the help files APROPOS will immediately proceed to search the macros.

The pattern is a slightly restricted version of a normal Unix regular expression, specifically:

.
Matches any character except \n.
[...]
Matches any of the characters listed in the [ ]. If the first character is a ^ it means use anything except the range specified (in any other position ^ isn't special) A range may be specified with a - (e.g. [0-9]), and if a ] is to be part of the range, it must appear first (or after the leading ^, if specified). A - may appear as the special range ---.
^
Matches only at the start of the string. Note that you must quote the ^ with an ESQ-q if you use it as your history character -- look in the index under history to learn how to change it.
$
Matches only at the end of a string.
\t
Tab
\n
Newline
\.
(any other character) simply escapes the character (e.g. \^)
*
Any number of the preceding character (or range)
?
One or more of the preceding character or range

By default searches are case insensitive, but you can make searching sensitive to case by deleting the variable case_fold_search (you can do this by putting a line case_fold_search 0 in your `.sm' file if you so desire).

The name and the comments are searched separately, so you could list all macros beginning with a, b, c, d, e, or z by saying

APROPOS ^[a-ez]

(which works because all comments start with a #), or

APROPOS "^#[^#]"

to list all macros that start with a single # (the quotes are needed to stop the #'s from being treated as comment characters).


Aspect

Syntax: ASPECT A

Set the aspect ratio (Y/X) to be A; This is used in drawing characters and points and is reset when a new DEVICE command is issued.

The current values of the x- and y- dimensions of the current device are (almost) always available as the variables $nx and $ny, and the current aspect ratio is $aspect (they are some of the special variables that are affected by the DEFINE variable | command).

If A is exactly 0, the current aspect ratio is printed -- this is equivalent to echo $aspect and is retained as a curiosity.

Usually the aspect ratio is calculated by SM to make characters look right (and to make square points square), but it is sometimes useful to override this, especially when positioning labels on graphs that will be plotted on printers of different aspect ratios.

It might be worth going through an example. Suppose that you want to make a plot that really is square when printed; how should you proceed?

The available plotting area runs from 0--32767 on each axis. So a plot set up as

location 5000 20000 5000 20000

will have the same aspect ratio as the plotting device, in general rectangular. We can write this as

define len 15000                # axis length, SCREEN units
location 5000 $(5000 + $len) 5000 $(5000 + $len)

if we feel sophisticated.

The variable $aspect tells you the Y/X ratio of the current device; so the location

location 5000 $(5000+$len) 5000 $(5000+int($len/$aspect)) box

will be a square box. Of course, you'd probably really want to say

if($aspect > 1) {
   location 5000 $(5000+int($aspect*$len)) 5000 $(5000+$len) box
} else {
   location 5000 $(5000+$len) 5000 $(5000+int($len/$aspect)) box
}

There is a problem with this; the sizes of points and labels are varied to look right with the current aspect ratio. This means that a

putlabel 5 Hello World

command that looks fine on the screen of your workstation will look awful on the printer. That's where the ASPECT command comes into play: on your workstation lie to SM and tell it that the aspect ratio is that of the printer. How do you do that? Well, the slick way is to say

macro aspect_as_device 1 {
   DEVICE $1
   define 1 $aspect
   ABORT
   DEVICE $device
   ASPECT $1
}

which assumes that you use a version of the device command that saves the current device as $device; the macro dev does this, and you can overload device to mean dev. Then you can say

aspect_as_device postport

to force the same aspect ratio as the postport device.; your plots will look ugly on the screen but beautiful when printed.


Arithmetic

Arithmetic

Arithmetic is allowed on vectors and scalars in SM, using the following operators, where expr is a expression, s_expr is a scalar expression (e.g. a number), and vector the name of a vector.

Nonary (?):

PI              Pi

Unary:

-expr           Change sign             ABS(expr)       Absolute value
ACOS(expr)      Arccosine               ASIN(expr)      Arcsine
ATAN(expr)      Arctangent              COS(expr)       Cosine
DIMEN(vector)   Dimension of a vector   EXP(expr)       Exponential
INT(expr)       Integral part           LG(expr)        Log_10
LN(expr)        Log_e                   RANDOM(s_expr)  Random numbers
SIN(expr)       Sine                    SQRT(expr)      Square root
STRING(expr)    Convert to a string     SUM(expr)       Sum_i expr_i
TAN(expr)       Tangent                 VECTOR[expr]    Elements of an array
( expr )        Raise precedence
Binary:

expr + expr          Add                expr - expr     Subtract
expr CONCAT expr     Concatenate        expr * expr     Multiply
expr / expr          Divide             expr ** expr    Exponentiate
ATAN2(expr_y,expr_x) Atan2

There are also some special operators:

HISTOGRAM(expr:expr)            Construct histogram
IMAGE(expr,expr)                Extract cross section (x, y coordinates)
IMAGE[expr,expr]                Extract cross section (x, y indices)
expr1 ? expr2 : expr3           expr2 if expr1 is true, else expr3
DO(s_expr, s_expr)              Implicit DO loop
DO(s_expr, s_expr, s_expr)      Implicit DO loop with increment

RANDOM generates a vector of s_expr random numbers in the range [0,1]. If you don't specify a seed (using SET RANDOM) one will be chosen for you based on the current time.

ATAN2 is the same as C's function of the same name, and is equivalent to ATAN(y/x). It gives a result in the range -pi -- pi dealing correctly with divisions by zero.

DO generates a range of values, e.g. set x=do(1,5) sets x to have the values 1 2 3 4 5; this is the same as set x=1,5; but set y=100 + sin(pi*do(0,10)/10) is more interesting. You can specify an increment, so do(5,1,-1) is 5 4 3 2 1.

The expression VECTOR[expr] results in a vector of the same dimension as the expr, with elements taken from VECTOR (i.e. VECTOR[INT(expr_i)]). See, for example, the macro interp. You can also use WORD([ expr [ , ... ]]) as part of an expression, where WORD is a macro taking zero or more arguments. The arguments are restricted to be either the names of vectors, strings, or numbers; I'm afraid that more general expressions are not permitted.

The precedences are what you'd expect, with ** being highest, then * and /, then + and -, and then CONCAT. The logical operators all have even lower precedence than CONCAT, and ?: has the lowest priority of all. If you have defined an image file with the IMAGE command, IMAGE(expr,expr) is an expression to extract values from your image. The two expressions give the x and y values where the image is to be sampled. For example SET x=0,1,.01 SET z=IMAGE(x,0.5) will extract a horizontal cross section through an image. As an alternative, you can use (0-based) indices to extract the values with IMAGE[expr,expr]; there are examples under IMAGE (see section Image). HISTOGRAM(expr1:expr2) constructs a histogram from a vector, where the data is in expr1, and expr2 (which must be sorted) gives the location of the bins. If the values of expr2 are equally spaced, the `location' of the bin means the centre; if they are not, a bin is defined by saying that points with value (e2[i-1] + e2[i])/2 <= x < (e2[i] + e2[i+1])/2 go into the ith bin. Note that values on bin boundaries go into the higher bin.

a ? b : c is very useful if you want to treat some value of an expression specially. You could do this with a loop but ?: is much faster; for example

set y = lg(x > 0 ? x : 1e-37)
set y = sqrt(x >=0 ? x : 0)

Due to the way that SM evaluates these expressions you may see warnings from the parts of the expressions that are not used (i.e. where the logical expression is false). You can turn down the verbosity, of course, or you could try sending mail us mail to see if we can't fix it (but it isn't easy, or else we'd have done it already).

See `Logical' for the logical operators, `Strings' for string operators, and `whatis' for finding out if strings are numbers, words, vectors, or whatever.


Axis

Syntax: AXIS A1 A2 VSMALL VBIG AX AY ALEN ILABEL ICLOCK
        AXIS A1 A2 VSMALL VBIG VLAB AX AY ALEN ILABEL ICLOCK
        AXIS A1 A2 ASMALL ABIG AX AY ALEN ILABEL ICLOCK

Makes an axis labeled from A1 to A2 at location AX, AY, length ALEN. The first form (with VSMALL and VBIG) specifies the values where you want small and big ticks explicitly; if you specify the string-valued vector VLAB it will be used to label the big ticks. The third form is more obscure: If ABIG > 0 use that for spacing of large ticks. If ASMALL < 0 make a logarithmic axis, if ASMALL = 0, do the default. (See TICKSIZE for more on the meaning of negative ASMALL and/or ABIG). If ASMALL > 0 try to use that for the spacing of small ticks.

ILABEL is 0 for no labels, 1 for labels parallel to axis, 2 for perpendicular to axis, and 3 for neither labels nor ticks. ANGLE determines the angle of the axis. If ICLOCK is even the ticks are anticlockwise on the axis, if odd they are clockwise. You usually want the ticks perpendicular to the axes, and this is what you get with ICLOCK 0 or 1; if it is 2 or 3 the ticks are vertical, and if 4 or 5 they are horizontal. The labels are always on the opposite side of the axis from the ticks.

For example, if the limits were 0 1 0 1, then the following commands would be equivalent to BOX:

AXIS 0 1 0.05 0.2 3500 3500 27500 1 0
AXIS 0 1 0.05 0.2 3500 31000 27500 0 1
ANGLE 90
AXIS 0 1 0.05 0.2 3500 3500 27500 2 1
AXIS 0 1 0.05 0.2 31000 3500 27500 0 0
ANGLE 0

(If expand is 1, that is). If you want to label the bottom axis of some plot only at prime points try

SET b={1 2 3 5 7 11 13 17 19} SET s=0,20
AXIS 0 20 s b 3500 3500 27500 1 0

If you have used LIMITS to scale the axes and LOCATION or WINDOW to move them, you could say something like

AXIS $fx1 $fx2 s b $gx1 $gy1 $($gx2-$gx1) 1 0

An example of using your own string valued labels would be:

set s=1,7,.5 set b=1,7 set labs={ O B A F G K M }
LIMITS 1 7 0 0
AXIS 0 10 s b labs 3500 3500 27500 1 0

which works as expected. If you don't have a shift key and try using lower case (obafgkm) you'll be surprised as all the letters are not at the same level (as they don't all have the same height). The easiest way to deal with this is to make them all the same height:

set labs={ o b a f g k m } + '\\strut'

(a strut is a TeXism that has the height and depth of a parenthesis; I'm afraid that you do have to escape the \ in the string). If that leaves too much space try:

set labs='\\move 100' + { o b a f g k m } + '\\strut'

I think that you get the point.

Rather than use AXIS to draw all of your axes, it may be easier to use BOX with some 3's to disable its axis-drawing habits. You'll still get a box, but no ticks or labels. For example,

LIMITS 0 1 0 10 BOX 1 2 0 3 TICKSIZE 0 0 -1 0 BOX 3 3 1 3

will label the y-axis with both linear and logarithmic axes.

This was changed in V2.1: To specify logarithmic axes you should now specify the logarithms, just as you do to BOX. For example, to draw a logarithmic axis running from 1 to 1000, specify A1 as 0 and A2 as 3, rather than 1 and 1000.

See NOTATION if you want to control the use of floating point or exponential notation. If you want your positive and negative exponents to line up define the SM variable line_up_exponents; if it's 1 they'll be padded with a space, if 2 or more, with a + (you can do this in your `.sm' file).


Box

Syntax: BOX [ INTEGER1 INTEGER2 [ INTEGER3 INTEGER4 ] ]

BOX puts axes around the plot region, labelling the lower and left according to the values set by LIMITS and TICKSIZE. If arguments INTEGER1 and INTEGER2 are included (default 1 and 2) they are used as ILABEL arguments for the lower and left axes (see AXIS). An ILABEL of 0 means to omit axis labels, 1 produces labels parallel to the axis, 2 perpendicular, 3 omits both labels and tickmarks, and 4 omits the axis entirely. INTEGER3 and INTEGER4 are used for the top and right axes.

If you want to change the font used for axis labels, define the variable default_font, either interactively (DEFINE default_font oe), or by putting a line in your `.sm' file: default_font oe. This affects regular as well as axis labels, and only works if you use TeX_strings, which we recommend anyway.

See NOTATION if you want to control the use of floating point or exponential notation.


Chdir

Syntax: CHDIR WORD

Set the current directory to be WORD, where WORD is any valid directory. It might be wise to enclose it in quotes, e.g. CHDIR "[-.more_data]", or use the cd macro. The new directory only affects SM, for example DATA or SAVE commands. When you exit SM, you will be back where you started. If the directory starts with a `~', the `~' will be replaced by the name of your home directory. This is the only place that `~' is significant; in particular it will not be recognised by the DATA command.(17)


Connect

Syntax: CONNECT WORD1 WORD2 [ IF (expr) ]

CONNECT draws line segments connecting the points in vectors WORD1 and WORD2. If the IF clause is present, only connect those points for which expr (see the section on vector arithmetic) is non-zero. Only contiguous points in the input vectors will be connected, resulting in a number of line-segments.

In fact, either or both of the WORDs may be replaced by `parenthesised expressions', i.e. expressions in parentheses. For example,

CONNECT x (2*y)

plots x against 2y.

If WORD1 and WORD2 have different dimensions CONNECT will ignore the excess points in the longer vector. If you want to plot a constant value you'll have to explicitly promote it, for example

CONNECT x (1+0*x)

which makes a rather boring plot.

To draw a line in a label you can either use CONNECT or DRAW, or use the TeX-macro \line to directly insert your line.


Contour

Syntax: CONTOUR 

Makes a contour plot of an image read by the IMAGE command (see section Image). The contour levels are set using LEVELS; plot coordinates are taken to be those set by the LIMITS command, and contours are drawn in the current LTYPE. It is not possible to produce labeled contours.

Any pixels whose value is NaN are ignored, as are any whose value equals the SM variable $missing_data; by default this is some very large number.

See also DITHER for dithering images, IMAGE CURSOR for using cursors to get values from images, MINMAX for finding the minimum and maximum of images, and Arithmetic for extracting cross-sections of images.


Ctype

Syntax: CTYPE WORD
        CTYPE INTEGER
        CTYPE = expr

With WORD, set the line colour to be WORD, if your display device supports coloured lines, where WORD must be one of default, white, black, red, green, blue, cyan, magenta, or yellow. The colours are those composed of three, zero, one, or two of the primary colours red, green, and blue. When a device is opened it sets default to some device specific value (e.g. white for xwindows, black for sunwindows).

Initially, CTYPE INTEGER is another way of selecting the same colours as are available with CTYPE WORD, where CTYPE 1 is the equivalent of the first colour listed above, or white (so default is 0). However, the CTYPE = expr command redefines the available colours to be the elements of the array given by expr. If it is arithmetic, each element of is interpreted as RED + 256*GREEN + 256^2*BLUE for the given colour, where 0 is off, and 255 corresponds to full intensity. If the expr is string-valued it specifies the names to be used for the colours that you have just defined. Any connection between the names and colours is, of course, up to you. You can get the current value of CTYPE with DEFINE ctype |.

So another way to get white lines would be to say:

CTYPE = { 0 255 0 } + 256*({ 0 255 255 } + 256*{0 255 0 })
CTYPE 1

while

CTYPE 2

would give green lines.

CTYPE ={ black white green }

would make your colour names correspond to reality again. You can use any names you like, you are certainly not restricted to the initial set.

You can reset the colours to their default (i.e. correct) values using the macro reset_ctype.

Many devices (e.g. sunview) require you to specify a number of colours that is a power of 2, so asking for 70 colours will use up 128 slots. It is probably a good idea to use as few colours as possible, as they are scarce resources on most displays. You should also be aware that the display may use some of `your' slots for the background, so specifying 63 colours on (e.g.) a sun actually requires 64 (and asking for 64 will use up 128). If you specify more colours than are physically available, or more than the device driver thinks that you deserve, SM will interpolate your values of CTYPE for you.

The default colour is specified in the device drivers, or in the DC (Default Colour) graphcap capability, and is set whenever a device is opened, so don't try to modify it with a CTYPE = expr command. You can, however, override the default colour with a foreground entry in your `.sm' file; it should be the name of a colour (as listed above). You may also be able to specify a background colour (as background). This is either a colour name or a set of three integers in the range 0-255 specifying the red, green, and blue values. We allow you this chance to specify arbitrary colours because it's your only chance to affect the background, and you can't use a CTYPE = command to compose your own palette. On some devices the name of the background colour may be chosen from a wider selection; for example if you are using Xwindows you may use any name from the colour database.


Cursor

Syntax: CURSOR 
        CURSOR WORD1 WORD2

Display the cross-hair cursor to enable you to get positions (in user coordinates). The current cursor position is typed on the screen every time that you hit a key; some keys are special, specifically you can exit the cursor routine by hitting `e' or `q'. If you exit with `e', CURSOR issues a relocate command to set the current plot position to the cursor position, and puts the command in the history buffer. If you exit with `q', no entry is made in the buffer. Usually successive positions overwrite each other, but if a digit is used to mark a point then the position is followed by a newline, so the next time you hit a key its position will appear on the next line. (You can remember that digits lead to numerous values appearing).

Many graphics devices have things called "GIN terminators". SM usually expects that this be set to `Carriage Return' with no extra characters, EOT is a popular (unacceptable) choice. If you have trouble check your graphics setup screen, then with your SM Guru who can look up in graphcap to see what is expected. If the local Guru were very friendly, he could change your GIN terminator to anything he wanted, even EOT, but he probably isn't.

The other form enables you to define a pair of vectors WORD1 and WORD2. SM provides you with a cursor, and every time that you hit a key it prints its position (just as above). If the letter is `e' or `p' it draws a point of the current type at the current position, prints the current position, and enters the (x,y) coordinates in the vectors; if you use `m' to mark a point the coordinates are not written to the screen, but the point is still added to the vectors. Exit with `q', or abort with a ^C in which case WORD1 and WORD2 are unchanged.

Note that if you want to use SPLINE on the vectors produced in this way, you should take care that at least one of the vectors is monotonic and increasing, or use the SORT command.

See also IMAGE CURSOR which returns the value under the cursor as well as the position if an IMAGE (see section Image) has been defined.

For devices with mice, if the buttons do anything, they should generate the characters `e', `p', and `q' (starting at the left). There is nothing special about `p', except that it is not `e' or `q' so it simply prints the current position.

The SunWindows cursor is slightly different. The cursor position is given by a pointing finger (it's the best we could do), and SM won't see any characters typed at the keyboard until you hit a carriage return. Device sunwindows is obsolete anyway, you should simply switch to using the sunview driver. Its cursor has a bug, in that it only sees every other character typed at the keyboard. If I knew why I'd fix it.


Data

Syntax: DATA file

Use file file as the source of data read with the READ command. The file is assumed to have numerical data in columns separated by spaces, or tabs. The range of lines specified by LINES is reset. If the file can't be opened for read, you will be warned. The variable $data_file is set to file. See the READ command to see how to read the data. You may need to quote the filename, e.g. DATA "/usr/file", which you can do by using the macro da: da /usr/file.

Perverse people who wish to use filenames such as `12' or `3.14' will find that they get syntax errors. If they must persist DATA "3.14 " will work.


Define

Syntax: DEFINE name value
        DEFINE name { value_list }
        DEFINE name < value_list >
        DEFINE name DELETE
        DEFINE name LOCAL
        DEFINE name ( expr )
        DEFINE name :
        DEFINE name |
        DEFINE name ? [ { prompt } ]
        DEFINE name ? [ < prompt > ]
        DEFINE name READ INTEGER
        DEFINE name READ INTEGER INTEGER2
        DEFINE name IMAGE
        LIST DEFINE [ begin end ]

All of these varieties of DEFINE define variable name to have some value, but as variables can be defined in all sorts of ways there are a good many possibilities.

Name is a single word starting with a letter, and containing only letters, digits, or `_', and may be a keyword. Whenever SM comes across $name, it is interpreted as a reference to variable name and $name is replaced by its value. (Note that some variables such as date are special as they always contain an up-to-date value, for an example try echo $date sometime. These variables are listed under DEFINE name |.) You can also evaluate expressions with $(expr), for example echo $(pi/2). The value can't be longer than about 80 characters, except for the value_list form in which case its length can be essentially infinite.

If you just want to know if a variable is defined, then $?name is defined to have the value 1 if name is defined, and 0 otherwise. Variables are not usually expanded within double quotes or {}, but if you use the syntax $!name the variable will be expanded within double quotes; $!!name will be expanded anywhere.

For the variants of DEFINE name value and DEFINE name value_list, value is either a word or number, or a list. The difference between using {} and <> to delimit a list is that keywords can appear within {}, but variables are not usually expanded.

DEFINE name DELETE, deletes a variable (see also the macro undef to undefine variables).

DEFINE name LOCAL, which is only allowed within macros, creates a variable which will only be visible from the current macro, and from macros called by it. Such local variables are automatically destroyed when leaving the macro within which they were created, and may not be explicitly deleted. This is similar to the behaviour of numbered variables, except that they really are local (i.e. they are only visible in the macro, and not in its descendents; SM's LOCAL variables have nested scope rather than being truly local). A common use for DEFINE LOCAL is:

   define i local
   foreach i { sorbus aucuparia } { set $i local }

to protect a FOREACH (or DO) variable, and all local vectors, in one simple line. It is because such loop variables are automatically destroyed that attempts to delete local variables are not reported at VERBOSE levels of 1 or less.

DEFINE name ( expr ) defines a variable to have the value of a (scalar) expression. When possible, it is more efficient to use vectors to perform calculations on scalars, rather than putting them into variables. It is also more efficient (and more obscure!) to use numbered variables (macro arguments) than real named ones. As a special dispensation, the expression can be an element of a string-valued vector (elements of arithmetic vectors are allowed too of course).

DEFINE name : defines the variable name from the environment file. If name can't be found, and is capitalised, SM will look for it in the environment (as a logical variable for VMS users).

DEFINE name | is used to define a variable from an internal SM variable such as expand or angle. These variables can be listed with LIST DEFINE | (or by LIST DEFINE if VERBOSE is two or more); a possibly incomplete list is: angle, aspect, ctype, date, exit_status, expand, fx1, fx2, fy1, fy2, gx1, gx2, gy1, gy2, ltype, lweight, nx, ny, ptype, sdepth, sheight, slength, distance, theta, phi, uxp, uyp, verbose, xp, and yp. The current plot limits are fx1 etc., (or gx1 etc. in device coordinates), the size of the screen (in pixels, or dots, or whatever the hardware uses) is nx * ny, the current position (in user coordinates) is (uxp,uyp) , the current position (in plot coordinates) is (xp,yp), exit_status is the return code from the last ! command, sdepth, sheight, and slength are the depth, height, and length of the last string drawn to the screen, distance, theta, and phi are the viewpoint for surface plots (see section Viewpoint), and the rest should be obvious.

This sort of variable changed a little with version 2.1.1. The variables that you can use have not changed, but their usage has slightly. They are all defined for you when SM starts and each is always correct, tracking the current value of the corresponding internal variable. For example, try echo $angle\n angle 45 echo $angle. If you now say define angle |, $angle will cease to track the internal value and will remain fixed (the same effect can be achieved with define angle 45). When you say define angle delete it will once more track the internal value. Your old code will continue to work, but in many cases it is possible to remove the explicit definition with |. This special sort of variable will not be SAVEd, and will not show up if you list the currently defined variables (unless VERBOSE is two or more).

DEFINE name ? will prompt you for the value of name at the keyboard, using the prompt string if given, otherwise the name of the variable. The old value of the variable (if defined) is printed within [], and is taken to be the default if you simply hit carriage return. As previously discussed, the difference between {} and <> is in the treatment of keywords and variables. If you don't want to use {} (probably because of something weird to do with when variables are expanded), you can always use quotes within <>.

The versions of the DEFINE command including READ define variables from the current data file. DEFINE name READ INTEGER sets name to be line INTEGER of the current data file, while DEFINE name READ INTEGER INTEGER2 defines name to be word INTEGER2 of line INTEGER. name is subject to the usual restrictions. If the line begins with a # the first character is simply ignored when defining variables.

DEFINE name IMAGE defines a variable from a file read with the IMAGE or TABLE command. Currently this only works for NX, NY, X0, X1, Y0, Y1, or any keyword from a FITS header.

LIST DEFINE lists all currently defined variables, or all those which are between begin and end alphabetically (asciily).

Examples




DEFINE v1 5.993
DEFINE label1 KPNO
DEFINE label1 < National Optical Astronomical Observatory > 
DEFINE v2 ($v1 + 3.4)
DEFINE v1 DELETE
DEFINE age ? { How old are you? }
DEFINE macros : WRITE STANDARD "$!macros"

(Note that we couldn't have used <> to prompt for your age, because then the ? after you would be treated as a keyword).

To illustrate the DEFINE name READ commands, consider a file with the following lines:

This is a file containing astronomical data
Magnitude  Intensity  Wavelength  Error

Then using the DEFINE commands as follows:

DEFINE title READ 1
DEFINE labelx READ 2 3

will assign the string This is a file containing astronomical data to the variable title, and the word Wavelength to the variable labelx, so you can say XLABEL $labelx.


Delete

Syntax: DELETE [ INTEGER1 [ INTEGER2 ] ]
        DELETE HISTORY [ ! ]
        DELETE HISTORY [ INTEGER1 [ INTEGER2 ] ]
        DELETE WORD

Delete commands INTEGER1 to INTEGER2 (inclusive) from the history buffer. If the INTEGERs are not present, delete the last command. DELETE 0 will delete all history commands. If the INTEGERs are negative they are interpreted relative to the current command, so -1 is the last command.

The DELETE HISTORY commands are identical to the DELETE commands, except they themselves do appear on the history list; they are preserved for backwards compatibility and because DELETE HISTORY \n can be used to prevent a command from appearing on the history list (the macro del1). If a macro contains a DELETE HISTORY, or calls a macro that contains one, or ... the macro will not appear on the history list. Traditionally, this meant that if there were two (or more) occurrences of DELETE HISTORY the previous command(s) were also be deleted, but in SM version 2.2.1 this has been changed, and DELETE HISTORY will only delete the last command typed at the keyboard. If for some nefarious purpose you really do want to delete older commands too, you can say DELETE HISTORY ! and the command will work the old way.

DELETE WORD deletes the vector WORD (see SET WORD or READ WORD for how to define vectors), MACRO name DELETE is used to delete a macro, DEFINE name DELETE deletes a variable.


Device

Syntax: DEVICE WORD [ rest_of_line ]
        DEVICE INTEGER [ WORD ] [ rest_of_line ]
        DEVICE META WORD
        DEVICE META CLOSE

(The DEVICE INTEGER form is retained for historical interest and backwards compatibility only.)

Choose a device to plot to. Exactly which devices are available depends on your hardware configuration and how SM was compiled. You can list available devices with the LIST DEVICE command (see section List). When you specify a device the previous device is closed, which may lead to some action being taken (for example, sending a plot to a printer).

When a device is opened it is looked up by name in the `graphcap' file (see section The Stdgraph Graphics Kernel). In some cases all the information that SM needs to plot to the device is available there (for example xterm or postscript); such devices are referred to as stdgraph devices. Otherwise the graphcap entry will contain the name of the real device driver, for example x11. Anything else on the line is passed to the device driver. In particular, for the stdgraph devices an argument that is not specifically processed by the device is taken to be the name of a file to save the plot in. Thus device postscript foo.ps creates a plot in a file called `foo.ps'(18)

The pseudo-device META is special, See section Meta. It is used to support metafiles, which allow you to save a plot as you display it, and finally send it to a different device.

Especially for hardcopy devices, you may have to specify which one you want, e.g. DEVICE postscript latypus. Because this depends on how your local graphcap was configured, you'll have to see your Guru for guidance; See section The Stdgraph Graphics Kernel.

When a device is opened, it is set to the current CTYPE, LWEIGHT, and LTYPE, and the proper aspect ratio is chosen to make text and plotted points look nice. It also looks for an entry foreground in your `.sm' file, and uses it as the default colour for the device (this overrides any default that the device driver may have specified). The device driver may (or may not) choose to honour a background entry as well. These colours may be specified either as names (see CTYPE), or the background colour may be given as a set of three numbers, which are interpreted as the red, green, and blue intensities in the range 0 - 255. Some devices may allow you a wider selection of background names; for example the Xwindows driver allows any name from the colour database.

If you want to use some foreground colour that CTYPE doesn't usually understand you must define it before opening the device. For example, after defining the macro

add_colour 4 ## add a colour to the standard set. Usage: name r g b
             CTYPE=<0 255 0 255 0 0 0 255 255 $2> + \
                 256*(<0 255 0 0 255 0 255 0 255 $3> + \
                       256*<0 255 0 0 0 255 255 255 0 $4>)
             ctype=<default white black red green blue cyan magenta yellow $1>

you could say add_colour gray 200 200 200, after which `gray' would be a perfectly good `foreground' colour.

Different ways of plotting to the same device (e.g. portrait or landscape) are accommodated by using different drivers (e.g. postport and postland for postscript devices) rather than some magic command to SM.

The NULL device

DEVICE nodevice is always available; it is a bit bucket where plot commands may be sent never to be seen again, the equivalent of /dev/null (under unix) or nl: under VMS.

It is useful because it is always available; it's the current device when SM is started. Because SM submits plots only when the current device is closed, and because opening nodevice closes the current device, it is also used by the hardcopy command (in fact hardcopy is a macro that expands to DEVICE nodevice).

Borland Graphics on a PC

SM works on a PC running DOS either by using Borland's graphics or windows (see the section on MS-Windows); this section describes the former. SM was ported to run under DOS by Laurent Bartholdi, who also wrote the BGI and MS-Windows device drivers. He gets all the credit for the PC version of SM, but of course he is not responsible for any remaining bugs (some of which we almost certainly created while merging the PC and regular versions).

The graphics drivers, the `.bgi' files, are assumed to be in a directory given by the DOS BGIPATH environment variable; alternatively you can specify a bgipath variable in your `.sm' file.

The DEVICE command takes two optional arguments: DEVICE bgi devtype mode. The first, devtype, is the type of hardware that you are running. If you want the driver to try to figure this out for itself, use DEVICE bgi detect (this is the default if you omit devtype entirely); for a listing of possibilities say DEVICE bgi ?. The second argument, mode, determines how SM switches between screen and graphics modes. Your options are none, swap (the default), or switch; experiment to see which works better for you. At present, a certain amount of `snow' is left at the top of the graphics screen. This is very dependent on the details of your graphics card, and we see no general way to prevent its appearance.

Once you have decided what options you like best, you can set a variable stdmode in your `.sm' file (e.g. to detect swap) to save yourself some typing.

There is a `hot key', ALT-F1, that can be used to toggle between text and graphics mode.

The current return value of the function coreleft is available as $coreleft (which is like any other DEFINE var | variable).

OS/2 Presentation Manager

The OS2PM driver is used to display graphics in a Presentation Manger graphics window under OS/2 v2.x (you should specify your terminal as os2pc). Two optional arguments are currently supported:

-n
Disable all backing for the graphics window. This will significantly increase the drawing speed, but the contents of the graphics window will not be redrawn when portions of the window are uncovered or when the window is resized.
-gWxH
Specify the window geometry. The W and H parameters should contains the WIDTH and HEIGHT of the graphics window in pixels.

If DEVICE os2pm is specified without the -gWxH argument the graphics window will be created the same size as the last previously displayed window. If this is the first time the graphics window is created it will default to 600 x 400 pixels.

For example,

     DEVICE os2pm -g800x500
          .
          .
          .
     DEVICE os2pm -n

The first DEVICE statement will produce an 800 x 500 pixel graphics window with backing enabled. The second will again produce an 800 x 500 pixel window but with no backing.

Graphics Metafiles

As described elsewhere (see section Meta) SM can save graphics commands to a metafile while producing a plot on your screen.

Postscript Devices

Strictly speaking, there are no postscript devices, merely postscript drivers in stdgraph (see section The Stdgraph Graphics Kernel). On the other hand, SM is able to drive postscript printers in a totally transparent way, so a user can think of SM's postscript capability as discrete drivers. In the following descriptions the arguments to the device command are referred to as $1, $2, and so on. Aliases are listed in parentheses after the device name, so post_colour can also be called post_color. Those currently supported are:

postscript (POSTSCRIPT)
The basic driver; produces 8x8inch output on the default printer.
postport (POSTPORT)
A full-page portrait-mode plot.
postland (POSTLAND)
A full-page landscape-mode plot.
post_colour (post_color)
Like postscript, but generates a colour postscript plot, and sends it to a printer called ps_colour0.
blackpostscript
Like post_colour, but uses a black background.
postfile (postencap)
Like postscript, but generate an encapsulated postscript file in $1.
postlandfile
Like postland, but generate an encapsulated postscript file in $1.
post_remote (postscript_remote)
Like postscript, but prints to a printer $2 on host $1.
postland_remote
Like postscript, but prints to a printer $2 on host $1.
postport_remote
Like postport, but prints to a printer $2 on host $1.

For an example of defining your own postscript device that takes a printer name as an argument, See section The Stdgraph Graphics Kernel.

The Silicon Graphics (and RS-6000) Device

The Silicon Graphics device driver works. If you read this and want more documentation, send mail to us and we'll get to it.

The General Device Driver, using Graphcap

By far the majority of devices that SM supports are driven through the stdgraph device; a partial list includes tek4010, tek4012, pericom, selanar, (or hirez ), versaterm (or macvt ), vt640 (a vt100 with retrographics ), vt240 in REGIS mode, hard4012 or hard4010 for a tek4010 that really has no decent ascii mode, tek4025, wyse1575, cit414a or 414a. We also support graphcap drivers for Postscript, QMS, and LN03 laser printers, (device names postscript, qms and ln03). Stdgraph can also cooperate with raster devices, for instance to plot on a lineprinter.

For the stdgraph (i.e. default) device driver the final word on the command line (if present) is taken to be the name of a file to receive the output that would ordinarily go to the screen, so if you say

device graphon outfile

and then create a plot nothing will seem to happen. However, if you close the device and write `outfile' to the terminal (maybe using /passall if you are running VMS) your plot will appear. In addition, any word beginning with a colon will be taken to be part of a graphcap entry (see section The Stdgraph Graphics Kernel), and prepended to the entry in the graphcap file for your chosen device. For example, if you wanted to save your postscript output in a file you could say

dev postscript ":SY=echo File is $F:"

which would replace the SY entry that sent the output to the printer by a new one that merely tells you what the file is called. If you'd prefer to give it a memorable name, you could say

dev postscript ":SY=echo File is \$F:OF=name:"

or

dev postscript :SY@: :OF@: name

(it doesn't matter if the entries are all in the same word). The former redefines the output file OF to be "name", and makes SY tell you so. The latter disables both OF and SY, so the generated postscript would ordinarily go to the terminal (just like any other graphics terminal), but a file `name' is specified, so the output is sent there instead.

If you find yourself frequently wanting to use a customised stdgraph device, this mechanism can become rather tedious; you'd rather simply invent the device and be done with it. The proper way to do this is to create a local graphcap file (see section The Graphcap File), and add your new device to it. For example, if you wanted to define a postscript device that took the name of the printer as its argument, you'd put an entry

mypostscript|like postscript, but specify the printer as its argument:\
        :SY=lpr -r -P$1 $F:TC=postscript:

in your file, and merrily proceed with making beautiful plots using DEVICE mypostscript fred. If you always want to use your new device you could call it postscript and in effect redefine the old postscript device (note carefully that I said :TC=postscript: not :tc=postscript:; if I hadn't, an infinite loop would have resulted).

The SunView (and Sunwindows) Devices

As the sunwindows driver is now obsolete, and may well disappear in some future release, you should use the sunview driver instead. If you insist on using the old driver, it must be run from within a gfxtool.

The SunView window driver supports a subset of the usual SunView command line arguments, specifically:

-WH
Summarise options
-Wi
Open window as an icon
-Wl label
Specify label for the window (default: SM)
-Wn
Don't label window
-WP x y
Position of icon
-Wp x y
Position of window -Ws w h Size of window

The standard SunView popup `frame' menu has been modified to allow you to erase the graphics screen. It is perfectly safe to use the menu to quit the graphics window, in this case the next device sunview command will create a new one. If SM thinks that the window is active when you try to kill it, it will warn you; failing to believe it may result in a cascade of complaints to the console window. There is a bug in the cursor routine (I claim that it is a SunView bug) that means that SM sees only every other key-stroke.

The Unix-PC Device

On a Unix-PC DEVICE upc opens a window of 304 by 192 pixels, which is about 4 by 4 inches. To quote the author (Peter Teuben, teuben@astro.umd.edu),

  1. This whole Unixpc version is an experimental version, take it as is, it works on my configuration, but may not work on yours.
  2. I'm playing with allowing a second and third parameter to the upc device name, which would allow you to change the default size of 304 by 192 pixels (The size in X must be a multiple of 16 though). Right now I have it check environment variables YAPP_X and YAPP_Y, but this may not work satisfactorily.
  3. I spawn windows using the public domain program `wlogin', this may be of some importance if your `upc' device in SM fails.

I don't have a Unix PC, so I can't work on this driver.

PC Graphics under MS-Windows

This section needs more work; send mail to rhl@astro.princeton.edu.

VAX/VMS UIS$ device

the VAXUIS driver is used to display graphics on a VAX Workstation using the VAX UIS$ library routines. The optional X and Y parameters specify the size of the graphics window ( in centimeters ) created on the workstation screen.

If called without the optional X and Y parameters the graphics display window will be the same size as that previously displayed.

If the X and Y parameters are not specified the first time the DEVICE vaxuis command is issued, the graphics display window will occupy 1/2 the height and 1/2 the width of the workstation screen.

For example, to create a 15 cm wide x 10 cm tall display window say:

		DEVICE vaxuis 15 10

The X-Windows Devices (X10 and X11)

There are two X-Windows drivers, one for X10 and one for X11 and they differ in their treatment of command line arguments. The X11 driver is considerably more sophisticated and will be treated first.

The X11 window driver (device x11) supports a subset of the standard command line arguments, specifically (the X-resources names appear in parentheses at the ends of the descriptions):

#geom
Specify icon geometry (.icongeometry)
-bd n
Border width (.borderwidth)
-bg colour
Background colour (.background)
-display name
Name of display to open (.display)
-fg colour
Foreground colour (.foreground)
-fn fontname
Name of hardware font to use (.font)
-geometry geom
Specify window geometry (.geometry)
-help
Summarise options
-kbdfocus
Preserve keyboard focus (the same as -focus). Without this, some window managers transfer focus to the graphics window when it is created; probably not what you want (.kbdfocus)
-iconic
Open window as an icon (.iconic)
-name name
-nocurswind
Do not show the cursor position while in cursor mode (same as -nocw) Specify name of window (.name)
-preopened display_id:window_id
Specify device and window id's
-synchronise
Synchronise with server (debugging only) (.synchronise)
-title title
Specify title of window (.title)

Where geom is a standard geometry string of the form WxH+-X+-Y, and the preopened option is for a programme calling SM non-interactively. All options may be abbreviated, so

device x11 -i #-1+1 -g 512x512+100+100

specifies that the graphics window be created as an icon in the top right hand corner of the screen, and that the real window should be 512*512 and positioned near the top left corner.

SM is not currently able to open more than one x11 device.

If you want to raise your graphics window so that you can see it, you can either use the window manager, reopen the device (dev x11), erase the screen, or use the PAGE command.

On hardware that doesn't support a backing store (or if you have chosen to disable a backing store when compiling the X11 driver) the screen will only be refreshed when it is active or when SM is waiting for input. If your operating system doesn't support the select() system call you may be even worse off, but reopening the device (device x11) should still result in the screen being redrawn.

The X10 driver is known as xwindow, and you can optionally specify a device to open, and a window ID, on the command line. For example

device xwindows DEVICE unix:0

will open a graphics window on device unix:0. (You can optionally include a ID number after the DEVICE if you are calling SM from a programme, and have already opened the window). The X10 driver doesn't bother to remember any hardware characters that you may have written on a graph, so that if you refresh the window they won't appear. If this worries you can, as always, force the software character set with an expand 1.001.


Dither

Syntax: DITHER x y min max fac

Generates a dithered represention of an image read by the IMAGE command (see section Image). The vectors x and y are set to points whose density is proportional to the image's intensity (only values between min and max are considered).

Any pixels whose value is NaN are ignored, as are any whose value equals the SM variable $missing_data; by default this is some very large number.

The dithering algorithm used is Floyd-Steinberg, and each pixel of the image is represented by (up to) fac*fac points, where (of course) all fac*fac points are only used for intensities greater than equal to max. Even the case fac == 1 can produce nice output for suitably sampled images.

The resulting vectors are usually plotted as ptype 1 1.

An example of dithering an image would be:

IMAGE image_file
DITHER x y 0 3000 4
PTYPE 1 1
POINTS x y

Of course, you can be more sophisticated; for example:

define min 3000  define max 60000  define gamma 2
set ii = image[*,*]
set ii=(ii < $min ? 0 : ii > $max ? 1 : (ii-$min)/($max - $min)
set image[*,*] = (1 + $gamma)*ii/(1 + $gamma*ii)
dither x y 0 1 4
define v local foreach v (x y) {
   set $v=$v + 0.5*random(dimen($v))
}
POINTS x y

or

DITHER x y 0 3000 1
expand 0.3 + IMAGE(x,y)/3000
PTYPE 4 3
POINTS x y

See also IMAGE for reading images, CONTOUR for contouring them, IMAGE CURSOR for using cursors to get values from images, MINMAX for finding the minimum and maximum of images, and Arithmetic for extracting cross-sections of images.


Do

Syntax: DO variable = start, end [ , incr ] { commands }

While the value of $variable runs from start to end, the commands are executed. The optional increment defaults to 1. It is not possible to change the value of the loop variable inside a loop (or at least it has no effect on the next iteration). To break out of a loop you have to break out of the current macro as well with RETURN (see section DO and FOREACH loops, and IF statements).

For example,

DO i=1,10,0.5 { WRITE STANDARD $i } 

will write 1 1.5 2 2.5 ... 10 to the terminal. The commands may be spread over several lines.


Dot

Syntax: DOT 

Draw a point at the current location (set by RELOCATE, DRAW, etc.) in the style determined by PTYPE. The point's size and rotation are governed by EXPAND and ANGLE.

To insert dots into labels, it may be easier to use the `TeX' definition \point or \apoint which inserts a dot of a specified PTYPE into a string (see section SM's Fonts).


Draw

Syntax: DRAW #1 #2
        DRAW ( #1 #2 )

Draw a line from the current position (set with, for example RELOCATE) to (#1, #2) in user coordinates. If the parentheses are present, use screen coordinates.


Edit

Syntax: EDIT function key_strokes 

Bind a function to a set of key_strokes for the editor. For example, EDIT refresh ^R makes the ^R key refresh the screen. A complete list of functions is given in the `Changing Key-Bindings' section in the main part of this manual (see under `bindings' in the index). Each character in the key sequence can be specified as a character, e.g. `a' or the single character `^A', as `^c' representing the single character ^c as the two character sequence `^' followed by `c', or by `\nnn' where nnn is an octal number (e.g. EDIT refresh \022).

In order to use multiple key sequences (e.g. ^A^B^C) you must first undefine any sub-sequences, in this case ^A and ^A^B, by making them illegal -- EDIT illegal ^A.

See READ for how to define a set of keys from a file, and KEY for how to define keys to execute commands.


Environment Variables

Environment (`sm') Variables

SM environment variables are defined in `.sm' files, which are searched for along a path which typically consists of the current directory, your home directory, and then some system place. You can specify your own search path by setting the environment (VMS: logical) variable SMPATH. If ~ appears in a path it is interpreted as your home directory unless you specified -u NAME when starting SM, in which case it will be interpreted as NAME's home directory instead. Alternatively, you can specify the name of the environment file using the `-f' flag on the command line; if it starts with a `/' it will be taken to be an absolute path name, otherwise it will be taken relative to the current path.

If you invoke SM with the -f or -u flags, the are not passed on to raster devices, so if you plot to a device that invokes rasterise it will use the .sm files specified by $SMPATH.

Each line of the files is taken to consist of a variable name, and the rest of the line which is taken to be its value. Any variable may be accessed using the DEFINE name : command, which defines name from the environment file.

Comments run from `#' to the end of the line. If the first character of a line is a `@' or `+' the name is taken to start with the second character. A `@' means that the entry isn't present, and that SM should stop searching the path for it. A `+' means that SM should keep on searching the current `.sm' file, and then the rest of the search path, looking for more entries with the same name. If it finds one, the second value is added to the end of the first (and if the second occurrence also had a `+' specified the search continues).

Some entries in the environment file are special to SM, although you are free to use them to your own ends as well. For most of those for which SM is only interested in whether the variable is defined, a value of 0 means that it shouldn't be defined. The variables are:

background
The background colour for plots
case_fold_search
If non-zero, make searches case insensitive
default_font
The default font for labels
device
Your initial graphics device
edit
A file of keybindings to read (see section Changing Key-Bindings).
fan_compress
Apply fan compression when connecting lines. This was donated by a user, and is intended to reduce the number of lines actually plotted to the device; whether it is useful is not clear. The reference is IEEE Computer Graphics and Applications, March 1989, `Faster Plots by Fan Data-Compression', by R.A. Fowell and D.D. McNeil.
file_type
The type of 2-D image for the IMAGE command
filecap
The filecap file to use (default: same as graphcap)
line_up_exponents
Force an extra space before single-digit exponents in axis labels
fonts
The name of the binary fonts file
foreground
The foreground colour for plots
graphcap
The graphcap file to use
help
The help directory
history
The length of the history list (default: 80)
history_char
The character used to recall commands (default: ^)
history_file
File to save history in
macro
The default macro directory
macro2
Your private macro directory
missing_macro_continue
If defined, a reference to a missing macro isn't a syntax error
name
The name SM calls you by
noclobber
Refuse to overwrite existing files with MACRO WRITE or PRINT.
overload
If non-zero, overload some commands
printer
The default printer (see hcopy and hmacro)
prompt
The initial value of SM's prompt
prompt2
The initial value of SM's secondary prompt
remember_history_line
Remember which line you last reused
save_file
Default file to save a SM session in
save_read_ptr
Save the position of the read pointer between READ commands
temp_dir
The directory for temporary files
term
Default terminal, over-ruling TERM
termcap
The file describing terminals to SM
TeX_strings
Use TeX-style strings for labels
traceback
Print the macro stack following an error
uppercase
Define uppercase versions of some macros
x_gutter
y_gutter
Modify the spacing between windows when using the WINDOW command. (These are not actually read from the `.sm' by the default startup macro, you have to set them yourself).

Under Unix, you should omit the termcap entry, or point it at `/etc/termcap'. Also under Unix, SM knows how to look up your name, so you can omit the name entry. If you try to use a name with more than one word, SM will use the first so you'll have to call yourself `my_lord' rather than `my lord' (the `_' will be replaced by a space).

Some of these are used directly by SM (e.g. help, fonts, but some are merely used by the startup macro to set the initial value of SM variables (e.g. TeX_strings, file_type). Other names may be used by the default startup macro, e.g. macro2 to specify a private macro directory or term to specify the terminal that you are using. See the discussion of startup under `useful macros'.


Erase

Syntax: ERASE 

ERASE erases the graphics screen. The macro era erases the screen without appearing on the history buffer. If you want to start a new output page on a hardcopy device use the PAGE command.

You may be able to erase individual lines with LTYPE ERASE, if you can you should look at the macro undo.


Errorbar

Syntax: ERRORBAR WORD1 WORD2 expr INTEGER

ERRORBAR is analogous to POINTS; it draws one-sided error bars on all points defined by vectors WORD1 and WORD2, where the length of each errorbar is set by the corresponding value in expr. INTEGER is 1 to put the bar along the +x direction, 2 for +y, 3 for -x, and 4 for -y. Use EXPAND to govern the size of the caps. In fact, instead of either or both of WORD1 and WORD2 you can use an expression in parentheses, for example ERRORBAR (lg(x)) (lg(y)) 120 1.

See also the macros ec and err for backwards compatibility with Mongo, and error_x and error_y to produce (symmetrical) two-sided errorbars. There is also a macro logerr to draw errorbars on logarithmic plots.


Expand

Syntax: EXPAND expr

EXPAND expands all characters and points, its default is 1.0. Note that the EXPAND factor is used in determining the plot window size in the WINDOW command. This means you should declare your EXPAND size to SM (if other than the default) before you use WINDOW. The current value of EXPAND is available as a DEFINE expand |.

If EXPAND is set to exactly 1, and ANGLE is exactly 0, then SM will use hardware fonts, when available, in writing labels. This is faster, but if you don't like it say "EXPAND 1.00001", or "ANGLE 0.00001", or use a \r explicitly to select the roman font.

EXPAND can in fact be given a vector of values, which are used for each point in a POINTS command. This supersedes the use of a fractional PTYPE (although we still support it as a quaint anachronism). Using vectors for both ANGLE and EXPAND makes it easy to draw a vector field, see (for example) the vfield macro. If more points are specified than the dimension of expr, the first element will be used for the excess.


Fft

Syntax: FFT n pexpr1 pexpr2 WORD1 WORD

Fourier transform 2 vectors (treated as the real and imaginary parts of a complex vector), returning the answer in the two vectors WORD1 and WORD2. The input vectors may be the names of vectors or expressions in parentheses. The direction is specified by n, either +1 for a forward transform, or -1 for an inverse.

The dimension of the vectors need not be a power of 2, but the transform is more efficient if it is. The worst case is when n is prime, in which case this command performs a slow Fourier transform in O(n^2) time.


Foreach

Syntax: FOREACH variable ( list ) { commands }
        FOREACH variable { list } { commands }
        FOREACH variable WORD { commands }

In the first two forms, the value of variable is set to each element of list in turn, and then the commands are executed. An example would be

var ( alpha 2 gamma ) { WRITE STANDARD $var }

which would write alpha, 2, and then gamma to the terminal (see section DO and FOREACH loops, and IF statements).

The form with {} can be useful if you want the list exactly as you type it, for example

	FOREACH f { 0.1 $date } { echo $f }

The form FOREACH variable WORD ... is used to iterate over a vector, either arithmetic or string. For example,

        SET str={Sorbus Aucuparia David Monger}
	FOREACH f str { echo $f }

It is often useful to define the FOREACH variable to be LOCAL (see section Define), e.g. DEFINE f LOCAL in the last example.


Format

Syntax: FORMAT [ x-format-string y-format-string ]

Allow the user to specify the axis tick label formats. The format should be given as a standard C (e.g. %4.1g) or Fortran (e.g. F10.4). This format will be in effect until unset by issuing the FORMAT command with no argument, in which case SM will figure out the best format for you, or until you issue a new FORMAT command with new format strings.

If a format is specified as "0", the format string is left unchanged; if it is given as "1", the default value is reinstated. The command FORMAT 1 1 is thus equivalent to FORMAT.


Grid

Syntax: GRID [ INTEGER1 [ INTEGER2 ] ]

Grid draws a grid at either major ( INTEGER1 = 0 ) or minor ( INTEGER1 = 1 ) tickmarks within a box. The default is INTEGER1 = 0. You can use INTEGER2 to specify only drawing an x- or y-axis grid: if INTEGER2 is omitted or 0, draw both x and y; if it's 1 only draw x; if it's 2 only draw y (3 is equivalent to 0).


Help

Syntax: HELP [ word ]

The HELP command tries to help you with word. If possible, it prints the entry from the help directory specified in your `.sm' file, the definition of word if it's a macro, the value of word if it's a variable, and the HELP string if it is a vector. If none of these are defined, HELP confesses defeat. You might want to use the abbreviation h which will not appear on your history list (or you could overload help itself). Further discussion of the HELP command is given in See section The Help Command.

If word is omitted it is assumed to be HELP.

You can associate a help string with a vector with the command SET HELP.

See also APROPOS and LIST.


Histogram

Syntax: HISTOGRAM WORD1 WORD2 [ IF (expr) ]

HISTOGRAM connects the points in vectors WORD1 and WORD2 as a histogram. The ith bin of the histogram is taken to run from (x[i-1] + x[i])/2 to (x[i] + x[i+1])/2; for the case of equally spaced x-values, this reduces to saying that the x values are the bin centres.

If the IF clause is present, only use those points for which expr (see the section on vector arithmetic) is true (i.e. non-zero).

In fact, either or both of the WORDs may be replaced by `parenthesised expressions', i.e. expressions in parentheses. For example,

HISTOGRAM x (2 + y)

to plot x against 2 + y. There is a macro barhist for drawing bar charts. See Arithmetic for how to convert vectors of data into histograms, and SHADE for how to shade them.


History

Syntax: HISTORY [ - ]

List the current commands stored in the buffer. For details on the history system, see section Command History. With the optional minus sign, the history list is printed backwards which is probably what you want if you are thinking of it as a set of commands to repeat. It's possible to overload list to be a synonym for HISTORY, see `overloading' in the index.


Identification

Syntax: IDENTIFICATION str

IDENTIFICATION puts the current date and time followed by str outside the upper right hand corner of the plot region. (Actually, identification is a macro, which RELOCATEs to a point above the right-hand axis, and half way between the top axis and the top of the page, and then writes a string with a PUTLABEL 4.) Note that the variable $data_file is set to the name of the current data file, and $date always expands to the current date and time.


If

Syntax: IF ( expr ) { list } 
        IF ( expr ) { list } ELSE { list } 

If the expr is true (non-zero), then the list of commands are executed, otherwise the ELSE clause is executed. For various complicated reasons, the ELSEless command must end with a newline (or as usual a \n) (see section DO and FOREACH loops, and IF statements). One common use for IF tests is when the expression tests if a variable has been defined, e.g.

IF($?file_name == 0) { DEFINE file_name ? } 

within some macro.

There are also commands using IF to define vectors conditionally (see SET), and to plot parts of vectors (See CONNECT, HISTOGRAM, POINTS).


Image

Syntax: IMAGE file
        IMAGE file xmin xmax ymin ymax
        IMAGE ( nx , ny )
        IMAGE ( nx , ny ) xmin xmax ymin ymax
        IMAGE CURSOR
        IMAGE CURSOR WORD WORD WORD
        IMAGE DELETE

Read an image from file, optionally specifying the range of coordinates covered by the data values. If you do not specify them they will be taken to be 0 nx-1 0 ny-1 where nx and ny are the dimensions of the image. If you specify ( nx, ny ) instead of a filename an empty image of the desired size will be created (see section Two-Dimensional Graphics).

IMAGE CURSOR is identical to the CURSOR command (see section Cursor), except that value of the image under the cursor is returned in addition to the position; IMAGE CURSOR WORD WORD WORD is equivalent to CURSOR WORD WORD, but it also generates a vector of image intensities.

IMAGE DELETE will forget the current image and levels.

The file format is specified using a `filecap' file, similar to `graphcap', and the entry to use in this file is given by the variable file_type (see section Two-Dimensional Graphics). The file is unformatted, and should start with two integers giving the dimensions of the data array, followed by the data values written row by row.

The current entries in `filecap' support files written from C, or from fortran in one of a variety of ways. For C programmers, DEFINE file_type C, the file should be written with open/write/close. For Fortran, there are a variety of options depending on operating systems and the details of how the file was opened. Under Unix, simply DEFINE file_type unix. Under VMS you have a choice. You can either create a variable record type file (recordtype='variable' in the OPEN statement) and choose file_type vms_var, or set recordtype='fixed' choose recl to be the x-dimension of the array and define file_type to be vms_fixed. You must set recordtype in one of these two ways. By default, data is taken to be real (float in C), but this can be overridden in the filecap entry for a file type. There is also an entry for FITS files (FITS is the `standard' image transport format for astronomical images). If you want to use a different file type you'll have to learn about `filecap' (see section Two-Dimensional Graphics), or else see your local SM Guru.

So under VMS either your code should look like (file_type = vms_var)

        integer i,j
        real arr(100,10)
c
        open(2,file=filename,form='unformatted',recordtype='variable')
        i = 100
        j = 10
c now write your data into arr
        write(2) i,j
        write(2) arr
        end

or, with file_type = vms_fixed,

        integer i,j
        real arr(100,10)
c
        open(2,file=filename,form='unformatted',recl=100,recordtype='fixed')
        i = 100
        j = 10
c write your data into arr here
        write(2) i,j
        do 1 j=1,10
           write(2) (arr(i,j),i=1,100)
1       continue
        end

Under Unix, either of these programme fragments would work after omitting the record information from the open statement.

For an example of creating an image from scratch (or from a vector), See section Set.

If you have an image defined (using the IMAGE command), you can extract a cross-section using the SET name = IMAGE ( expr , expr ) command. The two expressions give the (x,y) coordinates where you want the image to be sampled. For example,

SET x=0,1,.01 SET z=IMAGE(x,0.5)

will extract a horizontal cross section through an image. You can also use IMAGE[expr,expr] to extract values via their indices, where either or both of the exprs may be * meaning "all values"; this is especially useful to those who like to use SM's images as a way of reading binary data.

An example of creating an image from scratch would be

image (51,81) 0 1 0 1
define NX image define NY image
set ix=0,$NX*$NY-1 set iy=ix 
set iy=int(iy/$NX) set ix=ix - $NX*iy
set x=ix/($NX-1) set y=iy/($NY-1)
set image[ix,iy] = sin(x)*sin(y)

If you have a vector v of size NX*NY, you can say

set image[*,*] = v

to convert it to an image. The data is arranged row-by-row (i.e. in the fortran order).

If you wanted to extract the top row of an image, after

   define NY IMAGE  define NX IMAGE
   set ix=0,$NX-1

you can get the top row with any one of

   set rr=image[ix,$NY-1]
   set rr=image[do(0,$NX-1),$NY-1]
   set rr=image[*,$NY-1]

If you want to add 100 to every value of an image, you can say

set image[*,*] = image[*,*] + 100

It's obviously pretty easy to use SM to manipulate images point-by-point in this way (although you cannot (currently) write out the result (19)

See also ARITHMETIC for how to extract a cross-section into a vector and DEFINE for defining a variable from the image header. Images may be displayed with CONTOUR or DITHER, and examined with IMAGE CURSOR.


Key

Syntax: KEY 
        KEY key string

Define a key to generate a string. This is most often used simply to save typing some common command such as edit_hist. With the command KEY, you are prompted for the key to define, and the string. Because you are not using the history editor when you type the key, you can simply hit the key that you want defined, type a space, and then type the string terminated by a carriage return. The other form, where the whole command appears on one line, is probably more suitable for use in a macro such as your private startup macro (see under startup2 in the index). If you try entering it at the keyboard any special characters in key, such as ESC, will be interpreted by the history editor so you'll probably have to quote the key with ^Q or ESC-q. Alternatively you can use ^ and printing characters , or octal numbers, to represent the escape characters in the same way as for EDIT (see section Edit). If key is given as pf# or PF# (where # is 1, 2, 3, or 4) it will be interpreted as a special function key on your keyboard in a terminal-independent way (see the description of termcap (see section Termcap -- A Terminal Database) to see how these keys are defined). KEY definitions are listed along with other key bindings by the LIST EDIT command.

If the string ends in a \N, it will be executed the moment that the key is struck. (Note that this is \N not \n, which would have been interpreted as a newline.)

Only 10 keys can be defined, after that you'll start overwriting earlier definitions (this is a result of the way that KEY was implemented; if it is a serious nuisance send us mail).


Label

Syntax: LABEL str

LABEL writes the string str, which starts one space after LABEL and continues to the last non-space character, at the current location (set by RELOCATE, etc). After the label is written the current location is on the baseline, just to the right of the last character drawn. You can of course use quotes to include trailing white space. LABEL str is exactly equivalent to PUTLABEL 9 str (see section Putlabel).

The string's size and angle are determined by EXPAND and ANGLE. For more information on fonts and such like, See section Drawing Labels and SM's TeX Emulation.


Levels

Syntax: LEVELS WORD
        LEVELS expr

Set the levels for the CONTOUR command to be the values of the vector WORD or to the values of the expression.


Limits

Syntax: LIMITS WORD WORD
        LIMITS WORD Y1 Y2
        LIMITS X1 X2 WORD
        LIMITS X1 X2 Y1 Y2

LIMITS sets the coordinates of the plot region. All coordinates in RELOCATE, DRAW, etc, are referred to these limits. The various forms specify explicit limits for the x or y axis (X1 X2 or Y1 Y2), or default (specify the name of the vector to be used).

In fact, either or both of the WORDs may be replaced by `parenthesised expressions', i.e. expressions in parentheses. For example,

LIMITS 0 5 (ln(y))

will scale the y axis according to the logarithm of vector y (but not produce a logarithmic axis - see TICKSIZE for this capability).

The current value of the minimum and maximum values on the x and y axes can be obtained with a DEFINE | command, e.g. DEFINE fx1 |.

If the two limits specified for an axis are the same, the limits for that axis will not be changed.

You can specify that the limits on one or both axes have a desired range using the RANGE command. This command affects the performance of the LIMITS command. If a non-zero RANGE has been set, LIMITS will ensure that the upper and lower limits differ by that amount. (e.g. after RANGE 2 0 , LIMITS 0 1 0 1 is equivalent to LIMITS -0.5 1.5 0 1 ). If you specify a vector, the range is centred on the median value. If you have specified a range, and then ask for logarithmic axes with TICKSIZE, you may get complaints that logarithmic axes are impossible. Simply unset RANGE, and the problem should go away.


Lines

Syntax: LINES INTEGER INTEGER

Use only lines INTEGER1 to INTEGER2 from the current data file (specified with the DATA command). If VERBOSE is greater than 0, the lines actually read will be reported. LINES 0 0 will use the entire file, which is also the default following a DATA command. The variables $_l1 and $_l2 will be set to the first and last lines specified.


List

Syntax: LIST DEFINE [ begin end ]
        LIST DEFINE |
        LIST DEVICE [ pattern ]
        LIST EDIT
        LIST MACRO [ begin end ]
        LIST SET
        LIST TABLE

list all the currently defined variables (DEFINE) or macros (MACRO), optionally only within the range begin - end . If VERBOSE is 0 macros beginning ## won't be listed. You can list the internal variables (i.e. those such as $fx1 that track SM internal variables) with LIST DEFINE |, or by setting VERBOSE to be two or more.

LIST EDIT will list all the keybindings. If VERBOSE is 0 only the keys that don't generate themselves are listed (i.e. because A is bound to A it isn't listed). If VERBOSE is 1, in addition all non-printing keys are listed, and if VERBOSE is 2 or greater all keys are listed. Both the EDIT and the KEY bindings are listed.

LIST DEVICE will list all the devices known to SM. The devices are listed with each device on an (indented) line, first the primary name, then a list of aliases in parentheses, then a full name. If pattern is provided only those lines that match the given pattern will be printed, for details on SM's regular expressions See section Apropos. An example would be

LIST DEVICE ^post

to list all devices whose principle name begins `post'.

LIST SET lists all currently defined vectors. For each vector the name, the dimension and the HELP field are given. See SET for how to set the latter.

LIST TABLE lists all columns available in the current TABLE; this currently only works for FITS binary tables.

For a list of the history buffer use HISTORY (macro lis), to list a macro use HELP (macro h). It can be useful to overload `list' so that it doesn't appear on the history list, and so that `list' by itself corresponds to the command HISTORY (this is done for you if you use set_overload or put overload in your `.sm' file).


Location

Syntax: LOCATION GX1 GX2 GY1 GY2

Set the physical location of the plot. The plot region is the rectangle inside the box drawn by BOX. Vectors and points are truncated at the bounds of the plot region. LOCATION specifies (in device coordinates) where the plot region is located. LOCATION can be used to make an arbitrary size and shape plot, providing that you want it rectangular.

Because all devices have the same coordinate system in SM (0-32767), this command is considerably more useful than it used to be. The default LOCATION is 3500 31000 3500 31000. You can get at the current values of GX1 etc. using the DEFINE | command.

While you are using WINDOW (see section Window), LOCATION commands have no effect. SM remembers them, however, and obeys the most recent one when you are finished with WINDOW.

See the RELOCATE ( x y ) command to draw labels outside the plot region, and DRAW ( x y ) to draw lines there.

If you want to increase the x-location by 500 (say), you can say:

        LOCATION $($gx1 + 500) $gx2 $gy1 $gy2

This is sometimes useful to make room for an axis label; if your verbosity is 1 or higher you'll be advised of the appropriate displacement.


Logical

Syntax: Logical Operators

The following logical operators are allowed on vectors and scalars in SM, where non-zero means true:

Unary:

!expr           Logical Complement    
Binary:

expr == expr    Equal to             expr != expr    Not equal
expr < expr     Less than            expr <= expr    Less than or equal
expr > expr     Greater than         expr >= expr    Greater than or equal
expr && expr    Logical and          expr || expr    Logical or

Only !, ==, and != are allowed for string valued vectors. All arithmetic vectors test unequal to all string-valued vectors.

For string vectors, there are three cases to consider: vstr1 == vstr2 generates a vector of the same length as vstr1 (with must be the same length as vstr2) by comparing the two vectors element by element; 'str1' == vstr generates a vector of the same length as vstr by comparing each element of the vector vstr to the string str1; and 'str1' == 'str2' which returns a scalar by comparing the strings str1 and str2 (so it's false in this example).

As in C, == has a higher precedence than &&, which in turn has higher precedence than ||.

Note that there is also a ternary operator, (expr1) ? expr2 : expr3 which has the value expr2 if expr1 is true, and expr3 if it is false.

See `arithmetic' for the arithmetical operators See section Arithmetic. You can test to see if a variable is defined by looking at the value of $?var (see section Define).


Ltype

Syntax: LTYPE INTEGER
        LTYPE ERASE

All lines except for those making up axes and characters are drawn with line type INTEGER, meaning:

0       solid                           1       dot
2       short dash                      3       long dash
4       dot - short dash                5       dot - long dash
6       short dash - long dash                  

the default is a solid line, LTYPE 0. The current value of LTYPE is available as an internal variable (e.g. DEFINE ltype |)

LTYPE ERASE and will erase any lines that are redrawn (e.g. LTYPE 0 BOX LTYPE ERASE BOX will first draw a box, and then erase it). Not all devices can support erasing individual lines, if yours doesn't you'll have to ERASE the whole screen. A convenient way to use LTYPE ERASE is the undo macro. (in fact, LTYPEs 10 and 11 are used to implement LTYPE ERASE, LTYPE 10 to start erasing, LTYPE 11 to notify a device that you've finished doing so).


Lweight

Syntax: LWEIGHT number

Set all lines to have a weight of number, where the bigger the blacker. Generally, an lweight of 0 is taken to be the hardware's preferred width. The current value of LWEIGHT is available as an internal variable (e.g. DEFINE lweight |)


Macro

Syntax: MACRO EDIT name
        MACRO LIST [begin end ]
        MACRO name [ narg ] { body }
        MACRO name [ narg ] < body >
        MACRO name DELETE
        MACRO name #1 #2
        MACRO READ file
        MACRO WRITE file
        MACRO DELETE file
        MACRO WRITE name [ + ] file

MACRO EDIT name allows you to edit a macro. All the commands available to the history editor area available (including the ^ history), except that ^M inserts a line before the cursor, ^N and ^P get the next and previous lines respectively, and ^V and ESC-v move forwards and backwards 5 lines at a time. To exit use ^X (or whatever you have bound to exit_editor). The macro need not exist, and both its name and number of arguments can be changed by editing the zeroth line of the macro (^P from the first line. If this line is corrupted, or deleted, no changes are made to the macro when you exit. If the number of arguments is negative, the macro will be deleted when you exit.) You may prefer to use the macro ed instead of MACRO EDIT, as it doesn't appear on the history list and, if invoked without a macro name will edit the macro that you edited last. Incidently, hm (`help macro') will list the last macro that you edited with ed. The keybindings may be changed with READ EDIT.

LIST MACRO lists all currently defined macros, or all those which are between begin and end alphabetically (asciily). If VERBOSE is 0, macros starting with ## are not listed.

MACRO name [narg] { body } defines name to be body, where name is a single word, and body may be anything (most users need not worry about the form in angle brackets; it is occasionally useful when writing clever macros). A macro is invoked by typing its name. The optional nargs is the number of arguments the macro expects, default 0.

If the macro's body is defined to be delete, the macro is deleted. MACRO name DELETE also deletes a macro.

Arguments are referred to as $1, $2, ... $n, up to a maximum of $9. $0 gives the name of the macro. If the number of arguments is declared as more than 9, the macro is taken to have a variable number of arguments, up to the number declared modulo 10. If the number declared is greater than 99 the last argument will extend to the end of the line, and may consist of many words. When called, all the arguments must appear on the same line as the macro itself. This line may, as usual, be ended with an explicit \n. The macro can determine whether it has been supplied a given argument by using the $? construction (see DEFINE). It is also possible to change the values of arguments using DEFINE just as usual, and even to DEFINE arguments that you didn't declare. These are temporary variables, local to the macro, and will disappear when you exit the macro.

MACRO name #1 #2 defines macro name to consist of lines #1 -- #2 of the history buffer. If #1 or #2 is negative it is interpreted relative to the current command, so saying MACRO last2 -1 -2 will define a macro last2 consisting of the last 2 commands issued.

MACRO READ file reads the macros in file and defines them. See RESTORE for how to also restore the history buffer from macro all.

MACRO DELETE file has the effect of deleting all macros defined in file.

MACRO WRITE file writes all currently defined macros to file in alphabetical order. If the file exists, and $noclobber is defined, SM will refuse to overwrite the file. You can set noclobber by specifying it in your `.sm' file.

MACRO WRITE name [ + ] file writes the macro name to file. If the + is specified, or the file is the same as for the previous use of this command, the macro is written to the bottom of the file, otherwise the file is created. If the file exists and you aren't simply appending, and $noclobber is defined, SM will refuse to overwrite the file. You can set noclobber by specifying it in your `.sm' file.


Meta

Syntax: DEVICE META WORD
        DEVICE META CLOSE
        META READ WORD

If you open the special device called META it doesn't close the current device, merely intercepts plotting commands and stores them away as well as executing them immediately. This continues until you issue a CLOSE command.

The command META READ reads a metafile and executes it on the current device. So to make hardcopy of a plot you could say something like:

device x11
device meta metafile.dat
my_cunning_macro
more_brilliance
device meta close

after which (maybe after exiting SM and restarting it), you could say:

device postscript
meta read metafile.dat
device 0

to make a hardcopy.

It is safe to concatenate metafiles together, if the fancy takes you.

Because of the way that SM interrogates devices about their abilities, while using META all ltypes, lweights, and fonts will be emulated in software (this guarantees that the device you playback on will be able to handle the code). If the current device can handle dots (i.e. PTYPE 0 0) then META will attempt to use them too, but if it can't then META will be reduced to faking them. This could be a serious problem, so good luck. Metafiles do not support colour, again due to the impossibility of knowing if they will have the same behaviour as the original device.


Minmax

Syntax: MINMAX min max

Set variables min and max to the the maximum and minimum values of an image read by the IMAGE command. Only that portion of the image within the current LIMITS is examined. This may be useful for setting contour levels, or doing a halftone plot (see the macro greyscale).

For example, the commands:

MINMAX min max
SET levs = $min,$max,($max-$min)/9
LEVELS levs

will choose a set of 10 levels which cover the complete range of the data.


Notation

Syntax: NOTATION XLO XHI YLO YHI

Set axis label format (exponential or floating). By default, all numbers between 1e-4 and 1e4 are written as floating point numbers, and all numbers outside this range are written with an exponent. This corresponds to a NOTATION -4 4 -4 4 command.

If you set XLO=XHI and/or YLO=YHI, all values on that axis will be plotted using exponents (including 1); as a special case if both XLO and XHI are 0 NOTATION will be reset for this axis.

If you want your positive and negative exponents to line up define the SM variable line_up_exponents; if it's 1 they'll be padded with a space, if 2 or more, with a + (you can do this in your `.sm' file).


Overload

Syntax: OVERLOAD keyword INTEGER

Allow "keyword" (in lowercase) to be used as a macro name if integer is non-zero. For example,

overload set 1 overload define 1
macro set { DEFINE } macro define { SET }

would interchange the meanings of the SET and DEFINE commands. The uppercase forms of the keywords retain their usual meanings. overload set 0 would reinstate the usual meaning of set. You may be surprised by the effects of overloading certain keywords. For example, if you overload help to mean DELETE HISTORY HELP, then set help vec help_string won't work (you'd have to say set HELP vec ...).

This command is intended to be used for changing the default action of commands, rather than for a wholesale renaming of keywords! A more practical example than the above would be

overload erase 1 macro erase { del1 ERASE }

to prevent erase commands from appearing on the history list. See the macro set_overload for a set of definitions like this. It can be automatically executed by including an "overload" line on your `.sm' file.


Page

Syntax: PAGE 

PAGE starts a new page for a hardcopy plot (n.b. the device driver for raster plots is unable to support multiple page plots).

On window systems (X11, SunView) page will raise the window and refresh it if necessary.


Points

Syntax: POINTS WORD1 WORD2 [ IF (expr) ]

POINTS makes points of the current style (PTYPE), linetype (LTYPE), colour (CTYPE), size (EXPAND), and rotation (ANGLE) at the points in vectors WORD1 and WORD2. If the IF clause is present, only use those points for which expr (see the section on vector arithmetic) is non-zero. In fact, either or both of the WORDs may be replaced by `parenthesised expressions', i.e. expressions in parentheses. For example,

POINTS x (lg(y))

to plot x against the logarithm of y.

In case you ever need to know, the distance from the centre of a point to a corner is 128 screen units when unexpanded, if the ASPECT (see section Aspect) ratio is unity.


Print

Syntax: PRINT [+] [ file ] [ 'format' ] { list }
        PRINT [+] [ file ] [ 'format' ] < list >

Print the vectors specified by list to file, if file is absent, print to the terminal (the output is paged, sort of). The name of each vector is printed at the head of the appropriate column. If the output is going to a file, each line of the header starts with a `#', so the file can be read without using the LINES command. With the optional `+' the vectors are appended to the file, otherwise it is overwritten unless $noclobber is defined, in which case SM will refuse to touch the file. You can set noclobber by specifying it in your `.sm' file.

The optional format string is of the type accepted by the C function `printf', and you should see a book on C (or maybe the online system manual or help command) for more details. Basically, the format string is copied to the file with format specifiers beginning with % signs replaced by the numbers that you want printed. The format specifiers to use are the floating point ones, %e (exponential), %f (floating point), and %g (computer's choice), d, o, x for printing numbers as integers (the latter two are octal and hexadecimal), or %s for strings. Fields are right justified by default, you can insert a - just after the % to left justify them. A % may be written as %%, and a tab as \t. Lines are not terminated by a newline by default, you have to write them explicitly as \n.

For example,

SET x=1,10 SET y=x**2
PRINT file '%10f (%10.2e)\n' { x y }

will produce

#........x............y
#
..1.000000.(..1.00e+00)
..2.000000.(..4.00e+00)
..3.000000.(..9.00e+00)
(etc.)

where I have replaced each space by a . for clarity. If you say

PRINT '%g ' { x }

you will get

..........x

1.2.3.4.5.6.7.8.9.10.

If you want very long output lines you'll run into one of SM's internal limits; the maximum length of a string (currently 160 characters). You might try to work around this by putting part of the formatted output into string vectors and then using a %s format to write it out; such an approach can be made to work, for example instead of

print file 'Date: %2d %2d %4d\n' { dd mm yy }

you can write

set date = sprintf('Date: %2d',dd) + \
           sprintf(' %2d',mm) + \
           sprintf(' %4d',yy)
print file '%s\n' { date }

If you think that this is a hack, I rather agree with you, but it does permit formatted output of up to 400 characters.


Prompt

Syntax: PROMPT new_prompt

The current prompt is replaced by new_prompt; the default is :. Any occurrences of the character `*' are taken as instructions to ring the terminal bell. When you start SM your prompt is set to the value of the entry prompt in your `.sm' file (if you have one).

If you enter a partial command (e.g. macro foo { or echo ABC\) SM switches to a different prompt. By default this is >>, but if you define the variable prompt2 that will be used instead. You can set prompt2 in your `.sm' file.


Ptype

Syntax: PTYPE n s
        PTYPE WORD
        PTYPE ( expr )
        PTYPE { list }

PTYPE n s causes points to be drawn as n sided polygons of a style s, where s refers to:

0
open
1
skeletal (center connected to vertices)
2
starred
3
solid

For example, PTYPE 1 1 (or PTYPE 0 0) makes points appear as dots, PTYPE 4 1 (the default) makes (diagonal) crosses, and PTYPE 6 3 makes filled hexagons. Points made up of lines (types 0, 1, and 2) are drawn using the current LTYPE.

When possible PTYPE 0 0 will draw the smallest possible dots that the device is capable of; these may or may not be different from PTYPE 1 1.

The current value of PTYPE is available as an internal variable (e.g. DEFINE ptype |)

PTYPE WORD or PTYPE ( expr ) use vector WORD or the expression expr as its source of n and s, ( so you may define different point types for each point) except that the numbers are contracted together. If the entry has a fractional part, it is treated as an expansion factor, relative to the current expansion (no fractional part means default expansion); so if n is a vector giving the desired number of sides for a set of points, s is a vector giving the desired types, and e is a vector giving the desired relative sizes (0 <= e < 1), you'd want to say PTYPE (10*n+s+e). For example, an an entry of 103.5 in WORD is the same as PTYPE 10 3, EXPAND 0.5, but if you now say EXPAND 2 the net expansion will be unity. It's much easier to use a vector of expansions directly to the EXPAND command, but fractional ptypes are preserved for backwards compatibility. N.b. due to a bug in X10R4 for the Sun, PTYPE n 3 does not work for dev xwindows on a sun. If more points are specified than the dimension of expr, the first element will be used for the excess.

If WORD is a string-valued vector, its elements are used to label the points of the graph. They are drawn at the current expand and angle (vector-valued EXPANDs and ANGLEs are ignored), and in the current default font. For TeX-string users this can be specified with the variable default_font, which can either simply be defined, or set in your `.sm' file.

PTYPE { list } defines the symbol to use with the POINTS command to be some creation of the user. The list consists of a set of c x y where c is a letter, and x and y are integers. If c is `m' or `r' (move or relocate) the plot pointer is moved to the point (x,y), if it is `d' (draw) or absent a line is drawn from the current position to the point (x,y). The coordinates are measured relative to the current point being plotted, and are measured in screen coordinates (i.e. 0-32767). Both EXPAND and ANGLE are applied to the (x,y) values as usual.

As an example the command

PTYPE { m 0 500 500 0 0 -500 -500 0 0 500 } 

will define the marker to be a diamond, something like:

                  /\
                 /  \
                 \  /
                  \/

(but with unbroken lines). As a more useful example, there is a macro upper which defines a variable $upper to draw an upper limit sign, used as

PTYPE $upper

(if ANGLE were 180, they'd be lower limits).


Putlabel

Syntax: PUTLABEL INTEGER str

PUTLABEL writes a label at the current location with rotation and size specified by ANGLE and EXPAND (exactly like LABEL). The label is centered with respect to the current location according to the argument INTEGER which can be 1 - 9 meaning that the label is:

                        left    centre  right
        above           7       8       9
        centered        4       5       6
        below           1       2       3

(cf. a vt100 keyboard) To be a little more precise, `above' means that the string's baseline (the bottom of characters such as `a' that have no descender) is at the level of the current point, while `below' means that the top of the tallest character in the string is level with the current point. If you don't like this neglect of descenders, try

MACRO myputl 102 {label \raise\advance\depth{$2}by100{}\n putlabel $1 $2}
myputl 7 This is a Label

(You can then say overload putlabel 1 macro putlabel {myputl} if the mood takes you). After the label is written the current location is on the baseline, just to the right of the last character drawn. If INTEGER is 0 the string isn't actually drawn, but the string's dimensions are calculated (and are available as $swidth, $sheight, and $sdepth), and any TeX definitions are remembered. If PUTLABEL 5 isn't quite what you want (as it centres vertically as well as horizontally), try LABEL \centre{H_\alpha} instead.

See section Drawing Labels and SM's TeX Emulation, for a description of how to enter a label with funny characters, sub- and super-scripts, and so forth.

If EXPAND is set to exactly 1, and ANGLE is exactly 0, then SM will use hardware fonts, when available, in writing labels. This is faster, but if you don't like it say "EXPAND 1.00001", or use a \r explicitly to select the roman font. Or ask your SM Guru to edit the `graphcap' file to stop your printer from ever using hardware fonts (or read the discussion under LABEL).


Quit

Syntax: QUIT 

Quits the programme entirely.

The macro `q' is defined as something like

DELETE HISTORY DEFINE 1 0     # default value
DEFINE 1 ? { Are you sure? Enter 1 to really quit }
IF($1) { QUIT } 

so you won't quit accidently, and the QUIT won't appear in the history file. This is an obvious candidate for overloading.


Range

 
Syntax: RANGE number_x number_y

If number is non-zero, set the range on the x or y axis to be number, so LIMITS will choose two values that differ by number. Nothing will happen until you issue a LIMITS command.

For instance, if you wanted to ensure that the y axis of a logarithmic plot spans exactly two decades the commands RANGE 0 2 LIMITS x y would choose suitable y limits, with actual values appropriate for the y vector (in fact symmetrical about the median value).


Read

Syntax: READ WORD INTEGER
        READ [ ! ] { WORD INTEGER WORD INTEGER ... }
        READ [ ! ] { ... WORD range ... }
        READ ROW WORD INTEGER
        READ [ ! ] 'format' { WORD WORD ... }
        READ EDIT WORD
        READ OLD WORD WORD
        META READ WORD WORD

READ WORD INTEGER reads a column of data from the file specified by the DATA command, using the lines specified by LINES. Columns may be separated by white space (blanks or tabs) or by a comma, or by some combination of the two. It's OK if some of the columns contain text, providing that you don't try to read them. You can read text columns into string vectors, as described in the next paragraph. The data is read into the vector WORD, which will be created, from column INTEGER. Any field beginning with a * is taken to be `empty', and is assigned the value 1.001e36. Any line beginning with a # is skipped over (and printed if VERBOSE is greater than 1), any line beginning with a ! is skipped and always written to the terminal. Long (logical) lines may be spread over several (physical) lines by ending the line with a `\'; no line may exceed a total of 1500 characters. If you use continuation lines, note that SM's line numbers (for example, as set with the LINES command) apply to logical not physical lines; a continued line counts as only one line.

You can optionally specify a type of vector by adding a suffix onto the integer; `.f' (the default) means floating point, `.s' means string-valued. String valued vectors can be used as input to PTYPE commands, or simply for reading columns from data files that you want to PRINT.

READ { WORD INTEGER WORD INTEGER ... } is the same as repeating READ WORD INTEGER for each vector, but more efficient as it only has to read the file once.

READ { x 1 y 5.s z 2.f }

will read columns 1 and 2 into floating point vectors x and z, and column 5 into string-valued vector y.

Usually SM stops reading at the first invalid line, but if you say READ ! all the lines specified with LINES (or the entire file) are read. Missing numerical fields are set to be invalid (i.e. they are treated as *); missing string values are left blank. This is probably most useful with the %n format specifier.

If INTEGER is invalid ( <= 0, or > 40), the contents of the file are written to the standard output. READ ROW is very similar, but the values are read from row INTEGER of the file (any LINES command is ignored). The same type qualifiers are allowed as for reading columns. There is no limit to the number of elements in the vector, except that implied by the maximum length of a line. You cannot specify a range of columns to read with READ ROW, but try

SET i=2,5
READ ROW x 1
SET x=x[i]

If the first field is a string, you can say READ ROW s 1.s SET x=ATOF(s[i]).

If your data is in a number of columns (e.g. you have written it out to a file ten values to a line) you can specify a range of columns, for example

READ { x 1-4 y 5 z 6-10 }.

You can only use ranges for numerical vectors, and only with the list form of READ. Ranges won't work if there is a short line at the end, but you can still say something like

LINES 0 100
READ { x 1-4 }
READ ROW _x 101
SET x=x CONCAT _x

which will be almost as efficient if you have defined $save_read_ptr.

In order to speed up multiple reads of the same file, SM is able to remember where is got to in a file; this is only enabled if you define the variable $save_read_ptr (which can be done in your `.sm' file). The remembered position is disabled every-time that you issue a DATA command, or try to re-read part of the file. You can get into trouble if you read part of a file, modify the file without reissuing a DATA command, and then read some more, but in normal usage it should be safe to enable saving the read pointer.

Instead of using simple column-oriented input it is possible to specify a format similar to those used by C's scanf functions (Fortran formats are not supported); if you don't know C then most of what you need to know is that characters in the input must match those in the input file, except that items to be read are specified with format strings that start %. For example, a format abc%f:%f expects the input to consist of `abc' then two floating point numbers separated by a colon. If the % is followed by a * the field is read but isn't assigned to a vector. You can specify a newline as \n or a tab as \t.

As a further example, if your data file has lines like

        1:12:30  -45:30:11

you could read it with

        read '%d:%d:%d %f:%f:%f' { hr min sec deg dmin dsec }.

The type of the vector is deduced from the format string; you can't use .f or .s in the vector list (why would you want to specify a type twice?).

I said that the %-formats were `similar' to scanf's; they differ in the way that they treat field widths and white space. If you don't specify a width at all SM follows the usual C behaviour of skipping white space between items; if you do specify a field width no space is skipped over before the field begins. You can always explicitly skip spaces with a %*[ ] format. The %n format returns the number of fields matched rather than the number of characters.

The supported format letters are d, e, f, g, o, n, s, x, and [, their meanings are:

%d
Read an integer into a floating vector (`d' stands for `decimal'). If a field width is specified trailing spaces are treated as spaces not zeros -- this isn't fortran you know. The field " 1234 " (i.e. a field width of 6, %6d) has the value 1234 not 12340.
%e
%g
Read a floating point number with or without an exponent into a floating vector. As for %d, trailing spaces in a fixed-width field are treated as spaces not zeros.
%f
Read a floating point number without an exponent into a floating vector. As for %d, trailing spaces in a fixed-width field are treated as spaces not zeros.
%n
Return the number of fields that are already correctly matched in the current line; this is only useful in conjunction with READ !.
%o
Like %d, but the number's taken to be octal.
%s
Read a string into a string-valued vector. If a field width is specified the entire field is read spaces and all; if there is no width initial spaces are skipped as usual and the string is terminated by the first white space character.
%x
Like %d, but the number's taken to be in hex.
%[...]
Read a string consisting of the characters ... into a string valued vector. You can specify a range as a-z so %[a-zABC0-9] would read a string consisting of any lower case character or digit, or one of A, B, or C. If the first character is ^, read any characters except those specified (e.g. %[^abc] reads anything but the letters a, b, or c). If a field width is specified characters that don't match those specified at the end of the field are ignored.
%%
Not a conversion format, but a literal %.

READ EDIT WORD reads a new set of keybindings from the file WORD. The format and syntax are given under History (see section History) in the introduction.

READ OLD WORD1 WORD2 defines macro WORD1 to be the the contents of file WORD2. This is provided for compatibility with Mongo (see section Tips for Mongo Users) and the read_old macro. You no longer need use read_old to read SM history files, use RESTORE instead.

If VERBOSE (see section Verbose) is greater than 0, the lines actually read will be reported.

META READ WORD reads a metafile, as produced with the pseudo-device META, and executes the enclosed commands on the current device.


Relocate

Syntax: RELOCATE X Y
        RELOCATE ( X Y )

The first form sets the current position to (X,Y) in user coordinates without drawing a line. The second (with parentheses) sets the position in `screen' coordinates, i.e. 0-32767. The current position is used by the DRAW, LABEL, and PUTLABEL commands.

There are a couple of pairs of internal variables ($uxp,$uyp) and ($xp,$yp) that give the current position of the plot pointer, either in user or screen coordinates.


Restore

Syntax: RESTORE [ filename ]

Restore all the current macros, variables, and vectors from file filename (if omitted the default is to use the value of save_file in your `.sm' file, or failing that `sm.dmp'). In addition, the current history buffer is replaced by the macro all if defined in the RESTOREd file.

The file should have been written by the SAVE command, and RESTORE will treat any other file type as if it were a SM history file and add its commands to the end of the current history list.

If VERBOSE (see section Verbose) is greater than 0, some extra information is printed.


Return

Syntax: RETURN 

Return from the current macro, which includes breaking out of DO and FOREACH loops. If you are not executing a macro, simply return to the prompt (this is more or less equivalent to typing ^C).

A RETURN can be useful while playing with fiddling with data interactively. For example, if you want to playback a set of commands, but then do other things when the plot has appeared, you could put a RETURN after the desired part of the playback buffer. (This doesn't work quite the way that you might naively think. Playback works by defining a macro all from the history list, and then executing it. The RETURN is actually returning from this macro, rather than directly from the command list, but the effect is the same. If RETURN always returned directly to the prompt, macros such as hcopy wouldn't work.)

If VERBOSE is 2 or more, the name of the macro being returned from is output.

If the very last command in a macro is RETURN then the RETURN will take place, not from the desired macro, but from where the macro was called from. You can work around this by putting a space after the RETURN, or simply omitting it as it isn't doing anything anyway. If a RETURN comes last on a history list, this problem will lead to macros such as hcopy not working correctly.


Save

Syntax: SAVE [ filename  ]

Save some or all of the current macros, variables, and vectors in file filename (if omitted the default is to use the value of save_file in your `.sm' file, or failing that `sm.dmp'). The current history buffer may also be saved, as the macro all.

You are prompted for whether you want to save variables, vectors, and macros (which includes all, the current playback buffer). Macros beginning ## are not saved, as they are assumed to be system macros. Variables and vectors whose names start with a `_' are assumed to be temporaries, and are not saved either.

The opposite to SAVE is RESTORE (see section Restore). You may want to use the MACRO DELETE WORD command to undefine macros from e.g. the `utils' macro file. See, for example, the macro sav (which can be overloaded).

If VERBOSE (see section Verbose) is greater than 0, some extra information is printed.


Set

Syntax: SET name = expr
        SET name = { expr }
        SET name = < expr >
        SET name = expr IF ( expr )
        SET name = expr1, expr2 [, expr3 ]
        SET name = expr1 ? expr2 : expr3
        SET name LOCAL
        SET DIMEN ( name ) = INTEGER
        SET name = WORD ( [ WORD [ , WORD ... ] ] )
        SET name [ expr ] = expr
        SET IMAGE[expr, expr] = expr
        SET HELP WORD [ rest ]
        SET RANDOM s_expr

Conduct various operations on vectors of data. The simplest, SET name = expr sets vector name to be equal to the expression expr. If the IF clause is present, name will only contain those elements of expr for which it is true (non-zero). A special case of an expression is simply a list of values within braces (or angle brackets).(20) For string-valued vectors, the only allowable expressions are a string-valued vector, the CONCATenation of two string vectors, the addition (i.e. element-by-element concatenation), or a string in single quotes (e.g. SET s='Hello, World' or SET ss='n_{' + < e cl co g > + '}').

The command SET name LOCAL command, which is only allowed within macros, ensures that the vector name is only visible within that macro, and any called from it (this is really a vector in nested scope rather than local, but LOCAL is easier to type). Such local vectors are automatically destroyed when they go out of scope; in fact it is illegal to delete one explicitly. For example, if you define the macro bar as

   macro bar 2 {
      echo $(goo)
      set goo local 
      set goo=$1
      if(goo < $2) {
         bar $(goo+1) $2
      }
      echo $(goo)
   },

the command set goo=0 bar 1 5 will count from 0 to 5 and down again, and if you run the macro yar (defined as macro yar { set foo local set foo=1\n}) the vector foo will not be defined at global scope. Note that, as usual, you may have to be a little careful to ensure that you don't exit a macro before you expect. The symptoms would be that your local vector was already destroyed, or that it referred to one at less restrictive scope (see section The Command Interpreter). The easiest fix is to add a comment line to the end of the macro.

With expressions separated by commas the SET command is like a DO loop, setting name to be the values between expr1 and expr2, at increments of expr3 (which defaults to 1). You can also use an implicit DO as part of an expression, e.g. SET x=1 + do(0,10,2)/10 (see section Arithmetic).

The command with ? and : is similar to the C ternary operator. If expr1 is true, take the corresponding value of name for expr2, otherwise use expr3. This command is worth learning, as it can often be used to replace a DO loop. This command is in fact simply a special case of SET x = expr.

If you have a DO loop that calculates each element of a vector in turn, something that is possible if inefficient in SM, (21) you need to define a vector before you use it. You will also need to declare a vector (or create it by putting it on the left of a SET command) if you want to use a vector-valued subscript on the left of an expression. This can be done with the SET DIMEN(name) = INTEGER, which also initialises it to 0. Thus SET DIMEN(y) = DIMEN(x) is equivalent to SET y = 0*x. You cannot use expressions as the dimension, but SET y = $(4 + 4) works perfectly well. You can optionally specify a qualifier to the dimension, in just the same way that you can specify a qualifier to a column in a READ command, so SET DIMEN(s) = 10.s declares a 10-element string-valued vector.

SET name = WORD ( [ arg [ , arg ... ] ] ) allows you to use a macro as a sort of function definition. Within the macro WORD any assignment to $0 has the effect of assigning to name, and the other arguments behave as normal. The arguments arg can be words or numbers (but not general expressions) and are separated by commas. Note that this is a change to the syntax of this command! Previously only one argument was permitted, but it could be an expression, and the result was returned by assigning to $1 in a rather confusing way.

SET word[expr] = expr sets the elements expr of vector word to the values of the vector on the right hand side. If the left hand side is a string but the right hand side is numerical it will be converted. The first expr is converted to an integer before being used as an index; if it is too small it's set to 0, if too large to the largest allowable index. For example,

	set i=0,10 set x=100*i
	set dimen(y) = dimen(x)
	set y[i-1] = x

will result in a complaint that -1 is an invalid index and set y = { 100 200 300 ... }. Note that arrays are subscripted with [ ] not (), and that, as always, indices start at 0 not at 1. The word must exist before you can do this to it.

SET IMAGE[ix,iy] is used to set elements of an image to the specified values. The image must exist (see section Image), and the vectors ix and iy are interpreted as integer subscripts into the image (0-indexed, of course). This is the inverse of the SET z=image[ix, iy] and isn't quite the same as the SET z=IMAGE(x,y) command, as x and y are interpreted with using the (optional) xmin, xmax, ymin, and ymax values. In the old days, this command was set image(ix,ix) = ..., but this was confusing and is now deprecated.

SET HELP sets the help string for a vector; the rest of the line is read, and will be returned in response to a HELP WORD request. It can also be used in the string-valued expression HELP(name), for example YLABEL $(HELP(yvec)).

SET RANDOM number sets the seed of the random number generator used by the RANDOM operator; if you don't set it yourself it'll be set to some value based on the time since 1970.

Let's look at some examples.

SET y = $v1 + 5.0 * x

This sets each element of the vector y to be the value of the scalar $v1 plus 5.0 times the corresponding element of the vector x (assuming that x has been defined previously)

SET data_set_1 = lg(x) IF ( lg(x) > 0)

This sets the elements of the vector data_set_1 to be the (common) logarithm of the corresponding element of the vector x, if that logarithm is > 0. Thus data_set_1 will in general be of smaller size than x.

SET data = (lg(x) > 0) ? lg(x) : 0

In this case, data_set_1 will be the same size as x, and any elements of data_set_1 where the corresponding element of x is less than or equal to 1, will be set to 0.

SET vec = 4*{ 1 1.5 2 2.5 3 }

will define a vector vec, with 5 elements, with the values given by four times those in the list.

SET vec = 1,12,2 

an alternative way of defining the same values.

SET i = { 2 3 }
SET x = vec[i]

will set the vector x to have be 8 10 (i.e. vec[2] and vec[3]).

MACRO pow 2 { SET $0 = $1 ** $2 } 
SET vec = pow(vec , 3) 

cube the vector vec.

SET vec[0] = 2*pi

Change your mind about the first element of vec.

SET HELP pam Wichita, Kansas, July 7, 1953

will set the help string for vector pam to be the string Wichita, Kansas, July 7, 1953, so when you type HELP pam, this string will be printed out.

SET rhl=Robert

defines a string vector with one element.

SET DIMEN(rhl) = 10.s

defines a string vector with ten elements (all blank), while

SET rhl={Robert Horace Lupton}

defines a string vector with initialised elements, and

SET rhl[1]=Hugh

corrects it.

See the CURSOR command for defining a pair of vectors using the cursor to mark the points, and SPLINE for how to fit splines to pairs of vectors.


Shade

Syntax: SHADE INTEGER pexpr pexpr
        SHADE HISTOGRAM INTEGER pexpr pexpr

(`Pexpr' is the name of a vector, or an expression in parentheses, e.g. SHADE 1000 x (sqrt(y))).

Shade `inside' a curve defined by the expressions. The shading is rotated through the current value of ANGLE, and lines are spaced INTEGER apart (screen coordinates, so the full screen is 32768 across). If INTEGER is 0, the lines will be drawn as close together as the device allows, simulating an area fill. This is a very inefficient way to fill areas, made only slightly better by specifying a large LWEIGHT on devices that support such things in hardware (you'll also get slightly jagged edges).

The meaning of `inside' is that as the shading is done, from left to right taking the value of ANGLE into account, lines are drawn from every odd to every even crossing of the curve. The curve is considered as being closed by joining the first to the last point. If a shading line just touches the curve the algorithm may be confused, change INTEGER slightly, or adding 180 to ANGLE. Sometimes joining the ends of the curve may not be what you want, try using CONCAT to add points on the end yourself. For example,

SET x=0,10 SET y=x**2 LIMITS x y SHADE 1000 x y

looks like a new moon, but

SHADE 1000 (x CONCAT 10) (y concat -1e10)

shades beneath the curve, for ANGLE 0 that is. You could also try the macros scribble and shading in demos, e.g. type load demos scribble.

SHADE HISTOGRAM is similar, but it shades the histogram that would be drawn by HISTOGRAM from the same set of points. In this case the area to be shaded lies between the histogram and the line y=0. If this offends you, offset the whole graph and lie about the axes.


Show

Syntax: SHOW 

List the values of some of the internal variables, including current location and plot region limits in user and device coordinates, the value of the expansion and angle variables, the line type and weight, and the physical limits. Show is actually a macro, so you could modify it to your own ends, for example listing the current data file too.


Sort

Syntax: SORT { vector_list }

Sort the first vector in the list into increasing numerical order, and rearrange the others in the same way. The maximum number of vectors that can be sorted is 10. For example, following the commands

SET e = { 2 7 1 8 2 8 1 8 2 } SET p = { 3 1 4 1 5 9 2 6 5 }
SORT { e p } 

the vectors e and p would be 1 1 2 2 2 7 8 8 8 and 4 2 3 5 5 1 1 9 6 . The order within the p vector is not defined when the e values are identical.

Any mixture of string- and arithmetic-valued vectors is allowed.


Spline

Syntax: SPLINE x1 y1 x2 y2

Fit a natural cubic spline through the points specified by vectors x1 and y1. The dimensions of x1 and y1 must be the same and must exceed 2, x1 must be monotonic increasing (use SORT if necessary). When the spline has been fit, take the points specified in vector x2, and fill the (new) vector y2 with the corresponding values. Linear interpolation is used beyond the ends of x1.


Strings

Strings

SM supports a number of string operations on vectors and scalars. In the following descriptions expr is a expression and vector the name of a vector.

Unary:

ATOF(expr)
The value of expr converted to a floating point number. If an element of the expression cannot be so interpreted (i.e. it doesn't start with an optional sign followed by a digit), the value returned will be 0.
HELP(name)
The help string associated with vector name (set with SET HELP)
LENGTH(expr)
The length (SCREEN units) that a string would have if plotted
STRLEN(expr)
The number of characters in a string
STRING(expr)
Convert a number to a string. You might prefer to use sprintf('%t',expr) instead, as it gives you more control.
( expr )
Raise precedence
Binary:
expr + expr
Add; concatenate element by element
expr CONCAT expr
Concatenate the two vectors
INDEX(expr_1,expr_2)
Return the starting index of expr_2 in expr_1, or -1 if not found.
SPRINTF(expr_1,expr_2)
Format expr_2 using the standard C format string expr_1. The additional format %t or %T is identical to %e, but formats the string as a power of 10 in TeX format. Note that only one expr may be formatted, but that you can say sprintf(expr,expr) + sprint(expr,expr) ... to work around this restriction.
vector[expr]
The elements of vector given by expr.
Ternary:
SUBSTR(expr_1,expr_2,expr_3)
Return the substring of expr_1 that starts at expr_2 and is expr_3 characters long. If expr_2 is negative, count from the end of the string; if expr_3 is 0 return the rest of the string. For example, 'Dr. ' + substr('Ralph Monger',-6,0) would return 'Dr. Monger'.
expr1 ? expr2 : expr3
expr2 if expr1 is true, else expr3

Node that this is similar to the corresponding SET command, but it needs parentheses if used as an expression.

All indices, as elsewhere in SM, start at 0; e.g. substr('Algonquin',0,1) is A.

The expression VECTOR[expr] results in a vector of the same dimension as the expr, with elements taken from VECTOR (i.e. VECTOR[INT(expr_i)]). You can also use WORD([ expr [ , ... ]]) as part of an expression, where WORD is a macro taking zero or more arguments. The arguments are restricted to be either the names of vectors or numbers; sorry.

The HELP(name) string operator is often useful in labels, for example

        SET HELP size "r_e"
        ...
        XLABEL $(HELP(size))

The precedences are what you'd expect, with + being higher than CONCAT. The logical operators have even lower precedence than CONCAT.


Surface

Syntax: SURFACE type z1 z2
or      SURFACE type z1 z2 WORD WORD

Draw a wire-frame surface of the current IMAGE from the point defined by VIEWPOINT. If the WORDs are omitted a line in the surface will be drawn for each row and column of the image; if the WORDs are present they will be taken to be the x- and y- coordinates of the desired lines, and SM will interpolate in the image to determine the corresponding values (see also the hundreds digit of type, below).

The command VIEWPOINT specifies the position of the observer and the type of projection used (see section Viewpoint).

The last digit of TYPE is used to determine which surface to draw:

        0       no hidden line removal
        1       draw top surface
        2       draw bottom surface
        3       draw both top and bottom surfaces

If type's tens digit is set, SURFACE will use the current limits (as set with LIMITS) rather than autoscaling them from the data.

If type's hundreds digit is set, the two WORDs are taken to be the x- and y- coordinates corresponding to the rows and columns of the IMAGE, but no interpolation is done. For example, after

IMAGE (11,11)
SET ix=0,10
set xs=0,10,2
do y=0,10 {
   SET IMAGE(ix,$y) = cos(0.2*ix)*sin(0.4*$y)
}
VIEWPOINT 30 -10 -1
SURFACE 3 -1.1 1.1 xs xs

will draw a 2-sided surface, drawing 21 lines in each direction on the surface. If, on the other hand, the data were really only known on at irregular set of x- and y-values, you could say something like

IMAGE (11,11)
SET ix=0,10
SET x = { 0 1.3 2.4 3 4 4.5 4.6 6.7 8.2 9.6 10 }
SET y = { 0 0.4 0.9 1.2 2.718 3.14 4.2 5.4 6.667 9.1 10 }
do i=0,10 {
   SET IMAGE(ix,$i) = cos(0.2*x)*sin(0.4*y[$i])
}
CTYPE cyan
SURFACE 103 -1.1 1.1 x y
CTYPE default

to draw the same surface.

z1 and z2 are the limits used for the z-axis; you might want to set them with MINMAX. The surface drawn will be truncated at z1 and z2 unless you are using an axonometric projection (see section Viewpoint).

There are some useful macros in the file `surfaces'; say load surfaces to read them. If VERBOSE is one or more, a helpful header will be printed when you load the file.


Table

Syntax: TABLE [subtable] ['format'] file
        READ TABLE { WORD [WORD ...] }
        READ TABLE 'format' { WORD [WORD ...] }
        READ TABLE 'byname' { WORD [WORD ...] }
        READ TABLE 'bycolumn' { WORD id [WORD id ...] }
        LIST TABLE

SM is able to read a wide range of table formats, using tricks similar to those used for the IMAGE command. The variable table_type is used to specify which you want (and may be set in your `.sm' file). Common values are bintable and ctable.

TABLE [...] file is the equivalent of the DATA command, and sets file file to be the source of data read with the READ TABLE command; if the file can't be opened for read, you will be warned. If the subtable argument is provided, it specifies which table in a TABLE file is to be read; this is only currently supported for FITS tables ($table_type is bintable or a type derived therefrom; for such tables you probably want to use a subtable of 1). The format, if provided, specifies the types of the columns in the table; some tables may provide this either in the table header (e.g. FITS binary tables) or in the filecap file, as the FM quantity. Allowable format strings are specified at the end of this file. This format applies to READ TABLE commands for this table, unless specifically overridden.

The range of lines specified by LINES is reset; the LINES command may be used to select portions of TABLEs to read.

The READ TABLE command is used to read data from a table. If you specify a format string and a list of names, a vector will be read from each column specified in the format and assigned to the corresponding vector (for example, READ TABLE 'x16if2' { i x y } will skip 16 bytes at the start of the row, then read an integer into i, and two columns of floats into x and y). Format strings are described at the end of this section.

If you specify the format as 'byname', the names of the vectors will be taken to be the names of columns in the file, and the corresponding columns will be read. If the column name, say RDL, specifies an array, the vector will be filled from column RDL[0]; as an alternative to this you can specify the name as (e.g.) RDL[2] in which case vector RDL2 will be created from column RDL[2]. Byname access is only currently supported for FITS binary tables (as a special case, you can specify byname as the format in a filecap file).

For tables where byname formats are acceptable, you can list the available column names with LIST TABLE.

If you specify the format as 'bycolumn', the list is expected to be a list of pairs of values (similar to the regular READ { x 1 y 2 ... } command). The first element of each pair is the name of a vector, the second may be either a number or a column name (if supported). The number gives the desired column with respect to the current format string. For example,

	TABLE 'd*' file
	READ TABLE 'bycolumn' { x 1 y 2 }

will read x and y from the first two columns of the file, whereas

	TABLE 'x8d*' file
	READ TABLE 'bycolumn' { x 1 y 2 }

will read x and y from the second and third columns of the file, assuming that a double (the d) is eight bytes wide.

Instead of a number, you may be able to specify a column name, for example

	READ TABLE 'bycolumn' { x_u rowc[0] x_g rowc[2] }

but this depends on your chosen $table_type having support for byname access. In general you will not be able to mix name- and column- orientated access (for example, we do not support column orientated access to FITS binary tables unless you provide a format).

TABLE's formats are strings (i.e. they must be enclosed with "). consisting of a set of types followed by optional repeat counts, for example 'x12f5d*' would specify a table, each of whose rows had 12 unwanted bytes, 5 floats, and the rest integers. Format letters are:

a
A 1-byte ascii string
c
A 1-byte char
d
An 8-byte double
f
A 4-byte float
i
A 4-byte int
l
A long int (may be 8 bytes on some machines)
s
A 2-byte int
x
1 byte to skip (a space may be used instead of an x)

and each may be followed by a repeat count (default: 1), or a *, meaning to repeat as many times as fits into a row. In all cases except a, the repeat count refers to how many columns there are (so d4 means 4 doubles); for a it refers to the length of the string (so a4 is one 4-byte string). Note that the maximum length of an a table is the length of an element of a string-valued vector (usually 40, but configurable by whoever built your copy of SM).

Header keywords may be available with the DEFINE name IMAGE command.


Termtype

Syntax: TERMTYPE word [ INTEGER ]

Set the terminal type to be WORD. This has nothing to do with graphics, but is to do with the history and macro editors. WORD is case-sensitive. With two exceptions, the properties of the terminal will be read from the termcap file (see section Termcap -- A Terminal Database). If WORD is dumb SM tries to support editing on a (very) stupid terminal. If this isn't what you want, for example you are running SM from within emacs TERMTYPE none is equivalent to starting SM with the -s flag and entirely disables input line editing (although commands are still remembered so commands like playback and hcopy will still work). You can turn editing back on by issuing a TERMTYPE command with a valid terminal name.

For most purposes you don't even need to use this command, as when SM starts up it reads the value of the environment variable TERM (under Unix) or logical variable (under VMS) it effectively issues a TERMTYPE command with its value as argument. If you have a term entry in your `.sm' file this takes precedence over any TERM variable. For example, a term entry of selanar -21 is equivalent to the command TERMTYPE selanar -21.

You also should not have to use the optional INTEGER argument, which specifies the number of lines that will appear at a time when LISTing things, as this information is usually derived from termcap. If you are using a window system, then termcap may be wrong and this argument may be useful. Another exception occurs when you wish to disable cursor motion to avoid having your graphs scrolling off the screen. If this concerns you see section Termcap -- A Terminal Database.


Ticksize

Syntax: TICKSIZE SMALLX BIGX SMALLY BIGY

Determine tick intervals for BOX. SMALLX refers to the interval between small tick marks on the x axis, BIGX refers to the interval between large ticks and so forth. If BIG is 0, the axis routine will supply its own intervals according to the label limits. If SMALL < 0, the axis will have logarithmic tick spacing and BOX assumes that the limits are logarithms, e.g. -2 and 2 refers to limits of 0.01 and 100. If both BIG and SMALL are 0, you'll get SM's default behaviour.

Negative values of SMALL and BIG are interpreted as specifying the tickspacing in the decade 1:10, and are scaled to fit the decades actually plotted. For instance, if you say

LIMITS 0 1 3 4
TICKSIZE -1 10 -0.1 1 BOX

then the x-axis will have small ticks at 2, 3, ..., 9 and big ticks at 1 and 10, while the y axis will have small ticks at 1100, 1200, 1300, ... and big ticks at 1000, 2000, 3000, ... (You might want to use NOTATION to stop SM using exponential notation for the 10000 label). The most usual TICKSIZE is probably -1 10, and this may be written -1 0 for backwards compatibility.

Occasionally you may want to use the same tickspacing in all decades of your plot. To do this make BIG negative also in which case the spacing used for the first decade plotted will be used for all decades. (Note that this means that if the axis is plotted backwards then the value from the largest decade will be used):

LIMITS 1.9 2.1 2.1 1.9
TICKSIZE -0.1 -1 -0.1 -1 BOX

this is a good way to make an axis very crowded!

If you really cannot use TICKSIZE to accomplish your needs, you can use AXIS and provide vectors specifying the positions of the big and little ticks, and even the axis labels.


User

Syntax: USER ABORT [ string ]
        USER integer string

The first form, USER ABORT, is used to generate a syntax error, and return to the prompt (with a traceback if you've requested one with the traceback variable). The command reported as the offender is string if provided, otherwise USER ABORT.

If you want to catch these errors you can define a macro abort_handler which will be called with the message as all of its arguments instead of causing SM to return to the command prompt. For example, I use

abort_handler 111	# catch USER ABORT
		        echo Caught user abort: $1
        		#

Note that the argument extends to the end of the line -- this is important! If abort_handler took a single argument, what would the command USER ABORT good bye world do? First the handler would be called as abort_handler good bye world. It'd pull off the first argument good and print it and SM would continue to process bye as a command. It's neither a command nor a macro, so the default macro_error_handler executes USER ABORT bye is not a macro; aborting. Rest of line: world. The abort handler pulls of the bye, and tries to execute is --- and we have an infinite recursion that is broken only by a ^C or by reaching the maximum depth to which SM will nest abort handlers.

The other, with an integer, calls a function called `userfn', passing the integer and the string as arguments, both are passed by address as if SM were written in fortran (string is passed as a NUL terminated C string, though).

This function is provided to allow users without C compilers to make additions to the main grammar, but whether it is really useful is a different matter. Currently, if integer is non-zero then both integer and string are printed unless integer is 1, in which case the command USER 1 r 1.23 is equivalent to SET r=1.23 (only constants are allowed).

If string is dump you'll get a macro stack trace, and if it's segv you'll get a segmentation violation (on purpose). If you really want some new functionality, send us mail.


Verbose

Syntax: VERBOSE INTEGER

Make SM produce output on what it is doing if INTEGER is > 0. Setting VERBOSE to 0 is a way of only listing `important' (non-system) macros, and generally getting a little peace and quiet. It has the considerable disadvantage that you can think that you are reading data from files, while actually something is wrong. For this reason the default value is 1. A value of 2 or more is basically useful for debugging. If you get some nondescript syntax error and don't know where it is coming from, VERBOSE of 3 or 4 will trace your programme, and should help find the problem. The original error message will tell you which macro SM thinks it is processing when the error occurred but it will be wrong if the macro had been fully scanned when the error is detected. In this case it will report a parent of the current macro. The reason for this behaviour is related to why RETURN can return from the wrong place (see section The Command Interpreter).

If you want to know the current value of VERBOSE you can use the SHOW command (actually a macro), or try

DEFINE verbose DELETE echo Verbose: $verbose

which is (of course) what SHOW does anyway.

If verbose is one or more SM will:

if INTEGER is three or greater, then also :

if INTEGER is four or greater, then also :

if INTEGER is five or greater, then also :

If you set a negative verbosity, then if the parser was compiled with DEBUG defined, you'll get a veritable torrent of debugging information. Use another negative VERBOSE command to turn it off again.


Version

Syntax: VERSION 

Return a string identifying the version of SM in use. If you have any reason to communicate with SM's authors, we'll want to know which version you are running. As a matter of fact, version is a macro to print $version.


Viewpoint

Syntax: VIEWPOINT theta phi l

Surfaces are drawn from a direction (THETA,PHI), and projected onto a surface passing through the origin. The projection is from a point L away from the nearest corner of the cube containing the image. If L is positive a perspective projection is used; if it is 0 the viewpoint is taken to be infinitely far from the surface, and if it is negative an axonometric projection is used (i.e. the surface is projected from infinity onto the x-z plane).

The coordinate system is such that the z-axis is THETA=90, the x-axis is (THETA,PHI) = (0,0), and the coordinate system is right handed. Angles are taken to be in degrees, with theta lying in [-90,90] and phi lies in [-180,180]. The nearest corner of the cube containing the surface is projected onto the point (0,0).

There are some useful macros in the file `surfaces'; say load surfaces to read them. If VERBOSE is one or more, a helpful header will be printed when you load the file.


Whatis

Syntax: Whatis ( expr )

WHATIS(something) has a value depending on what something is:

a number:       0
not a number:           set 01 bit    (bit 0)
  a macro:              set 02 bit    (bit 1)
  a variable:           set 04 bit    (bit 2)
  a vector:             set 010 bit   (bit 3)
     a float vector:    set 040 bit   (bit 5)
     a string vector:   set 0100 bit  (bit 6)
  a keyword:            set 020 bit   (bit 4)

So if "aa" is the name of a string vector, WHATIS(aa) has the octal value 0111, or 73, whereas WHATIS(HELP) has the value 021, or 17, and WHATIS(1) is 0. There is a macro in `utils' called is_set that tests if WHATIS sets a particular bit, for example

	if(is_set(kkk,3)) { echo kkk is a vector }

tests if bit 3 (vector) is set for "kkk" and prints its findings; it's easier to say

	if(is_vector(kkk)) { echo kkk is a vector }

which does the test for you.


Window

Syntax: WINDOW nx ny x y

WINDOW makes the current plot location the window at (x,y), where there are nx windows across and ny windows up and down. WINDOW 1 1 1 1 resets the plot location to the entire plot area. The size and placement of the windows is decided by the value of EXPAND when the WINDOW commands are issued, so be sure that EXPAND has the same value for every window in a set. (It's used to figure out the axis labels, and spacings between boxes). While plotting to a given window you can of course change EXPAND to your heart's content.

If the number of windows in either the x or y direction is negative no space is left between the boxes in that direction (try DO i=1,3 { WINDOW 1 -3 1 $i BOX }). It's possible to overload `window' and `box' to only label external axes in blocks of touching boxes.

If either x or y is specified as, e.g. 2:4, the window is set to cover the range 2-4 (i.e. the part of the screen covered by windows 2, 3, and 4). Note that this feature can be used to split the screen in arbitrary ways, e.g.

    window -1 -6 1 1:5 box
    window -1 -6 1 6 box

(or you could say window -20 -20 15:19 15:19 as an alternative to a LOCATION command).

If you don't want boxes that touch, but you don't like the gaps left between boxes by the WINDOW command, you can now do something about it legally, without lying to SM. After we calculate the widths of the `gutters' between the windows that we think that you need, they are multiplied by the values of the SM variables x_gutter and y_gutter, so if you think that the spacing is too large in the x direction you can say

define x_gutter 0.5
window 2 2 1 1 box
window 2 2 1 2 box

to make things look better.

It's confusing to change LOCATIONs while using WINDOWs; you probably want to say WINDOW 1 1 1 1 first.


Write

Syntax: WRITE STANDARD string
        WRITE [+] WORD string
        WRITE HISTORY WORD

WRITE STANDARD writes a string, followed by a newline, to the standard output. The string is taken to be the rest of the line up to a carriage return (which may be written explicitly as \n). The macro echo is usually used as an abbreviation for this command. WRITE WORD is similar, except that the string is written to file WORD. If the filename is the same as the previous WRITE, or if you preface the filename with a +, the string is appended, otherwise the file is overwritten.

WRITE HISTORY WORD, writes macro WORD onto the end of the history list.

For MACRO WRITE, see under macros.


Xlabel

Syntax: XLABEL str

Write the label str centered under the x axis made by BOX. The string is taken to be the rest of the line up to a carriage return (which may be written explicitly as \n). If you think that the label is badly positioned you can say things like

XLABEL \raise-500My X-axis Label

(providing that you use TeX-style fonts, of course)

If the label is too tall it may overlap with the numerical tickmark labels. If VERBOSE is one or more, you'll be warned about this, and a suggested change to the plot LOCATION will be suggested. This moves the entire plot; it is your responsibility to reset it later if appropriate.

If ANGLE is non-zero, it will be used to determine the direction of the label, otherwise it is parallel to the x axis.

See section Drawing Labels and SM's TeX Emulation, for a description of how to enter a label with funny characters, sub- and super-scripts, and so forth.

If EXPAND is set to exactly 1, and ANGLE is exactly 0, then SM will use hardware fonts, when available, in writing labels. This is faster, but if you don't like it say "EXPAND 1.00001", or start the string with a \0 which does nothing, but forces the software character set.


Ylabel

Syntax: YLABEL str

Write the label str centered to the left of the yaxis made by BOX. The string is taken to be the rest of the line up to a carriage return (which may be written explicitly as \n). If you think that the label is badly positioned you can say things like

YLABEL \raise500My Y-axis Label

(providing that you use TeX-style fonts, of course)

If the label is too tall it may overlap with the numerical tickmark labels. If VERBOSE is one or more, you'll be warned about this, and a suggested change to the plot LOCATION will be suggested. This moves the entire plot; it is your responsibility to reset it later if appropriate.

If ANGLE is non-zero, it will be used to determine the direction of the label, otherwise it is parallel to the y axis (ANGLE 360 will achieve horizontal labels).

See section Drawing Labels and SM's TeX Emulation, for a description of how to enter a label with funny characters, sub- and super-scripts, and so forth.

If EXPAND is set to exactly 1, and ANGLE is exactly 0, then SM will use hardware fonts, when available, in writing labels. This is faster, but if you don't like it say "EXPAND 1.00001", or start the string with a \0 which does nothing, but forces the software character set.


Go to the first, previous, next, last section, table of contents.