Analysis TTreeFormat

From GlueXWiki
Revision as of 11:35, 17 April 2013 by Pmatt (Talk | contribs) (Unique Particle Names)

Jump to: navigation, search

Why a standard TTree format?

  • For any reaction can streamline (and provide a best-practices implementation of): analysis utilities, BDT setup/input, amplitude analysis setup/input(?)
  • Makes it easy for users to keep everything organized, especially handling of the combinatoric background.
  • Output can be enabled/disabled with a single flag.
  • Format is designed to be one-size-fits-all, but is still extensible (customizable).

TTree Format - General

  • ROOT 5.32+ will be required for building BANA (for TClonesArray::ConstructedAt(), which makes it much easier to code tree creation)
    • Just about any version of ROOT is fine for reading the data

Events

  • One TTree per DReaction
    • e.g., will have different trees for missing/detected recoil proton for the same final state
  • One TTree entry per recorded physics event.
  • Each variable will have it's own TBranch
    • Branch name format: "UniqueParticleName"__"VariableName" //note double underscore (so that the variable & particle names can have single underscores)
    • Positions and four-momenta will be stored in TVector3 & TLorentzVector objects, all others variables are double or unsigned int.
    • Users can add their own custom branches to the tree

Particle Combinations

  • In a given entry, the TBranch for each variable holds an array: each index of the array corresponds to a different particle combination.
    • So all of the data from particle combination #3 will be stored in index "2" of each array
  • Combos will be sorted in the arrays by kinematic fit FOM (if no kinfit performed, then by overall pid FOM) (best listed first)
    • TObject data (e.g. TLorentzVector, TVector3) will be stored in TClonesArray's

TTree Format - Detail

  • Example Reaction:
    • γ p → η'1(2300), p
      • η'1(2300) → K*(892)0, K0_bar
        • K*(892)0 → K+, π-
          • K0_bar → π+, π-

Unique Particle Names

  • Reaction Particle Names, Decaying: "EtaPrime1_2300," "KStar892_0," "KShort"
  • Reaction Particle Names, Detected: "Proton," "KPlus," "PiMinus1," "PiPlus," "PiMinus2"
  • Thrown MC Particle Names: "ThrownPlus," "ThrownMinus," Thrown0"
    • Array entries do NOT correspond to particle combos: just a different particle in each array index
  • Unused Particle Hypothesis Names: "UnusedPlus," "UnusedMinus," "Unused0"
    • Array entries do NOT correspond to particle combos: just a different particle in each array index

Branch Examples

"PiMinus_PathLength" //double[]
"PiPlus1_ChiSq_Timing" //double[]
"PiPlus2_Momentum_Measured" //TClonesArray of TLorentzVector

Accessing TClonesArray Data Examples

  • TSelector:
GetEntry(entry);
cout << ((TLorentzVector*)PiPlus2_Momentum_Measured->At(0))->Px() << endl; //At(): particle combination 0, 1, 2, ...
  • TTree:
MyTree->Draw("PiPlus2_Momentum_Start->Px()"); //draws all particle combinations

Summary

  • Data Structures:
    • DTreeParticle: roughly mirrors DKinematicData: kinematics + PID info of track
    • DTreeStep: roughly mirrors DParticleComboStep: collection of DTreeParticle's for a given step of a reaction (e.g. photoproduction, Λ decay, π0 decay, etc.)
    • DTreeCombo: roughly mirrors DParticleCombo (collection of DTreeStep's for a given reaction), + detected particles not used in the combo
    • DTreeEvent: contains DTreeCombo's for each output DReaction, + thrown tracks
  • Extensible:
    • Each class has maps to contain additional data (TObject* and double, map keys are string): users can add their own custom information here
    • Otherwise they can make a friend TTree to add branches to the existing tree.
  • Usage:
    • Process with a TSelector.
    • TTree::Draw() and TTree::Project() will not work due to nested classes/containers.

Cons

  • Data is contained in nested deques/maps, which causes problems:
    • Impossible to make them split properly for viewing in the TBrowser.
    • TTree::Draw() and TTree::Project() will not work due to nested classes/containers.

DTreeParticle

  • Roughly mirrors DKinematicData: kinematics + PID info of track
  • p3, v3, and t are stored at both the start (production) and end points (decay, TOF/BCAL/FCAL hit) of the track.
    • This is primarily motivated by the Ξ-, which is long-lived and whose trajectory is bent by the magnetic field before it decays.
  • Extensible: maps can be used by users to add their own custom information.
class DTreeParticle : public TObject
{
  public:
    // PID:
    Particle_t dPID;
 
    // KINEMATICS: Start //If kinematic fit was performed, this is the kinematic fit results.  Else are identical to the "Measured" kinematics.  
    TVector3 dPosition_Start; //the position where the particle is produced
    double dTime_Start; //time of the track at dPosition_Start
    TVector3 dMomentum_Start; //momentum of the track at dPosition_Start
    TMatrixDSym dCovarianceMatrix; //at dPosition_Start // Order is (px, py, pz, x, y, z, t)
 
    // KINEMATICS: End
    TVector3 dPosition_End; //detected particles: the reconstructed position of the BCAL/FCAL/TOF hit; decaying particles: the point where it decays
    double dTime_End; //time of the track at dPosition_End
    TVector3 dMomentum_End; //momentum of the track at dPosition_End
 
    // KINEMATICS: Measured
    TVector3 dPosition_Measured; //the position where the particle is produced
    double dTime_Measured; //time of the track at dPosition_Measured, projected from the TOF/BCAL/FCAL hit
    TVector3 dMomentum_Measured; //momentum of the track at dPosition_Start
 
    // KINEMATICS: Other
    double dPathLength; //from dPosition_Start to dPosition_End
 
    // PID QUALITY:
    unsigned int dNDF_Tracking;
    double dChiSq_Tracking;
    unsigned int dNDF_Timing;
    double dChiSq_Timing;
    unsigned int dNDF_DCdEdx;
    double dChiSq_DCdEdx;
 
    // DEPOSITED ENERGY:
    map<DetectorSystem_t, double> dDepositedEnergies; //Is dE/dx for all but BCAL/FCAL (shower energies)
 
    // DTREESTEP POINTERS:
    const DTreeStep* dProductionStep; //the step object in which this DTreeParticle is produced (is a final-state particle)
    const DTreeStep* dDecayStep; //the step object in which this DTreeParticle decays (is an initial-state particle) (will be null if not a decaying particle!)
 
    // CUSTOM VARIABLES:
    map<string, double> dCustomVariables; //key is unique string, double is value
    map<string, const TObject*> dCustomObjects; //key is unique string, TObject* is object
 
  ClassDef(DTreeParticle, 1)
};

DTreeStep

  • Roughly mirrors DParticleComboStep: collection of DTreeParticle's for a given step of a reaction (e.g. photoproduction, Λ decay, π0 decay, etc.)
  • Extensible: maps can be used by users to add their own custom information.
class DTreeStep : public TObject
{
  public:
    // INITIAL PARTICLES:
    const DTreeParticle* dInitialParticle; //if is null: decaying or beam particle not yet set!
    const DTreeParticle* dTargetParticle; //NULL for no target
 
    // FINAL PARTICLES:
    deque<DParticle_t> dFinalParticleIDs; //separate in case particle is NULL (e.g. decaying resonance)
    deque<const DTreeParticle*> dFinalParticles; //particle may be NULL if it is decaying or missing (especially if no kinematic fit was performed!!)
 
    // CUSTOM VARIABLES:
    map<string, double> dCustomVariables; //key is unique string, double is value
    map<string, const TObject*> dCustomObjects; //key is unique string, TObject* is object
 
  ClassDef(DTreeStep, 1)
};

DTreeCombo

  • Roughly mirrors DParticleCombo (collection of DTreeStep's for a given reaction), + detected particles not used in the combo
  • Extensible: maps can be used by users to add their own custom information.
class DTreeCombo : public TObject
{
  public:
    // STEPS:
    deque<const DTreeStep*> dTreeSteps;
 
    // RF:
    bool dRFTimeMatchQuality; //true if good (certain), false if bad (not confident in value (e.g. no "good" tracks have TOF hits))
    double dRFTime;
    double dRFTimeUncertainty;
 
    // UNUSED PARTICLES:
    vector<const DTreeParticle*> dUnusedDetectedParticles;
    vector<const DTreeShower*> dUnusedDetectedShowers;
 
    // KINEMATIC FIT:
    DKinFitType dKinematicFitType; //Defined in DKinFitResults.h //d_NoFit if not performed
    double dChiSq_KinematicFit; //NaN if not performed
    unsigned int dNDF_KinematicFit; //0 if not performed
 
    // CUSTOM VARIABLES:
    map<string, double> dCustomVariables; //key is unique string, double is value
    map<string, const TObject*> dCustomObjects; //key is unique string, TObject* is object
 
  ClassDef(DTreeCombo, 1)
};

DTreeEvent

  • Contains DTreeCombo's for each output DReaction, + thrown tracks
  • Extensible: maps can be used by users to add their own custom information.
class DTreeEvent : public TObject
{
  public:
    // RUN, EVENT #'s:
    unsigned int dRunNumber;
    unsigned int dEventNumber;
 
    // DATA:
    map<string, deque<const DTreeCombo*> > dTreeCombos; //string key is (D)Reaction name, deque is the particle combos
    deque<const DTreeParticle*> dThrownParticles;
 
    // CUSTOM VARIABLES:
    map<string, double> dCustomVariables; //key is unique string, double is value
    map<string, const TObject*> dCustomObjects; //key is unique string, TObject* is object
 
  ClassDef(DTreeEvent, 1)
};

Usage Example: Create & Process Tree

  • ROOT can't handle nested classes/containers as branches inside of TTree's. Therefore:
    • rootcint is used to create a shared object library containing the DTreeEvent, DTreeParticle, etc. objects, which then needs to be loaded prior to processing the TTree.
    • Only one branch is created: the one for DTreeEvent.
    • TTree::Draw() and TTree::Project() don't work.

Create Tree

  • This would be done "under-the-hood" in DANA, but a simple example is shown here: 1 event containing 1 combo, 1 step and 1 particle
void Create_Tree(void)
{
  //load library, create file & tree
  gSystem->Load("libBANA_ROOT_TREE.so");
  TFile* locFile = new TFile("test.root", "RECREATE");
  TTree* locTree = new TTree("testtree", "testtree");
 
  //create event: THE ONLY BRANCH ON THE TREE (set run & event #'s)
  DTreeEvent* locTreeEvent = new DTreeEvent();
  locTree->Branch("dTreeEvent", locTreeEvent, 32000, 0); //splitlevel = 0 makes sure no sub-branches are created (ROOT doesn't do them correctly)
  locTreeEvent->dRunNumber = 12345;
  locTreeEvent->dEventNumber = 67890;
 
  //create a step with one particle in it, set start time
  DTreeStep* locTreeStep = new DTreeStep();
  DTreeParticle* locTreeParticle = new DTreeParticle();
  locTreeParticle->dTime_Start = 2.0;
  locTreeStep->dFinalParticles.push_back(locTreeParticle);
 
  //put the step in the combo
  DTreeCombo* locTreeCombo = new DTreeCombo();
  locTreeCombo->dTreeSteps.push_back(locTreeStep);
 
  //put the combo in the tree
  deque<const DTreeCombo*> locCombos;
  locCombos.push_back(locTreeCombo);
  string locReactionName = "TestReaction";
  locTreeEvent->dTreeCombos[locReactionName] = locCombos;
 
  locTree->Fill();
  locFile->Write();
  locFile->Close();
}

Sample TSelector

Bool_t MySelector::Process(Long64_t entry)
{
  //dTreeEvent IS THE ONLY BRANCH (DTreeEvent*)
  GetEntry(entry);
 
  cout << "run, event #'s: " << dTreeEvent->dRunNumber << ", " << dTreeEvent->dEventNumber << endl;
 
  //get the combos for the given reaction
  string locReactionName = "TestReaction";
  deque<const DTreeCombo*> locTreeCombos = dTreeEvent->dTreeCombos[locReactionName];
 
  //grab the step, particle, and start time
  const DTreeStep* locTreeStep = locTreeCombos[0]->dTreeSteps[0];
  const DTreeParticle* locTreeParticle = locTreeStep->dFinalParticles[0];
  cout << "t = " << locTreeParticle->dTime_Start << endl;
}

Process Tree

void Process_Tree(void)
{
  string locHallDHome = getenv("HALLD_HOME");
  string locIncludePath = locHallDHome + string("/include/");
  gInterpreter->AddIncludePath(locIncludePath.c_str()); //for particleType.h and whatever else is needed
  gSystem->Load("libBANA_ROOT_TREE.so"); //load the class definitions so that can read the "dTreeEvent" tree branch
 
  TFile* locFile = new TFile("test.root", "READ");
  TTree* locTree = (TTree*)locFile->Get("testtree");
  locTree->Process("MySelector.C"); //process the events in the tree with this TSelector
}