A brief introduction to SM

x-y plots | error bars | linear fits | histograms | multiple plots | surfaces & contours | in/output

SM is a versatile plotting utility which grew out of a graphics package called mongo (SM is formerly "supermongo"). It is widely used in the astronomical community.

The utility can do most anything required of a scientific plotting package--2D plots, histograms, surface and contour plots, data manipulation etc. While it does not have all of the graphics sophistication of Mathematica or Maple, it is easy to use and can provide a quick and effective way of examining data. What weaknesses it possesses in terms of predefined functions are offset by the fact that users can define their own macros.

This page is intended to be a "least-action" guide for information that will you help you accomplish a few very specific things with SM. For more thorough and accurate information, please try the official SM tutorial or the html version of the SM manual.

(you typehost> sm

(Note: the hash (#) symbol is used here to indicate the start of a comment.) This should cause a new plotting window to be created, and now you are ready to proceed. Bear in mind the following useful actions which can be taken during a session:: dev X11 #define output "device", a window in the X-windows system.

- end the
session by typing
**quit**; - clear the plotting device (making it
ready for a new plot) by typing
**erase**; and - get on-line help
with the
**help**command.

(Again, the # symbol indicates the beginning of a comment.) Note: x is vector -- a list of N numbers x[0],x[1],...x[N-1] determined by the: set x=0,10,2# set x=(0,2,4,..10)

: set y=sin(x**(1/2))# pack y values

: limits -0.5 10.5 -1.1 1.1 #set limits of axes "by hand" (could've usedlimits x y, also)

: box# draw the axes using the limits just specified

: connect x y# connect the dots

: poi x y# make points too, using abbreviation poi

The read statement created the vectors x and y (or recreated them if they were already defined) from the N elements of the first two columns of the file. x[0] comes from the first column of the first line in the file while y[N-1] is from teh second column of the N line of the file (excluding comment lines).: erase #this clears the plotting window

: data file.dat #tell sm the name of your data file (file.dat)

: read {x 1 y 2} #read the file, store column 1 in vector x (col 2 -> y)

: limits x y #set ranges of plot axes based on values in vectors x and y

: box #create the borders of the plot, tickmarks and all

: points x y #plot the data points stored in vectors x and y.

: xlabel X (some units)# label horizontal axis

: ylabel Y (other units)# " vertical ".

Note that errorbars need not be symmetrical (the reason for the two calls to: data errfil.dat #name of data file

: read {x 1 y 2 sy 3} #read the file containing x y and sigma_y.

: limits x y #set ranges of plot axes based on values in vectors x and y

: box #create the borders of the plot, tickmarks and all

: points x y #plot the data points stored in vectors x and y.

: errorbar x y sy 2 #plot upper half of error bar (2 => +y dir)

: errorbar x y sy 4 #plot upper half of error bar (4 => -y dir)

Note: the lsq function can have 2 arguments or 4 (or 5--type help lsq) When it has 2 args, it merely does the bestfit to the line y = $a*x+$b, setting the values of variables $a, $b. When it has four arguments,: lsq x y #do a least-squares fit of a line to x vs. y

: calc $a #print the value of variable $a = slope of the best-fit line

: calc $b #print y-intercept of best-fit.

: lsq x y x q #do lsq on x y, set q=$a*x+$b

: con x q #draw lines between points x vs. q

You can do a weighted least-squares fit, as when you have known errors in the dependent variable as in the previous exercise with error bars. To incorporate these uncertainties, in the fitting routine, try

(see the help information on: set w=1/(sy*sy) #set weight to 1/sigma_y^2

: wlsq x y w #do a least-squares fit of a line to x vs. y

Note: see the help pages for keyword: set q = -100,100,5# let this vector define the histogram bins of width=5.

: set h=histogram(y:q)# bin the (predefined) vector y as per bin locations given by q.

: limits q h# set axis ranges.

: histogram q h# this plots the histogram.

: box# finishing touch, maybe.

will direct subsequent plotting output to the lower half of the page. Use: window 1 2 1 1# two windows, stacked vertically, use lower one

to reset to one window. The help pages are worth looking at, as they give some details on how to control more directly the subdivision of area for the plotting windows.: window 1 1 1 1# (yawn)

After this line is in place (re)start SM.file_type C

(An example of a file in SM's "C" format is
in **~p5720/data/slc.map_thinned.sm**; it
has elevations for the SLC area on a 51x51 grid. Note elevations
are in meters, between 1000m and 4000m.)

To make a surface plot of an image file, try the following:

That should do it. Use: image "fil.dat" 0 1 0 1# read im image data, set image to lie in x,y=(0,1).

: limits 0 1 0 1# set limits to match image (actually these are default values).

: surface 1 0 5000# draw surface, 2 => top surface only; 0,5000 are z-axis limits.

: load surfaces# load in 3d plotting specials.

: overload viewpoint 1# redefine SM's viewpoint command

: overload surface 1# redefine the surface command

: surface# like above, but it calcs the z limits automatically

: box3# put on proj. x,y,z, axes + labels.

Contour plots:
For contour plots, try the following perscription. (The
file **~p5720/data/slc.map.sm** is a "C" format datafile
that has elevations for the SLC area on a 201x201 point grid.)

If you want use different units for the x and y axes than the grid size in the above example, you can either user the: image "fil.dat"# as above, but w/default image size, locale (see help).

: limits 0 200 0 200# assuming image size is (nx,ny) =(201,201)

: levels { 1000 2000 3000 }# define contour levels (z values!) to plot

: lweight 2# set thickness of line to be moderately heavy

: contour# generates the contours.

: lweight 1. # set line weight back to normal

: levels { 500 1500 2500 3500 }# define new contour levels

: contour# and plot the new levels

: box# afterthought(?) draw axes

A couple of hints:

- In your text file keep one SM command per line.
- Begin your command list with
**erase**to start with a clean slate. - Remember, # starts a comment (commands after it on same line are ignored)

BE SURE that your: dev postfile file.ps# setup for output to postscript file

: execute sm_commands.file# make the plot....

: dev X11# changing the device triggers SM to write the .ps file

**
Local hint for JPEG output**

If you want to create a JPEG file (for display on the web, or when required in a homework assignment!) try

Then, when you return to your shell, convert to JPEG formation using the Un*x commands:: dev pbm file.pbm# setup for output to Pixel Bit Map file

: execute sm_commands.file# make the plot....

: dev X11# changing the device triggers SM to write the .pbm file

This converts the .pbm file into a Pixel Gray Map format (.pgm), which is piped to the "cjpeg" utility. Cjpeg does the final conversion to a .jpg file. Be sure to type this VERBATIM! See the "man" or "info" pages if you are curious about the arguments. The final redirect from cjpeg is important -- you may find your terminal in a very bad state if you do not redirect the output!pbmtopgm 1 1 file.pbm | cjpeg > ! file.jpg

**dev** sets the output device;**dev X11** => X-windows; and

**dev postfile file.ps** =>. write to postscript file named
file.ps

**set** creates variables (scalars or vectors);

**set x={0 10 20
30}** creates a vector x with dimension 4 such that x[0] = 0.0, x[1]
= 10.0, ...x[3] = 30.0.

**set
x=0,30,10**, has the same effect; it means to pack x with values of 0 to 40, using steps of 10.

**set y=4.0*x**2+3.2*x-23** creates y with the same dimension as x then packs it, element for element, with the quadratic function of x.

**data file.dat** loads a filename into the guts of sm to **read** later.

**read** reads the file specified by the **data** command.
**read { x 1 y 2 z 3}** packs x with first column of numbers, y with 2nd....

**erase** clears the output device (wipes the "page" clean).

**limits** sets the ranges for the x and y axes.

**limits x
y** figures out nice horiz. and vert. axis ranges from data in
vectors x and y.

**limits 100.1 200 -10 10** set horiz. axis
range of 100.1 to 200, and vert. axis range of -10 to 10.

**box** plots the axes, tickmarks and number labels indicating
range.

**points x y** plots the points in x,y as ordered pairs.
Note: x and y must have the same dimension (# of elements).

**ptype # #** can be used to change the type of point (e.g., dot,
circle)--see the **help** info.

**expand #** changes the
size BUT it also changes the size of other things, too, like axis labels.

**connect x y** draws lines between points x,y.

**ltype #** can be used to choose line type (solid, dashed, etc.).
**lweight #** changes the weight or thickness of the lines--like
**expand**, it is global in that other things like points, axis labels,
are affected by the most recent setting of **lweight**.

**apropos** allows you to search for keywords in the online help files.

**quit** exits SM.

- You can use 3-letter abbreviations of some commands like
**lim**for**limits**,**con**for**connect**, etc. - You can use the
**set**command to define data vectors which are subsets of other vectors. For example, suppose vectors x,y, and z all have the same dimension (e.g., they have all been read from the same data file). If you want to plot only x-y data that are restricted to some range in z, you can do so by working with two new vectors defined as follows:**: set p = x if (z > 2 && z < 10)**# p gets x values when 2 < z < 10

**: set q = y if (z > 2 && z < 10)**# q gets y values when 2 < z < 10

- You can get info about a vector using the
**calc**command:**: calc dimen(x)**# print the dimension of x

**: calc sum(x)/dimen(x)**# sum x, divide by # of elements -- this gets the avg x value

- The
**data**command may require double-quotes if your data filename contains slashes or minus signs. - Be sure to use
**dev X11**if you want to see your display on a system running X.

**Failure to read in data files correctly?**The file format is pretty specific:**sm**wants columns of numbers only, except that you can comment out lines with a hash (**#**) symbol at the beginning of a line. There can be a fair number of columns (I don't know what the limit is, certainly > 10) but if the number changes from one line to the next,**read**will fail. If a line is blank then**read**will read no further, and it may whine about it if it found spaces or tab characters. If, at the end of the file, the last line doesn't have a new-line (carriage-return) character, that may cause trouble as well.**Unable to see any output?**Type**dev X11**to bring up an X-plotting window.

bcb 11-Sep-98.