TTree Example

This example is taken from the SVN repository: ./Examples/TTree/Test.java.

It creates a ROOT file (FromJava.root), and creates a TTree called "demoT", with branches:

  • Floats: fX, fY, fZ.
  • Ints: iX, iY, iZ.
  • TVector3: vec1
  • std::vector<float>: vecF.
  • std::vector<int>: vecI.
  • std::vector<double>: vecD.
  • std::vector<bool>: vecB.
  • std::vector<TVector3>: vec3.

Three points are added to each of the vectors of primitive types, and a random number of points in [1,16] is added to the vector<TVector3>.

The second TTree has branches:

  • Doubles: dX, dY, dZ.
  • Bool: bX, bY, bZ.
  • TLorentzVector: lvec1.
  • std::vector<TLorentzVector>: vecL.
import java.util.Random;
import hep.physics.vec.*;
import org.lcsim.thirdparty.javaROOT.*;

public class Test
{
	public static void main(String[] args)
	{
		// Load the library
		try
		{
			System.loadLibrary( "javaROOT" );
		}
		catch( UnsatisfiedLinkError javaROOT_linkError )
		{
			System.err.println( "JavaROOT native library failed to load.\n" + javaROOT_linkError + "\n" );
			System.exit( -1 );
		}

		// Create a RNG to fill our histograms with.
		Random r = new Random( 0 );

		// Create a file
		RootSessionField sess = new RootSessionField( "FromJava.root", "RECREATE", "Test", 1 );

		// Create a tree, populate it with branches and set it up for use.
		sess.newTTree( "demoT", "TestTree", 99 );

		// The branch names are initially cached. We cannot fill the tree with
		// data until we "setup" the TTree with RootSessionField::setupTTree,
		// when the branches are actually created in the ROOT file.
		// At this point, no further branches can be created, but we can fill
		// tree with data.

		// Branches of type float, called "fX", "fY" and "fZ" respectively.
		sess.branchTTreeFloat( "demoT", "fX" );
		sess.branchTTreeFloat( "demoT", "fY" );
		sess.branchTTreeFloat( "demoT", "fZ" );
		// Branches of type int, called "iX", etc.
		sess.branchTTreeInt( "demoT", "iX" );
		sess.branchTTreeInt( "demoT", "iY" );
		sess.branchTTreeInt( "demoT", "iZ" );
		// Branch of type TVector3.
		sess.branchTTreeVector3( "demoT", "vec1" );
		// Branch of type std::vector<float>.
		sess.branchTTreeVectorFloat( "demoT", "vecF" );
		// Branch of type std::vector<int>.
		sess.branchTTreeVectorInt( "demoT", "vecI" );
		// Branch of type std::vector<double>.
		sess.branchTTreeVectorDouble( "demoT", "vecD" );
		// Branch of type std::vector<bool>.
		sess.branchTTreeVectorBool( "demoT", "vecB" );
		// Branch of type std::vector<TVector3>.
		sess.branchTTreeVectorVector3( "demoT", "vec3" );

		// Setup the tree to fill with data.
		sess.setupTTree( "demoT" );

		// Create another tree
		sess.newTTree( "demoU", "AnotherTestTree", 99 );
		// Branches of type double.
		sess.branchTTreeDouble( "demoU", "dX" );
		sess.branchTTreeDouble( "demoU", "dY" );
		sess.branchTTreeDouble( "demoU", "dZ" );
		// Branches of type bool.
		sess.branchTTreeBool( "demoU", "bX" );
		sess.branchTTreeBool( "demoU", "bY" );
		sess.branchTTreeBool( "demoU", "bZ" );
		// Branch of type TLorentzVector.
		sess.branchTTreeLorentzVector( "demoU", "lvec1" );
		// Branch of type std::vector<TLorentzVector>.
		sess.branchTTreeVectorLorentzVector( "demoU", "vecL" );

		// Setup the tree to fill with data.
		sess.setupTTree( "demoU" );

		// Currently, you must use these write-only collection classes to
		// pass vectors to javaROOT. These are included in
		// org.lcsim.thirdparty.javaROOT.
		vectorFloat fVals;
		vectorInt iVals;
		vectorDouble dVals;
		vectorBool bVals;
		vectorVector3 vecVals;
		vectorLorentzVector lorVals;

		for( int i = 0; i < 4096; i++ )
		{
			// (Re-)create the collections, clearing them.
			fVals = new vectorFloat();
			iVals = new vectorInt();
			dVals = new vectorDouble();
			bVals = new vectorBool();
			vecVals = new vectorVector3();
			lorVals = new vectorLorentzVector();

			sess.fillBranchFloat( "demoT", "fZ", (float) r.nextGaussian() );
			sess.fillBranchFloat( "demoT", "fX", (float) r.nextGaussian() );
			sess.fillBranchFloat( "demoT", "fY", (float) r.nextGaussian() );

			sess.fillBranchInt( "demoT", "iZ", (int) ( r.nextGaussian() * 1024 ) );
			sess.fillBranchInt( "demoT", "iY", (int) ( r.nextGaussian() * 1024 ) );
			sess.fillBranchInt( "demoT", "iX", (int) ( r.nextGaussian() * 1024 ) );

			// For convenience, we pass hep.physics.vec.Hep3Vectors to fillBranchVector3,
			// which is automatically stored as a ROOT TVector3 in the ROOT file.
			BasicHep3Vector t = new BasicHep3Vector( r.nextGaussian(), r.nextGaussian(), r.nextGaussian() );
			sess.fillBranchVector3( "demoT", "vec1", t );

			// Generate some data, and add them to the collections.
			fVals.add( (float) r.nextGaussian() );
			fVals.add( (float) r.nextGaussian() );
			fVals.add( (float) r.nextGaussian() );
			sess.fillBranchVectorFloat( "demoT", "vecF", fVals );

			iVals.add( (int) ( r.nextGaussian() * 1024 ) );
			iVals.add( (int) ( r.nextGaussian() * 1024 ) );
			iVals.add( (int) ( r.nextGaussian() * 1024 ) );
			sess.fillBranchVectorInt( "demoT", "vecI", iVals );

			dVals.add( r.nextGaussian() );
			dVals.add( 2 * r.nextGaussian() );
			dVals.add( 3 * r.nextGaussian() + 2 );
			sess.fillBranchVectorDouble( "demoT", "vecD", dVals );

			bVals.add( ( r.nextGaussian() > 0 ) ? true : false );
			bVals.add( ( r.nextGaussian() > 0 ) ? true : false );
			bVals.add( ( r.nextGaussian() > 0 ) ? true : false );
			sess.fillBranchVectorBool( "demoT", "vecB", bVals );

			for( int j = 0; j < r.nextInt( 15 ) + 1; j++ )
			{
				vecVals.add( new BasicHep3Vector( (float) r.nextGaussian(), (float) r.nextGaussian(), (float)
				r.nextGaussian() ) );
			}
			sess.fillBranchVectorVector3( "demoT", "vec3", vecVals );

			// "Commit" these data to the first tree.
			sess.fillTTree( "demoT" );

			// Fill the second tree with data.
			sess.fillBranchDouble( "demoU", "dY", r.nextGaussian() );
			sess.fillBranchDouble( "demoU", "dZ", 2 * r.nextGaussian() );
			sess.fillBranchDouble( "demoU", "dX", 3 * r.nextGaussian() + 2 );

			sess.fillBranchBool( "demoU", "bY", ( r.nextGaussian() > 0 ) ? true : false );
			sess.fillBranchBool( "demoU", "bX", ( r.nextGaussian() > 0 ) ? true : false );
			sess.fillBranchBool( "demoU", "bZ", ( r.nextGaussian() > 0 ) ? true : false );

			// For convenience, we pass hep.physics.vec.HepLorentzVectors to fillBranchLorentzVector,
			// which is automatically stored as a ROOT TLorentzVector in the ROOT file.
			BasicHepLorentzVector t2 = new BasicHepLorentzVector( r.nextGaussian(), r.nextGaussian(), r.nextGaussian(), r.nextGaussian() );
			sess.fillBranchLorentzVector( "demoU", "lvec1", t2 );

			for( int j = 0; j < r.nextInt( 15 ) + 1; j++ )
			{
				lorVals.add( new BasicHepLorentzVector( (float) r.nextGaussian(), (float) r.nextGaussian(), (float) r.nextGaussian(), (float)
				r.nextGaussian() ) );
			}
			sess.fillBranchVectorLorentzVector( "demoU", "vecL", lorVals );

			// Commit the data to the second tree.
			sess.fillTTree( "demoU" );
		}

		// Essential to ensure all values are properly committed to the file.
		sess.delete();
	}
}

  • No labels