#define MAXTRACKS 20
//--------------------------------------------------------------------+
//								      |
//	Fragment of code to book and fill a Column-wise Ntuple        |
//								      |
//--------------------------------------------------------------------+
#include <string>
#include "HepTuple/HepHBookFileManager.h"
#include "HepTuple/HepNtuple.h"
#include "ZMutility/FixedTypes.h"
#include <cstdlib>
#include <iostream.h>
#include <cmath>
#include <vector>

//  Declare the pointer to the file manager at this level to
//  make it available at file scope.

HepFileManager *tManager;

Int4 main(Int4 argc, char ** argv)
{
  Int4 nevents=2000;
  }
  void generate( Int4, bool );

//  Initialize HBOOK and open an RZ file.  Note that this is now the only
//  direct invocation of an HBOOK-specific method. Using it here triggers
//  everything else even though all subsequent references below are to
//  generic things like HepHistogram.

//  Note that the top directory on the RZ file will have the same name as
//  the file itself.  There's no choice in this but it isn't a big deal
//  since the name of the top directory isn't actually recorded anywhere.

  tManager = new HepHBookFileManager("toyz.rz");

//  Book and fill an ntuple in a function named generate.

  generate(nevents,first);
  delete tManager;
  return 0;
}

void generate(Int4 nevents, bool first)
{
			.
			.
			.

//  Instantiate an ntuple, declare it to be columnwise (this is default
//  anyhow) and tell the manager where to find the data items when we tell
//  it to capture. This is a handy way to do this.  We establish a reference
//  to the data item here and give the item a value when the program logic
//  warrants it. After all items have been assigned a value, we tell the
//  ntuple machinery to capture everything. This works because the location
//  of the data doesn't change - just the value sitting in that location.

  HepNtuple & tupl = tManager->ntuple("Toy CWNtuple")

  tupl.setColumnWise();
  tupl.setDiskResident();

//  N. B. In addition to defining the ntuple block names and column names,
//        these declaration also indirectly declare the data types of the
//        corresponding items, either through the type of the data item,
//        the type of the default value or the type of the referenced item.

//  Define a block named TRACKS and a column named Ntracks.  In addition,
//  declare this column to contain an index variable and specify it's range.

  cout << "\nDeclaring columns, ranges and index variables." << endl;
  tupl.columnAt("TRACKS::Ntracks",&numTracks,(Int4)1);
  tupl.span("TRACKS::Ntracks",0,MAXTRACKS);	    // specify full nametag

//  Declare a column array named Pt and say that it is a variable length
//  array indexed by Ntracks and has maximum dimension MAXTRACKS.  Repeat
//  this for each column within the Tracks block. Note that we specifically
//  cast the default value as a Float8.  This fixes the type of the data.

//  There are a number of variations on how to declare indexed column arrays.
//  We use several of them here to demonstrate some of the possibilities.

  tupl.columnArray("TRACKS::Pt",  1,(Float8)99.9);
  tupl.dimension("TRACKS::Pt",MAXTRACKS);	// specify nametag
  tupl.index("TRACKS::Pt","Ntracks");

  tupl.columnArray("TRACKS::Eta", 1,(Float8)99.9);
  tupl.dimension(MAXTRACKS);			// default nametag to "current"
  tupl.index("TRACKS::Eta","Ntracks");

  tupl.columnArray("TRACKS::Phi", 1,(Float8)99.9);
  tupl.dimension(MAXTRACKS);
  tupl.index("TRACKS::Phi","Ntracks");		// specify nametag

  tupl.columnArray("TRACKS::Px",  1,(Float8)99.9);
  tupl.dimension(MAXTRACKS);
  tupl.index("Ntracks");			// default nametag to "current"

// Two-fold method cascade since each returns another reference

  tupl.columnArray("TRACKS::Py",  1,(Float8)99.9).dimension(MAXTRACKS);
  tupl.index("TRACKS::Py","Ntracks");

// Three-fold method cascade since each returns another reference

  tupl.columnArray("TRACKS::Pz",  1,(Float8)99.9).dimension(MAXTRACKS).index("Ntracks");

//  Finally, print out the block descriptor string that this produced.

  cout << "\nPrint the chForm string for Block TRACKS to see what we got." ^lt;< endl;
  cout << tupl.blockFormat("TRACKS") << endl;

//  Release everything so we can define values for all quantities.

  cout << "\nClear all data in preparation for presenting values." << endl;
  tupl.clearDataBlock("TRACKS");
			.
			.
			.
//  Do whatever is needed to define numTracks and fill the arrays it indexes.
			.
			.
			.

//  Capture a bunch of ntuple entries before they go out of scope, store
//  everything and clean up for the next event.

    tupl.capture("TRACKS::Ntracks",numTracks);
    tupl.capture("TRACKS::Pt" ,&(PtArray[0]));
    tupl.capture("TRACKS::Eta",&(EtaArray[0]));
    tupl.capture("TRACKS::Phi",&(PhiArray[0]));
    tupl.capture("TRACKS::Px", &(PxArray[0]));
    tupl.capture("TRACKS::Py", &(PyArray[0]));
    tupl.capture("TRACKS::Pz", &(PzArray[0]));
    tupl.captureBlock("TRACKS");
    tupl.storeCapturedData();
    tupl.clearData();
			.
			.
			.
}