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.
In this example we plot a function y=sin(x**(1/2)). First we must define
the vector x, for example in the range of 0 to 10, then we set the
y values.
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
(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:
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.)
A couple of hints:
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
dev sets the output device;
set creates variables (scalars or vectors);
data file.dat loads a filename into the guts of sm to read later.
erase clears the output device (wipes the "page" clean).
limits sets the ranges for the x and y axes.
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).
connect x y draws lines between points x,y.
apropos allows you to search for keywords in the online help files.
quit exits SM.
Getting started.
Below are some example exercises to learn a few of the things one can
do with sm. To begin an sm session, type sm
into an xterm shell:
host> sm
(you type sm only; host might be darkstar for example). SM's
prompt is a colon (:). Next you may need to specify a plotting
device; here let's assume for now that you want to see your plot
as a new window in X. Type in
: dev X11 # define output "device", a window in the
X-windows system.
(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:
Plotting a function.
: set x=0,10,2 # set x=(0,2,4,..10)
(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
setcommand. Also note: we could define x (or y or both) by reading
it from a file as in the next example.
: 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 used limits 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
Plotting a set of data points in a file.
Make a data file. It should be ASCII text (not binary), with x,y
values listed in two columns (no commas, please). Note that SM will
stop reading data after it encounters the first "unexpected" part of
the file (e.g., the end of file, a blank line, non-numeric characters,
a change in the number of columns). Lines which begin with a hash (#)
are comments and are ignored without ill effect when SM reads a data
file.
: erase # this clears the plotting window
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).
: 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 ".
Plotting error bars x-y data
Suppose now that a data file has three columns where the
first two are independent and dependent variables (x,y) and the
third is the errors associated with y. To plot error bars, use
: data errfil.dat # name of data file
Note that errorbars need not be symmetrical (the reason for the two
calls to errorbar above) and the you can put them along x
direction as well. (Of course these point+errorbar commands will work on any
vectors, not just those read in from the 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)
Fitting a line to the x-y data
: lsq x y # do a least-squares fit of a line to x vs. y
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 p q it does the fit to x and y, then it
looks at vector p, assumed to be a list of x-values, and creates (or
recreates) a vector q such that q = $a*p+$b. In the above example, x
was used as the list of x-values at which to evaluate q. You probably
don't want to write lsq x y x y because this will overwrite
data stored in vector y with the best-fit values.
: 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
: set w=1/(sy*sy) # set weight to 1/sigma_y^2
(see the help information on wlsq).
: wlsq x y w # do a least-squares fit of a line to x vs. y
Generating a histogram
SM's apropos [keyword] help facility will flag several occurances
of the keyword "histogram". It is used in a context dependnet way,
as follows:
: set q = -100,100,5 # let this vector define the histogram bins of width=5.
Note: see the help pages for keyword arithmetic for a discussion
on the use of histogram(a:b). (For example, b must be sorted, and
the behavior differs depending on whether the bins are equally space.
: 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.
More than one plot on a page
The window command allows you to plot more than one
graph on a physical page.
The command takes four arguments, the first two are the
number of windows along the horizontal and verticle axes
(repsectively), while the third and fourth are the "coordinates"
(1..nx,1..ny) of the window to which subsequent output will
be sent.
For example,
: window 1 2 1 1 # two windows, stacked vertically, use lower one
will direct subsequent plotting output to the lower half of the page.
Use
: window 1 1 1 1 # (yawn)
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.
Image plotting: surfaces and contours
SM can plot image data, but the data must be in specific formats. Here
we choose the "C" formats as explained in help image.
To do so,
copy/create a .sm file in your home directory (for example, see
~p5720/.sm) and be sure it contains the following line:
file_type C
After this line is in place (re)start SM.
: image "fil.dat" 0 1 0 1
# read im image data, set image to lie in x,y=(0,1).
That should do it. Use viewpoint
to change perspective. Type help surface to see other possibilities.
Note load surface allows you to draw projected 3D axes:
: 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.
: image "fil.dat" # as above, but w/default image size, locale
(see help).
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
command with 5 arguments as in the surface plot example, or you
could even just reset the limits after you draw the contours
but before you draw the axes with the box command!
: 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
Input (read-n-execute)
SM can read and execute a list of commands, like the examples given
above, directly from a text file. Use execute sm_commands.file, or
input sm_commands.file (although this latter may not work).
Output (file dump)
SM's output can be directed with the device command. To make a
postscript file that contains a plot as directed from the commands in
some file sm_commands.file (an emacs-generated text file with a
line-by-line list of SM commands, for
example), try
: dev postfile file.ps # setup for output to postscript file
BE SURE that your sm_commands.file does not have
a dev command in it or you may get nothing dumped to the postscript
file! (Also, note that you needn't use the execute command--that's
just a convenience. You could type all plotting instructions in directly.)
: execute sm_commands.file # make the plot....
: dev X11 # changing the device triggers SM to write the .ps file
: dev pbm file.pbm # setup for output to Pixel Bit Map file
Then, when you return to your shell, convert to JPEG formation using
the Un*x commands:
: execute sm_commands.file # make the plot....
: dev X11 # changing the device triggers SM to write the .pbm file
pbmtopgm 1 1 file.pbm | cjpeg > ! file.jpg
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!
Overview of the most important commands.
Here is a list of commonly used commands. For each, you should
type the most important one, help (command), for more details.
dev X11 => X-windows; and
dev postfile file.ps =>. write to postscript file named
file.ps
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.
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....
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.
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.
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.
Hints
Some potentially useful features of SM.
: set p = x if (z > 2 && z < 10) # p gets x values when 2 < z < 10
Then just plot p,q in the usual manner.
: set q = y if (z > 2 && z < 10) # q gets y values when 2 < z < 10
: 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
Some quick comments to avoid problems:
Troubleshooting
bcb 11-Sep-98.