Structure Package for Sunsort

Relies on: Sunsort
C include file: hitsubs.h
FORTRAN include files: subs.i and hitsubs.i

This package provides a way of storing the structure of the experiment that is accessible to the code. This allows general routines to be written which don't need to know the structure of a specific experiment, instead they can pick their information out of here.

The structure is held as a tree starting with the topmost element which is called experiment. It's up to the user to decide how to sub-divide the experiment into detectors. A simple division may be to say that an experiment consists of 2 psssds and 2 monitors. Each psssd consists of 16 strips. Each strip consists of signala, signalat, signalb and signalbt. Each monitor consists of signala and signalat. This would lead to a tree like:

        			   experiment
        			 ,'   /   \  `.
        		       ,'    /     \   `.
        		     ,'     /       \    `.
        	           ,'      /         \     `.
                         ,'       /           \      `.
                     pssd      pssd         monitor    monitor
               ,::'///|||\\\`::.  :          /   \        :
             strip x 16 ......... :     signale signalet  :
           .' / \ `.
         .'  /   \  `.
       .'   /     \   `.
     .'    /       \    `.
signala signalat signalb signalbt

Typically an extra detector will be modelled called junk which will contain all the unused ADCs to allow then to be seen from the experiment structure.

Each level of the tree is handled in the same way. It is described by a variable of type struct detectors. In C you can traverse the tree by manipulating pointers. In FORTRAN routines are provided to access the tree, these routines keep track of where you are.

The package structure provides many variables that are attached at each level of the structure. Some of these are used by other packages. See the relevant package description for more details. If you are using those packages then you should use the variables as described (or more likely leave them to the package to manage). If you are not using the package then leave those variables alone as they are subject to change.

As far as the structure package is concerned, the only node type name with any special meaning is experiment. When the structure is loaded from file, the package expects to find exactly one node called experiment it will make this the top node in the structure tree.

C data structures

The C data-structure for each node looks like this:

             struct detectors {
	         struct detectors *parent;
		 struct detectors *children;
		 struct detectors *next;
		 struct information *info;
		 int number;
		 short adcnum;
		 short hits;
		 struct {
		     struct detectors *head;
		     struct detectors *next;
		 } hitlist;
		 double gain;
		 double offset;
		 int threshmin;
		 int threshmax;
		 double value;
		 void *user;
		 ...		    /* The rest of this structure is opaque */
	     };
      

The entries have the following meanings:

parent
points up the tree to the node to which this node is attached. It is NULL for the node experiment.
children
points down the tree to the first node that is attached below this node. It is NULL for a leaf node.
next
points across the tree to the next node at the same level, that is the next node with the same parent. It is NULL for the last node on a level.
info
points to some more information about this node.
number
The number of this node at this level. The first node at this level is numbered 1. In the example above, on the level below experiment, the pssds will have numbers 1 and 2, and the monitors numbers 3 and 4. The numbers will match the order of children and next, that is, children always points to a node with number 1 and next always points to the node with the number one higher than the current node.
adcnum, hits, hitlist, gain, offset, threshmin, threshmax and value
These are provided for the use of other packages.
user
A hook on which you can place your own data. This hook is initialised to NULL. If the event structure is destroyed (which happens whenever it is reinitialised) and if this pointer is non-NULL then it is freed by calling free().
The following structure holds information which is the same for all nodes of the same type:
	     struct info {
	         char *name;
		 int ndetel;
		 ...		    /* The rest of this structure is opaque */
             };
      

Most of the entries in this structure are for the internal use of the sort subroutines, so leave them alone. The following are available to be read and under no circumstances must they be written to:

name
A string holding the name of the type of this node
ndetel
Subject to change, will be documented later

Shared C and FORTRAN access

FORTRAN routines only have access to one experiment tree. C routines can load multiple trees if they desire. C routines have to pass the head of the tree to most routines to show which tree they want to access. An external variable:

struct detectors *expt;
is provided which the FORTRAN routines always use. Users who wish to access the same tree from C and FORTRAN should set this variable.

Routines

struct detectors *loadexperiment(char *filename);

Loads the experiment structure from file. It returns a pointer to the top level of the experiment structure, that is to a node called experiment. The file structure is documented elsewhere.

To automatically set the FORTRAN pointers do:

		loadexperiment_(filename);
      
and access the variable expt to get the pointer to the head of the tree.

int setdetprocs(char *name, int (*preinit)(struct detectors *), int (*init)(struct detectors *), int (*preevent)(int, struct detectors *), int (*event)(int, struct detectors *));
integer function setdetprocs(character*(*) name, integer function preinit(), integer function init(), integer function preevent(integer), integer function event(integer))

This routine defines which routines are to be called to initialise and to process an event for each node in the structure. Name is the name of the structure as given in the experiment file. Preinit, init, preevent and event are the four functions to be called at various times. See the section Detector Routines later for more details.

These function can only be used if all detector procedures are of the same type (C or FORTRAN) to set mixed types, you must use the setdetprocsmixed() call from C.

int setdetprocsmixed(char *name, void *preinit, int preinit_type, void *init, int init_type, void *preevent, int preevent_type, void *event, int event_type);

This routine behaves as setdetprocs but the type of each routine can be specified. Use DETPROC_F to specify a FORTRAN routine, and DETPROC_C to specify a C routines. Fortran routines should be declared with lines like:

	         int mydetector_preinit_(void);
	         int mydetector_init_(void);
	         int mydetector_preevent_(int *);
	         int mydetector_event_(int *);
      

Function pointers should then be cast to void * in the call.

void expt_dump(struct detectors *dp, int indent);
subroutine expt_dump(integer indent)

Writes a textual description of the experiment tree to stderr. It also dumps the values of the variables used in other packages in brackets so ignore them if you aren't using them.

In C you may pass it a pointer to the node from which you want to dump the tree this allows you to dump part of the tree. In FORTRAN the only option is to dump the whole of the default tree.

The parameter indent controls how many spaces are put at the start of a line, it is incremented by 4 for each level down the tree.

int detector_init(struct detectors *dp);
integer function detector_init()

Perform user specified initialisation for all elements in the experiment tree for which initialisation routines were specified with setdetprocs(). See the section Detector Routines later for more details. The return value is that of the last detector routine that was called.

In C pass this routine the pointer to the top of the experimental tree. In FORTRAN this always processes the default tree.

FORTRAN specific routines

There are many subroutines for accessing the experiment tree from FORTRAN. The routines keep track of a current position in the tree. Routines are provided to move this position around the tree. Routines are provided to access data at this position, and to access data at an arbitrary position. In general, it's faster to access the data at the current position.

integer loadexperiment(character*(*) filename)

This routine loads an experiment in the same way as the C function loadexperiment() does. However, it also initialises the FORTRAN compatability routines. They will not work if this routine is not called, hence, if you want to mix C and FORTRAN, you must load the experiment structure through the FORTRAN call. In C this can be done by calling loadexperiment_(char *filename). The pointer to the top level of the experiment tree can be found in the external variable expt. This routine returns 1 for success and 0 for failure.

Movement routines

subroutine detectortop
Move to the top of the experiment tree.
integer function detectorparent()
Move to the parent of the current position (*).
integer function detectornext()
Move to the next node on the same level (*)
integer function detectorchildren()
Move to the first node at the next level. (*)
integer function detectorsave()
Remember the current position (returns 0 if it works, 1 if out of memory).
integer function detectorrestore()
Return to the last saved position (returns 0 if it works, 1 if no more saved positions).
subroutine detectorforget()
Forget all saved positions.

The routines marked with * return 0 if the move was successful, non-zero if there was nowhere to go (that is, it was at the top, right, or bottom of the tree).

Data retrieval routines

Each of these routines is available in 2 flavours. For a variable called xxx there's a routine getthisxxx() which gets the data for the current node, and a routine getxxx(reference, ...) which gets the data for a node given an absolute reference from experiment without moving the current pointer. A reference is of the form:

node.node.node.node...

where node is either the name of the node, or the character % to indicate that the next parameter should be read to indicate how many steps along the three to take. For example, signalbt of the third strip of the second pssd in the example tree above can be referenced as:

     ('%.%.%',2,3,4)
      
or
    ('%.%.signalbt',2,3)
      

Naturally, only nodes with unique names at a level should be reference by name, others should be referenced by number.

The following routines are available for accessing constant information about a node.

character*80 function getname(...), getthisname()
Returns the name of the detector type at this node.
integer function getnumber(...), getthisnumber():
Returns the number of the node.
integer function getndetel(...), getthisndetel()
Returns the number of children (sub-elements) this node has.

Steven M. Singer
Last modified: Thu Sep 30 20:40:10 BST 1999