Go to the previous, next section.
limits(0.0,1.0,0.0,1.0);
. On VMS, and with some unix systems (notably
HPUX and AIX), if you are writing fortran, you must
prepend
an `f' to the command - call flimits(0.0,1.0,0.0,1.0)
. If you forget this
`f', your programmes will compile, but they `won't' work. (They'll give
segmentation violations, most likely. Why? Because you will be calling the
C functions directly, not the Fortran interface functions, and the languages
have different ways of passing arguments, so e.g. you will pass the address of
the variable from your Fortran program to a C function that expects to get the
value of the variable. This translation is precisely what the interface
functions are set up to do for you).
@footnote #{Under Unix
the loader can often distinguish fortran from C, so you may not
need the `f' -- call limits(0.0,1.0,0.0,1.0)
}
This situation is further complicated by the fact that, to avoid naming
conflicts with operating system library functions, SM is often built with the
prefix `sm_' prepended to the function name, so e.g. when you issue the box
command, the subroutine that is called is named sm_box
. Then, if you
use callable SM, from C the function name is sm_box
, but from Fortran
on VMS and other systems, the function you must call is fsm_box
.
(The functions are renamed by the SM guru by defining the macro RENAME
in `options.h' when compiling SM. And in fact, exactly how the name is
changed is up to the guru. `sm_' is merely the common, and default, choice).
So how are you supposed to know what to call the functions? Well, our best
suggestion is to ask the person who build SM on your system (unless you are
that person, in which case, N.B. the SM distribution does define
RENAME
by default). The second best suggestion is to look in
`libplotsub.a' (or `libplotsub.olb' on VMS systems), and see what
the names of the functions are. On VMS, try this:
lib/list/names libplotsub/liband look at the names it lists under module
INTERFACE
. On a unix system
you can use strings. But it is a bit messier, so you should filter the output
e.g. as follows
strings libplotsub.a | grep errorbarIf you see things in the output like
sm_errorbar
, then you know that
the functions were renamed. If you see things like fsm_errorbar
, then
you know this is one of those machines where you have to prepend the `f' for
the fortran interface functions.
If you used an ANSI compiler to link SM (or your guru did) then you
will need to provide prototypes for the SM functions that you call if
you use the C interface (Fortran knows nothing of such things).
This can be done by including the file `sm_declare.h'. You need
the prototypes as some SM functions expect float
(not double
)
arguments.
In what follows, we will assume that you are not writing fortran under VMS, so we will omit the leading effs.
To use SM functions, you must link with appropriate libraries. You
will always need to link with the three SM libraries, libplotsub
,
libdevices
, and libutils
in that order. Specifically,
under Unix, you'll need to include the files `libplotsub.a',
`libdevices.a', and `libutils.a'
when you link (it's probably easier to use -lplotsub -ldevices -lutils
,
along with a -Ldir
if needed).
and under VMS you'll
need `libplotsub.olb/lib', `libdevices.olb/lib', and `libutils.olb/lib'. I can't tell you where
they'll be on your system.
In addition, you may need to link (after utils
)
any libraries used by
the devices that have been compiled into your version of SM.
For example, if you use the X-windows driver, you'll need to link with
the X-library (-lX
). Consult a local guru in case of any trouble -
the person who installed SM has had to work this out already.
A list of functions giving the calling sequence for all the
available functions follows, but first an example. Note especially the use of
graphics
and alpha
to set the terminal to graphics mode, and
return
to a normal terminal afterwards. We would recommend always calling these,
if they do nothing (e.g. on a laser printer) they'll do no harm.
A related function is gflush()
which will update graphics on the
screen, for instance with stdgraph where output is usually buffered.
Some devices (such as GL on an SGI, or X-windows on machines without
backing store such as RS/6000's) need some help from you to redraw the
screen. You do this by calling redraw
whenever you are waiting
for input, passing it `0' (the file descriptor of standard input, for
those of you familiar with C). When input is ready, redraw
will
return and your application can proceed. It should do no harm on systems
where it does no good.
There are examples of programmes (both C and fortran)
calling SM in the directory sm/callable
; you might want to look at them
before starting your own project.
integer NXY parameter (NXY=20) integer sm_device integer i real x(NXY),y(NXY) c do 1 i=1,NXY x(i) = i y(i) = i*i 1 continue c if(sm_device('hirez') .lt. 0) then print *,'Can"t open hirez' stop endif call sm_graphics call sm_defvar("TeX_strings","1") call sm_limits(-1.,22.,0.,500.) call sm_ctype('red') call sm_box(1,2,0,0) call sm_ptype(40.,1) call sm_points(x,y,NXY) call sm_xlabel('X axis') call sm_ylabel('Not x axis') call sm_alpha print *,'hit any key to exit' call sm_redraw(0) read(5,*) i endRemember, if you were running VMS, HPUX, or AIX then all those calls would start `f' -
call fsm_graphics
and so forth.
Note that box
takes all of its four possible arguments, and that
commands such as points
add an argument to specify the number
of points to plot.
You must, of course, ensure that you use the correct type of variables,
passing integers or reals as required (and as listed below). If you are
using C, you must carefully distinguish between passing by value, and
passing by address (which we only use when an array is expected, and
for returning a cursor position).
The functions are as follows. For fuller definitions of the
arguments look at the main description of the command. The only ones
that are different are conn
for connect
(due to a collision
with a system routine), and curs
, defvar
, and plotsym
because they don't
quite correspond to any interactive commands. A common source of
trouble is not noticing that the ptype
call is the vector
form of the command, so to set a ptype of `4 1' you must
say ptype(41.0,1)
.
The arguments are declared in fortran in this list. real x(n)
means that x
is an array of size n.
`Real' means single precision. (So in C,
character
char *
;
integer
int
;
real
float
;
real()
float *
. We deal with converting the
calling conventions from one language to another, but note comments at
the bottom of this table.)
alpha
angle(a)
axis(a1,a2,as,ab,ax,ay,al,il,ic)
box(x1,y1,x2,y2)
conn(x,y,n)
ctype(c)
curs(x,y,k)
defvar(str1,str2)
device(str)
dot
draw(x,y)
erase
errorbar(x,y,e,k,n)
expand(e)
format(xf,yf)
gflush
graphics
grelocate(x,y)
grid(i)
hardcopy
histogram(x,y,n)
identification(str)
label(str)
limits(x1,x2,y1,y2)
location(x1,x2,y1,y2)
ltype(lt)
lweight(lw)
notation(xl,xh,yl,yh)
plotsym(x,y,n,sym,ns)
points(x,y,n)
ptype(pp,n)
putlabel(i,str)
redraw(i)
relocate(x,y)
shade(delta,x,y,n,type)
ticksize(xs,xb,ys,yb)
window(nx,ny,x,y)
toscreen(ux,uy,sx,sy)
xlabel(str)
ylabel(str)
Device
returns 0 if it opens the requested device, or -1 if it
fails. You must declare device
as returning integer, of course.
Curs
returns after you hit any key, returning the coordinates of
the point, and the key struck as an integer (e.g. `a' as 97 in ascii).
In C, all three arguments are pointers, two to float and one to int.
Defvar
defines a variable, it is identical to the interactive command
DEFINE name value
. It is only used to define variables that are
significant to SM, currently file_type
and TeX_strings
.
Fortran users might or might not need to double \
s in TeX labels,
depending on the foibles of your compilers (you are more
likely to need the doubled \\
under unix).
Plotsym
is like first
using the PTYPE { ... 2
command to define sym
, and then
POINTS
to plot x against y. The ns
array consists of triples
of integers, (move x y)
where move is 1 to move the plot pointer,
0 otherwise. This is not quite the same as the interactive command,
but doesn't involve any characters. The move
integer may not be omitted.
The `file descriptor' that redraw
demands will almost always be
0
(standard input) on unix boxes; if it is needed by VMS or
other operating systems I will add a note here when I write the device driver.
Shade shades the inside of the curve specified by x and y if type is
1, or the area below a histogram specified by x and y if type is 2.
The line spacing in screen coordinates is delta.
You can use toscreen
to convert from user to screen coordinates (which
run from 0 to 32767, and are used by grelocate
). The second pair
of arguments should be pointers to int if called from C.
The use of the 2-D functions may require a little more explanation.
If you want to use SM to read your data,
producing contour plots is very similar to doing so interactively, with the
difference that instead of defining the variable file_type
, you
must call the function filetype
with the desired value as the argument
before reading the data. This is equivalent to calling defvar
to
define the variable file_type
, and is only supported for
backwards compatibility.
As an alternative, you can fill your own data array,
and pass it to SM to be contoured with defimage
.
The function calls follow (again in fortran), followed by some explanation.
contour
defimage(arr,x1,x2,y1,y2,nx,ny)
delimage
filetype(type)
levels(l,n)
minmax(x,y)
readimage(file,x1,x2,y1,y2)
minmax
expects to be passed pointers to floats, and
the first argument to defimage
is not a 2-D array, but an array of
pointers to the rows of the image. x1, x2, y1, y2
specify the limits
as in the interactive IMAGE
command; if they are set to be 0.0 then
the dimensions of the array will be used. As an example, again in non-VMS
fortran:
integer NXY parameter (NXY=20) integer sm_device integer i,j real z(NXY,NXY),lev(NXY) c do 2 i=1,NXY do 1 i=1,NXY x(i,j) = (i-NXY/2)**2 + (j-1)**2 1 continue 2 continue c if(sm_device('postscript latypus') .ne. 0) then print *,'Can"t open printer' stop endif call sm_graphics call sm_limits(-1.,21.,-1.,21.) call sm_box(1,2,0,0) call sm_defimage(z,0.,20.,0.,20.,NXY,NXY) call sm_minmax(amin,amax) do i=1,NXY lev(i)=amin + (i - 1.)/(NXY - 1)*(amax - amin) 3 continue call sm_levels(lev,NXY) call sm_contour call sm_hardcopy call sm_alpha endIt is also possible to call the SM parser directly from your own programmes. This is usually done by people who have large data arrays that they want to plot, so we have also provided a call to define your arrays as SM vectors. To use this, your SM guru must build an extra library, (called `libparser.a' on unix systems). This is done with the command
make Parserin the top level SM source directory. If this has been done, you can link the parser into your code by including the flag
-lparser
before
the other SM libraries (but after any -L
flags). The programmes
`interp' and `finterp' in the `callable' directory provide
examples of calling SM's parser; `finterp.f' looks like:
real a(10) integer i do 1 i=1,10 a(i) = i 1 continue call sm_array_to_vector(a,10,'xyz') print *,'Calling SM parser...' call sm_parser('-q') print *,'Exited parser' endHere the array
a
(with 10 elements) is to be called xyz
in SM,
and SM is to be invoked with the command line options -q
. You can of
course define as many vectors as you feel like, but using DELETE
to
delete them from the parser is a serious error (i.e. don't!).
array_to_vector(arr,n,name)
parser(args)
array_to_vector
) (character args).
Go to the previous, next section.