If DIPSO can’t or won’t do something reasonably straightforward (e.g. a simple functional operation
on a single spectrum) — or even, if you’re ambitious, something quite complicated —
that you require of it, then you can avail yourself of the user interface. This consists of a
logical function, USER
, which gives simple and straightforward access to the contents of
the ‘current’ arrays; and two user-callable subroutines, UPUSH
and GETSTK
, which allow
you to respectively get data from and put data onto the stack. (These two routines are
described at the end of this section.) You are also free to use any GKS, or SGS routines you may
need.
If you want to do something that requires opening new input streams, it is recommended that you use streams 23-29 inclusive. DIPSO closes most i/o streams as soon as it has finished with them, but it always has stream 22 open, and you are strongly discouraged from using streams 5 and 6 for anything other than standard input and output (i.e. the designated device; normally the terminal when DIPSO is used interactively). (The reason that stream 22 is always open is that GKS sends its error messages to this stream. Such messages are more likely to annoy than enlighten DIPSO users!
To use the interface you will need to write a subprogram called USER
which should follow the example
given in $DIPSODIR/user.f
.
The example subroutine contains almost all the additional documentation needed to understand how to ‘do your own thing’. This documentation may seem a bit technical, but don’t be put off by that (consult one of your local computer devotees if in doubt); the interface is really very easy to use. As a bare minimum, you could copy the example subprogram and just add in your own IF block:
The USER
function delivers lots of variables for you to play with, but the essential contents of the
argument list are:
Sometimes you will want to treat PARAMS
as a character string (for example, it might be a filename); but
more often you will want to read numbers from it. You can do this in exactly the same way as DIPSO
does by calling the routine DECODE
:
where:
USER
by DIPSO.
The ‘PROMPTS’
must be left justified, separated by blanks, and terminate with a blank. (Have a look at
the $DIPSODIR/user.f
code for examples of how to use DECODE
.
Having written your USER
code, you can build your own dipso
binary.
You must first set the environment variable SYSTEM
appropriately for your system: alpha_OSF1
for
AXP OSF/1, or sun4_Solaris
for Sparc Solaris 2.x.
Then, you can compile and link a new binary by typing:
If you wish to link in subroutines contained in object modules sub1.o,
sub2.o etc, you should define
an environment variable MY_OBJECTS
specifying these object files:
This leaves you with a personal copy of dipso
in the directory you’re working in. You should then set
up an alias to run this version in preference to the system version:
(This section can be skipped by people who never make programming errors!)
DIPSO is equipped with a condition handler to prevent crashes. DIPSO shouldn’t give a crash in the
normal run of things (if you get one, please report it, giving fullest details possible — preferably a
macro file which always results in the crash), but it may well do so in user-supplied code. In this case,
you will normally want to disable the condition handler in order to get the system handler, which may
tell you where the crash occurred. To turn the handler off, the HANDLER
command can be invoked (use
HANDLER
0). On some flavours of UNIX, this may result in the program appearing to freeze
after a crash. If this happens, pressing control-C should return you normally to a system
prompt.
If your site has a ‘user-enhanced’ version of DIPSO that is used by several people, then it might
be convenient to put the executable into a local public directory. In this case you should
persuade your node manager to create such a directory, with appropriate protections, and give
it the environment variable LDIPSODIR
. The local version can then be run, of course, as
$LDIPSODIR/dipso
.
In response to the COMM
command, DIPSO first looks for a file $LDIPSODIR/command.hlp
, which will be
used if found. It will then go on to look for a file $DIPSODIR/comand.hlp
which it will also use if
found.
So it’s possible to put an appropriately modified version of command.hlp
into LDIPSODIR
to keep users
informed of local additions to available commands. The local version of command.lis
should contain
only the extra local commands, not the standard commands, and should be formatted like the
standard version.
Note, in previous versions of DIPSO, command information was stored in a file called command.lis
which had a different format to command.hlp
files and was processed differently. It is recommended
that any local command.lis
files still existing be converted into command.hlp
format (see
$DIPSODIR/comand.hlp
for a description of the format). If DIPSO finds a local old-style command.lis
file it will simply display its contents (as in previous versions of DIPSO) in preference to using
any new-style command.hlp
files. Note, however, that the extended functionality of the
COMM
command (i.e. word searches, command descriptions and classification) will not be
available.
It’s possible to give HELP
for local commands, too, although it can only be accessed as plain text (see
USEHTX
). The HELP
command in plain text mode first runs through $DIPSODIR/help.lis
but if it doesn’t
find a command name there, it will try to look for an $LDIPSODIR/lhelp.lis
, and search that for help
information. This file should match the format of $DIPSODIR/help.lis
, but need contain information
only on local commands.
The first thing that DIPSO does is look for a file called $LDIPSODIR/updates.lis
, and print out
anything it contains. So if you’ve made changes, you can announce them to your local community
through this mechanism.
If you want to do complex operations involving several data sets, you may well want to access data on the DIPSO stack. Well, you can; but first, you’ll need to understand a bit more about how DIPSO stores data.
A DIPSO data set contains a variety of information. First of all, there is a brief header string [CHARACTER*80 TITLE]. Then, of course, there are the X and Y data arrays [X(MAXPT), Y(MAXPT), MAXPT=64000], which contain the NPOINT pairs of data points. Now, in order to know where in the data any gaps occur, DIPSO maintains a separate ‘break’ array [BREAKS(MAXBRK), MAXBRK=1000] which contains the NBRK break points associated with the data set. A break point is the index, in the X and Y arrays, of the last point before a gap in the data set. Thus if there are 200 points in the data set, and there are breaks between the 7th and 8th, and 123rd and 124th, data points, then BREAKS(1)=7, BREAKS(2)=123, and BREAKS(NBRK)=200, where NBRK is 3. Note that the last point in a data set is always a break point, so that NBRK is always 1 or greater.
To allow compatibility with some other programs (notably IUEDR), DIPSO assumes that a specific Y
value (zero by default) actually flags a gap in the data, for some i/o commands (e.g. SP0RD/WR
). This
will often be invisible to the user, but you ought to keep it in mind. Note also that if DIPSO reads in a
data set where a gap is padded out with a whole string of zeros (e.g. from IUEDR), then it throws
away all but a couple of them, to save space. (Try SP0RD
ing a hi-res IUEDR spectrum, then SP0WR
ing it;
the output is much smaller than the input). This behaviour does not apply to the READ
, WRITE
, SAVE
and RESTORE
.
When using NDFs, there is another Y value which is also used (by all commands which access NDFs) to flag gaps in the data. This value is the standard Starlink “bad” value which is used to flag invalid or missing data in many other Starlink packages. Its value is -1.7014117E+38 (software generates these “bad” values automatically... you’re not expected to type them in!).
Finally, although DIPSO will plot general X,Y arrays, several of the applications commands expect and
require data that have Angstrom or km/s as the X unit (e.g. EW
). A variable, WORV (which means
“Wavelength OR Velocity”), is used to flag data in which the “X” unit is km/s; if this is the case, then
WORV=,
where
is the rest wavelength to which the velocities are referenced (in Angstroms) and c is the speed of light
(km/s). Otherwise, WORV=1.0. (You’ll just have to think carefully about what you’re doing if your
data are in frequency units, I’m afraid — WORV=1.0 will generally be associated with your
data.)
To output data from other programs in a form suitable for inputting to DIPSO with the
(recommended) READ
command requires the following minimal code (with appropriate values and
names for all variables):
Such programs then need to be linked with the DIPSO object libraries, and the NDF subroutine library
(see SUN/33). To create a program called fred
which uses WRITE_NDF
to create an output NDF, do the
following:
As well as being readable by DIPSO such output data sets will also be automatically readable by all the standard STARLINK packages on any of the supported operating systems.
So, now you know what’s in a DIPSO data set; and thus, you have a good idea of the information on the stack. DIPSO lets you take copies of stack data using calls to the subroutine GETSTK:
where:
XV
and YV
data
are to be loaded; and on exit is the number of elements of the arrays which are
occupied (i.e. the number of points).
XV
array.
You can also push data onto the stack:
The arguments are the same as for GETSTK, except that ASZE (integer) is the size of your arrays holding the X and Y values, and BSZE (integer) is the size of your BREAKS array.
To encourage you to look on DIPSO as a tool with which you can interface your own software, it is
worth noting that the ELF
package (described below), all the Fourier analysis software, the IS
routines,
and the NEBCONT
facility were added to DIPSO with very little more than the basic interface described
above.
If you do write some software that you think may be of general interest, please contact Ian
Howarth (idh@star.ucl.ac.uk
); it may be possible to incorporate it into the public version of
DIPSO.