New features added in Sunsort 4.06
==================================

On the fly projection of 2d spectra
-----------------------------------

The 2d spectrum viewer program can now project spectra at arbitrary angles.
This is done on the fly in the graphical user interface allowing the user
to easily check lots of angles.

To enable the feature select Slicing->Arbitrary angle. A new window will
appear with the projection controls in. Lines will appear in the main spectrum
window showing the direction of projection. A series of parallel lines are
drawn parallel to the projection direction, and a single line is drawn showing
the line the projection is performed on to.

The projection window has the following controls:

Project Area:	  This controls whether the full spectrum is projected, or just
		  the area inside the slicing window (this window is set with
		  Slicing->Set Slice Window).

Axis:		  This controls whether the projection is performed on to the
		  X axis, the Y axis, or the perpendicular to the projection
		  axis. Since the choice of axis only affects the dispersion
		  of the projected spectrum, and the window here automatically
		  scales, no change will be seen as the axis is changed.
		  However, when the data is finally passed do sort_xvgr, the X
		  axis values will reflect the chosen axis.

Projection angle: This slider controls the projection angle. The displays
		  react in real time as the slider is moved. The angle set here
		  is the real angle in the coordinate space of the spectrum,
		  not the on screen angle (see below for more details).

X and Y:	  These set the scalings on the X and Y axes. Set these as
		  written, so that if to convert an X channel number into an
		  angle in degrees you muse multiply by 2 and add 5 you
		  would set the X line to read:
		          X: Degrees = channels * 2 + 5

Project onto ...: This sets the coordinate the projection axis is drawn
		  through. The only affect of this is to translate the
		  projection.  Since the window here automatically tracks the
		  projection, no change will be seen. However, when the data
		  is finally passed do sort_xvgr, the X axis values will
		  reflect the chosen coordinate.

|P|2 order:	  This overlays a squared Legendre polynomial of the specified
		  order over the data. The up and down arrow buttons alter the
		  order, and the + and - buttons alter the height of the
		  polynomial.

Do Projection:	  This button passes the data to sort_xvgr from where it can
		  be printed, and other transformations can be performed.

Note about coordinates:

In the projection window, coordinates and angles refer to the a coordinates
and angles in real space. This is the same as the displayed space if, and
only if, the X and Y scalings are both set to *1+0. To get spectra to display
on screen with reasonable scales, it is sometimes necessary to disperse the
spectra, for example, if theta and psi are variables holding the angles theta*
and psi in your FORTRAN code, and have the values in degrees, and you used the
code.

	call inc2d(5, nint(psi), nint(theta))

Then the on-screen coordinates would match the real coordinates, however, it
is rare that this is the case. More likely is something like:

	call inc2d(5, nint(psi*2-116), nint(theta*3+64))

If there were ridges in theta-psi space with an angle (atan(dtheta/dpsi)) of
30 degrees, then on screen, this would be an angle of 41 degrees. Provided
you set the scalings correctly to :

	X: Degrees = channels * 0.5     + 84
	Y: Degrees = channels * 0.33333 - 21.33333

Then, when the lines drawn on screen lined up with the ridges (a screen
angle of 41 degrees), the projection angle displayed in the window would
read 30 degrees.

Note on integer rounding:

In line with the current practice of using nint() to round values in FORTRAN,
the projection code assumes that each histogram bin is centred round its
channel value. For example, the bin (36,25) takes all values in the range
35.5<=x<36.5, 24.5<=y<25.5. This matches the behaviour of the 1D routines.

In C, this rounding is performed by:

	(int) (x + 0.5)

Note that just saying (int) x will round down.

The new functions f and d prefixed functions (see below) perform the correct
rounding.

[I know in the past I've said use int() to round, but reading through the
 rest of Sunsort code it all assumes nint(). Look carefully at how channels
 are centred in 1d spectra.]

New functions for spectra
-------------------------

The following new functions are available:

call incv1d(spectrum, channel, amount)
call incv2d(spectrum, x_channel, y_channel, amount)
call set1d(spectrum, channel, amount)
call set2d(spectrum, x_channel, y_channel, amount)
val1d(spectrum, channel)
val2d(spectrum, x_channel, y_channel)

The incv functions increment the specified channel by the specified amount.
The set functions set the channel to the specified amount, the val functions
return an integer which is the contents of the specified channel.

The incv, set and val routines, can be usefully combined in code like this:

*twod
...
32	sum	128
33	count	128
34	mean	128
...
      integer x,y,gas
...
* Get gas signal
      gas = adc(...)
...
* Calculate x and y positions of detector hit
      x = ...
      y = ...
...
* Generate a graph of average gas signal as a function of detector position
      call incv2d(32, x, y, gas)
      call inc2d(33, x, y)
      call set2d(34, x, y, val2d(32, x, y)/val2d(33, x, y))

In practice, it is better to add a software noise gate onto the gas signal
to make the means more meaningful.

To tidy sort codes, the following new functions have been added: 

sinc1d, sinc2d, sincv1d, sincv2d, swin2d, sset1d, sset2d, sval1d, sval2d,
finc1d, finc2d, fincv1d, fincv2d, fwin2d, fset1d, fset2d, fval1d, fval2d,
dinc1d, dinc2d, dincv1d, dincv2d, dwin2d, dset1d, dset2d, dval1d and dval2d.

These are exactly the same as the normal functions except the channel numbers
(and amounts in the case of the incv and set functions) given as integer*2 for
the s prefixed functions, real (or real*4) for the f prefixed functions, and
double precision (or real*8) for the d prefixed functions. This allows lines
like:

	call inc1d(1, nint(adc(1)))
	call inc2d(5, nint(psi*2-116), nint(theta*3+64))

to be simplified to:

	call sinc1d(1, adc(1))
	call finc2d(5, psi*2-116, theta*3+64)

if psi and theta are real. If they were double precision, dinc2d would have to
be used.

For C sort codes, the following functions available:

	void inc1d(int, int);
	void inc2d(int, int, int);
	void incv1d(int, int, int);
	void incv2d(int, int, int, int);
	int win2d(int, int, int);
	void set1d(int, int, int);
	void set2d(int, int, int, int);
	int val1d(int, int);
	int val2d(int, int, int);
	void dinc1d(int, double);
	void dinc2d(int, double, double);
	void dincv1d(int, double, double);
	void dincv2d(int, double, double, double);
	int dwin2d(int, double, double);
	void dset1d(int, double, double);
	void dset2d(int, double, double, double);
	int dval1d(int, double);
	int dval2d(int, double, double);

In C, the short and float versions of the functions are not needed as the
compiler automatically upgrades short and float to int and double
respectively.

Note that the C syntax for win2d differs from the FORTRAN syntax allowing you
to write code like:

	if (win2d(5, x, y))
	{
	    ....
	}

instead of the FORTRAN equivalent:

	call win2d(5, x, y, inwin)
	if (inwin) then
	  ...
	endif

New shorthand for defining multiple spectra
-------------------------------------------

This new format allows groups of spectra to be defined much more elegantly.
As well as the old syntax:

	number	name	size

you may now say

	first..last      first_name size

or

	first..last,step first_name size

The first and last give the numbers of the first and last spectra in the
group. The first_name gives the number of the first spectrum. Names for
other spectra in the group are derived by incrementing first_name.

Perhaps this is easiest to explain by example:

1..5	adc1	4096

is equivalent to

1	adc1	4096
2	adc2	4096
3	adc3	4096
4	adc4	4096
5	adc5	4096

41..44	spec5	128

is equivalent to

41	spec5	128
42	spec6	128
43	spec7	128
44	spec8	128

and,

61..67,2 siga1	4096
62..68,2 sigb1	4096

is equivalent to

61	siga1	4096
62	sigb1	4096
63	siga2	4096
64	sigb2	4096
65	siga3	4096
66	sigb3	4096
67	siga4	4096
68	sigb4	4096

Simplified common block declarations
------------------------------------

To save having to type:

       common/adcnum/numadc,dtrig
       common/adcs/event,record,wrtevt,bitpat,trign,adc
       common/filenm/filein, fileou
       common/vars/var

       real var(500)
       integer dtrig(0:31,0:31)
       integer event, record, numadc
       character filein*40, fileou*40
       integer*2 bitpat(8),trign,adc(128)
       logical wrtevt

in every sort code, where this declaration can change between versions of
sunsort giving errors, you can now just type:

	include '.sunsort_initadc.i'

to get all the up-to-date common block declarations.

As a case in point, if you don't make this change when you switch to version
4.06 you will get the harmless warning 'inconsistent lengths for common block
adcs' or words to that effect. Make the change and all will be OK.

You need to place the include line once in each function that needs access
to the common variables.

If you are using C sort-codes, then you should #include ".sunsort_initadc.h"
once at the top of the sort code (outside any functions). You may then
access any of the common block variables as commonblock_.variable.
Note that arrays are numbered from 0 in C, so to get the equivalent of the
FORTRAN adc(1) you need adcs_.adc[0]. To make life easier, two macros -
ADC() and VAR() - have been declared which are exactly equivalent to the
FORTRAN interface (that is FORTRAN adc(1) is the same as C ADC(1)).

C sort-codes
------------

A C sort-code should #include ".sunsort_initadc.h", and provide three
functions void init_(void), void sortin_(void) and void finish_(void).  These
are equivalent to the three entries in the FORTRAN sort code. Variables which
need to be seen by all three sort routines should be declared static outside
the routines. For example, the equivalent of the FORTRAN sort code:

*trigger
128
*oned
1..64 adc1 4096
*twod
*vars
*sort
	subroutine init
	implicit none
	save
	include '.sunsort_initadc.i'
	integer events, i

	events = 0
	return

	entry sortin
	events=events+1
	do i=1,64
	   if (adc(i).gt.0) call inc1d(i, nint(adc(i)))
	enddo
	return

	entry finish
	print *,events,' events sorted.'
	return
	end

is the C sort code:

*trigger
128
*oned
1..64 adc1 4096
*twod
*vars
*sort
#include <stdio.h>
#include ".sunsort_initadc.h"

static int events;

void init_(void)
{
    events = 0;
}

void sortin_(void)
{
    int i;

    events++;

    for(i = 1; i <= 64; i++)
	if (ADC(i) > 0)
	    inc1d(i, ADC(i));
}

void finish_(void)
{
    printf("%d events sorted.\n", events);
}

In2p3 data format
-----------------

The annoying thing about in2p3 data is that the tapes are not ANSI format.
This means you can't use the Exabyte button on Sunsort as there is no concept
of named tape volumes and file names. Fortunately, this is not a fatal problem.

To read an in2p3 data tape, the first thing you need to do is, confusingly,
select Sort media: Disk. Enter the Sort file name /dev/rmt/0n (assuming
you want drive 0).

If you hit open, it will then open the first tape file. Closing will move you
to the start of the next file. If you want to move forward and backward files,
then the procedure is to close the file, then in any window on that machine
(the Sunsort window at the Sunsort> prompt will be fine), enter an mt command.

mt is documented on its manual page (man mt for more details), but the
following may help:

	mt -f /dev/rmt/0n status	(see where are we)
	mt -f /dev/rmt/0n fsf 1		(go to the next file)
	mt -f /dev/rmt/0n nbsf 1	(back to start of this file)
	mt -f /dev/rmt/0n nbsf 2	(back to start of previous file)
	mt -f /dev/rmt/0n rewind	(back to start of tape)

Note that because closing the stream moves you to the start of the next file,
the sequence close, mt nbsf 2, open reopens the file you were just on from
the start. 

When you start reading data from a file, the in2p3 reader can dig out the file
name stored inside the file and print it on screen, so I suggest that while
you are trying to find the right file, you open the file and read 5 records,
which should be enough to get the file name. Then you can use the mt commands
to move about. Remember that when you get to the right file, you should do a
clear all to remove any data loaded from the first 5 records of the files you
skipped past.

in2p3 data can also contain parameter blocks, when found, these are dumped to
screen. Scaler blocks are not processed (yet).

I think, but haven't checked, that if you write filtered data to tape, then it
gets written out in ANSI format so you can read it back using the normal
Sunsort Exabyte interface, however, the filtering process removes all
non-event data (ie. file headers, parameter blocks etc. are lost).

Demon data format
-----------------

DEMON data format is a true Eurogam format. DEMON, however, record all their
data in Eurogam groups as opposed to us who use simple parameters.  For those
of you who don't know, a simple parameter is something like

	adc 12 has value 635.

A group is more like

	group 45 has values 838, 2871, 294, 1222, 471 and 3073.

To get group data, you use the call egroup. It has the syntax:

	call egroup(group_number, group_data, max_parameters)

group_number is the number of the group you want to retrieve the data from.
group_data is an integer*2 array which should be big enough to hold all the
	data for the group.
max_parameters is the size of the array group_data so that the routine will
	not accidentally write past the end of the array.

On return, group_data is filled with the parameters, and max_parameters now
holds the number of parameters actually returned.

The C function is:

	struct group_data *egroup(int group_number);

group_number is the number of the group you want to retrieve. struct
group_data is defined in the standard header .sunsort_initadc.h, and has the
format:

	struct group_data {
	    int            group_len;
	    unsigned short *group_ptr;
	};

group_len holds the length of the group, and group_ptr points to an array
of the data (the first data element is at group_ptr[0]).

Command line and batch files
----------------------------

As well as using batch files to sort data, they can also be used to set up
variables appropriately for different runs. All you need to do is create a
batch file that just contains the var commands, eg.

	var 1 32
	var 7 13
	var 8 18
	update

The update command is necessary if you want the changes in the variables to
be reflected in the variables window, and is new in Sunsort_4.06.

Of course, if you want to set all variables, then you can just load and
save them in the same way as spectra. The method above has the advantage that
it can leave some variables unaltered. The above method is probably more
suited to a long batch file where you want to sort a file, alter a variable,
sort another file, alter a variable etc.

FSUPC data format
-----------------

Annoyingly, this data format also does not use ANSI format tapes so you have
to go through the same contortions as for in2p3 data (see above). To
complicate matters further, although data files are meant to have the run
number stored in them, some are missing it. You'll have to guess their run
number by dead reckoning from those files with headers.

In depth syntax checking of sort codes
--------------------------------------

The FORTRAN syntax checker program ftnchek is now bundled with sunsort.
Makesort knows how to invoke it to check function calls into standard sunsort
functions. Makesort also knows how to call lint for C sort codes.  To use
makesort to do this, add the keyword check to the command line, for example,

	makesort sortcode.srt check			FORTRAN code
	makesort sortcode.srt check -xC			C code

Alternatively, if you are using sort_tool, press the button marked "Check"

Ftnchek complains if, in variable declarations, the save command comes after
the implicit none command. Technically it is correct, the Sun FORTRAN compiler
is flexible enough to allow the command either way round.

Ftnchek also complains if you have variable declarations after data
statements, for example,

	integer xxx(2)
	data xxx/3,5/
	integer i

Again, it is technically correct as, according to the FORTRAN specification
data statements must come after all declarations. The Sun FORTRAN compiler is
flexible enough to allow misordered statements (and although ftnchek warns you
about such statements, it can cope with them).

Ftnchek also complains if you use " to delimit strings, strict fortran
specifies that the ' character must be used, so,

	call eginit("egmap.dat",ierror)

is strictly illegal in FORTRAN, you should say,

	call eginit('egmap.dat',ierror)

The Sun compiler allows both, ftnchek only allows '.

What ftnchek is really good at is picking up when you've passed the wrong
types, or wrong number of parameters to a function.

You can use ftnchek on your own FORTRAN programs (that is, other programs than
sort codes). You should read the manual first by typing:

	nroff -man /the/directory/containing/sunsort/man/ftnchek.1 | more

If you have a complex sort code involving multiple files, then you should
learn how to invoke ftnchek or lint yourself.
