Next: Using FARFALLA in Up: The FARFALLA Programming Reference Previous: Pointers to Information

Using FARFALLA to Create a Custom DST

The first step in designing a custom DST is to identify the clients the DST will serve. One could make a DST to serve a particular analysis group, or to serve a group at a particular location. At Caltech, we have a number of people doing many different analysis projects. If each person had their own custom DST on disk at Caltech, there would be much duplication of data. We have defined a Caltech DST which will contain all the data needed for several analysis projects.

Once the clients are identified, then one must determine what information they need, and criteria for selecting the events for which that information is needed. Some painful decisions will need to be made at this point because information must be thrown away to have a compact DST. If any information is needed that is not contained (or contained efficiently) in an existing FARFALLA node type, the designer must create all the new node types necessary (as described above).

Because most DSTs will require some reconstructed data, and a wealth of reconstruction software already exists in the DREAM environment, one will probably want to run a DREAM job to create the DST. However, to interact directly with FARFALLA, one must write in C++ . It is therefore necessary to write a DREAM duser routine in C++ . The duser routine will probably do all its work after PASS 3 of DREAM, and it will probably contain many calls to DSAGET to pull reconstructed information out of the DREAM ZEBRA banks. One may then run the DREAM job on MACRO data distribution (FZEX-format) tapes, writing DST output files to disk.

Part of the MACRO FARFALLA software release includes modules to fill the standard node types with data found in DREAM banks. If you create a new node type which you wish to share with MACRO collaborators, you should also include a similar module to fill your node type.

There are several technical difficulties in getting a C++ duser routine to work with FORTRAN. Here we present the solutions we have come up with; different solutions may be possible.

The easiest way to get information out of the DREAM banks is by calling the DREAM routines DSAGET and ERPGET. DSAGET and ERPGET return the address of a DREAM bank, regardless of whether the bank contains REAL or INTEGER data (or mixed REAL and INTEGER data). However, C++ is a strongly-typed language. If when we tell C++ about DSAGET, we indicate that it returns INTEGER data, then we may not subsequently use it to pass data into a REAL variable. We have chosen to circumvent this problem by using a union. Then we can make C++ think it is passing data into an array of INTEGERs, but we will later treat the data as an array of REALs.

The standard routine provided to create all erp nodes and fill them with data follows. It assumes that the top-level event node of the tree has been created, and a pointer to that node is in the global variable ev. Note that dream.h contains the function prototype


extern "C" void erpget_(char*,int&,int&,int&,int&,int&,int len=4);

The union erpDreamBank receives both INTEGER and REAL data.


#include <iostream.h>
#include <strstream.h>
#include <math.h>

#include <farfalla.h>
#include <eventNode.h>
#include <erpNode.h>

#include "dream.h"

extern eventNode *ev;           // The global event pointer

// ------------------------------------------------------------------------
// This function gets the information out of the ERP Banks and creates and
// then fills the erpNodes.
// ------------------------------------------------------------------------

void dreamMakeErpNodes() 
{
  int ierr;
  int numErpHits=0;
  union {int i[34]; float f[34];} erpDreamBank;
  erpget_("GLOB",1,2,1,numErpHits,ierr); // Read in the global ERP bank
  for (int i=1 ; i <= numErpHits; i++) 
  {
    erpNode *erpBank;           // Declare the pointer
    F_addChild(ev,erpBank);     // Make a new erpNode

    erpget_("HITS",i,1,34,erpDreamBank.i[1],ierr);  // Get ERP bank

    erpBank->boxnum = erpDreamBank.i[1];              // Now Fill the Node
    erpBank->tdc0h  = erpDreamBank.i[4]; 
    erpBank->tdc1h  = erpDreamBank.i[5]; 
    erpBank->adc0u  = erpDreamBank.i[6]; 
    erpBank->adc1u  = erpDreamBank.i[7]; 
    erpBank->tdc0l  = erpDreamBank.i[8]; 
    erpBank->tdc1l  = erpDreamBank.i[9]; 
    erpBank->adc0a  = erpDreamBank.i[10]; 
    erpBank->adc1a  = erpDreamBank.i[11]; 
    erpBank->time   = erpDreamBank.f[19];
    erpBank->energy = erpDreamBank.f[23];
    erpBank->posh   = erpDreamBank.f[25];
  }
}

The following are prototype DREAM C++ user routines to create a simple FARFALLA DST. (The DREAM user routines defined here are main, dstrak, dsoru, dendu and duser.) dsoru and dendu manage the output file, using the global variable outfile. A different output file is opened for each run. For each event duser creates the event node, then calls the standard routines to create and fill nodes from the DREAM banks. We assume there is a function pruneTree(), not shown, which makes the decisions of which events to keep, and which information to keep for each event. pruneTree() is where the data is customized for a particular set of DST clients.


#include <fstream.h>
#include <strstream.h>
#include <math.h>

#include <farfalla.h>
#include <eventNode.h>

#include "dream.h"

// ------------------------------------------------------------------------
// This is the main steering DUSER for the FARFALLA DST production.
// it includes:
//
// - output file defintion (fstream outfile)
// - global eventNode definition (eventNode *ev)
// - PAWC global common block definition
//
// main()   - Call the main DREAM routine
// dstrak() - Call CATTRK
// dsoru()  - Called on SOR records.  Open new FARFALLA output file.
// dendu()  - Close any leftover FARFALLA files
// duser()  - Get reconstructed data.  Fill FARFALLA Nodes.
//
// ------------------------------------------------------------------------

extern void dreamMakeEventTree();
extern void dreamMakeErpNodes();
extern void dreamMakeWireTrackNodes();
extern void dreamMakeStripTrackNodes();
extern void dreamMakeOtherWireNode();
extern void dreamMakeOtherStripNode();
extern void runStatsBOR();
extern void runStatsEvnt();
extern void runStatsEOR();
extern void pruneTree();

fstream outfile;                // The output file
eventNode *ev = NULL;           // Declare a global pointer to an Event Node
int pawc_[50000];               // The global PAWC common

main()         {dream_(50000);}    // The Main DREAM routine
void dstrak_() {cattrk_();}        // DSTRAK ; Use CATTRK
void dendu_()  {outfile.close();runStatsEOR();} // DENDU: close the last file

void dsoru_()                   // DSORU: open a new file each run
{
  if (outfile.rdbuf()->is_open()) outfile.close();

  int run;                      // This is a integer variable for the run
  int ierr;
  dsaget_("RAW ",1,3,1,run,ierr); 

  // The following code sets filename to "dstXXXX.far", where XXXX is
  // the run number -- don't worry if you don't understand it
  char filename[80];
  strstream string(filename,80);
  string << "dst" << run << ".far" << ends;    // Make the file name
  outfile.open(filename,ios::out);             // Open the file
  runStatsBORDream();                          // initialize runStats
}

void duser_(int& ipass, int& itimes) // DUSER: decode the data
{
  int ierr;
  if ((ipass == 0) && (itimes == 2)) dwfdxp_(ierr);  //Uncompress WFDs

  if (itimes != 3 ) return;     // Only do this after DREAM is finished

  dreamMakeEventTree();         // Makes new tree; fills it; has ev point at it

  // Now call of the routines which grab the decoded data and 
  // put them into the FARFALLA nodes.

  dreamMakeErpNodes();          // Create/fill the ERP nodes
  dreamMakeWireTrackNodes();    // Create/fill Wire Track nodes
  dreamMakeStripTrackNodes();   // Create/fill Strip Track nodes

  // The following routine accumulates statistics for a runNode
  runStatsEvnt();
  
  pruneTree();          // Kill any nodes we dont want to write
  if (ev != NULL)
  {
    ev->outputSubtree(outfile); // Write FARFALLA tree to disk
    ev->deleteSubtree();        // Delete this tree from memory
    ev = NULL;                  // Mark tree as deleted
  }
}



Next: Using FARFALLA in Up: The FARFALLA Programming Reference Previous: Pointers to Information


walter@
Wed Aug 10 11:53:26 PDT 1994