Difference between revisions of "Analysis TTreeFormat"

From GlueXWiki
Jump to: navigation, search
(Particle Data : Unused Hypotheses)
(Thrown Beam Particle)
 
(372 intermediate revisions by 4 users not shown)
Line 1: Line 1:
== Why a standard TTree format? ==
+
= TTree Format - Overview =
* For any reaction can streamline (and provide a best-practices implementation/examples of): analysis utilities, BDT setup/input, amplitude analysis setup/input(?)
+
* Physics Analysis Root TTree (PART) format.
* Makes it easy for users to keep everything organized, especially handling of the combinatoric background.
+
* Format is designed to be one-size-fits-all, but is still extensible (customizable).
+
 
+
== TTree Format - Overview ==
+
 
+
=== ROOT Version ===
+
* ROOT >= v5.32 will be required for building DANA
+
** Much easier to code <span style="color:#0000FF">TTree</span> creation: <span style="color:#0000FF">TClonesArray</span>::<span style="color:#008000">ConstructedAt()</span> can be used instead of calls to placement-new
+
** Just about any version of ROOT is fine for reading the data
+
  
 
=== Data Hierarchy ===
 
=== Data Hierarchy ===
* One <span style="color:#0000FF">TTree</span> per <span style="color:#0000FF">DReaction</span>, each stored in a separate ROOT file.  
+
* One <span style="color:#0000FF">TTree</span> per <span style="color:#0000FF">DReaction</span>, each stored in the ROOT files specified by the user.  
** e.g., will have different trees for missing/detected recoil proton for the same final state
+
** e.g., If 2 DReactions: missing & detected recoil proton: 2 different trees, could be in separate files or the same file.
* One <span style="color:#0000FF">TTree</span> entry per particle combination.  
+
* One <span style="color:#0000FF">TTree</span> entry per event.  
* One <span style="color:#0000FF">TBranch</span> per variable. (e.g. <span style="color:red">"RunNumber"</span>, <span style="color:red">"PiMinus__PathLength"</span>, etc.)
+
* All particle data stored in arrays/<span style="color:#0000FF">TClonesArray</span>'s: one array index per particle.
* Thrown particles and unused particle hypotheses will be stored in arrays/<span style="color:#0000FF">TClonesArray</span>'s: one array index per particle.  
+
** Thrown particles
** e.g.: <span style="color:red">"Unused__ChiSq_Tracking"</span> (<span style="color:#0000FF">Double_t</span>[]), <span style="color:red">"Thrown__P4_Thrown"</span> (<span style="color:#0000FF">TClonesArray</span>(<span style="color:#0000FF">TLorentzVector</span>))
+
** Reconstructed neutral and charged hypotheses (by default: only used ones, but can save all: DReaction setting)
** Unused beam particles are NOT saved.
+
** Beam photons that are later used in combos (unused beam particles are NOT saved)
 +
** Combo particle information
 
* Event-independent information (e.g. the target, the <span style="color:#0000FF">DReaction</span> decay chain, etc.) is stored in <span style="color:#0000FF">TTree</span>::<span style="color:#008000">fUserInfo</span> (a <span style="color:#0000FF">TList</span>*)
 
* Event-independent information (e.g. the target, the <span style="color:#0000FF">DReaction</span> decay chain, etc.) is stored in <span style="color:#0000FF">TTree</span>::<span style="color:#008000">fUserInfo</span> (a <span style="color:#0000FF">TList</span>*)
  
=== Object-Oriented Programming ===
+
=== DSelector ===
* Will provide tool to convert tree branch data into the C++ objects for a given event (callable from <span style="color:#0000FF">TSelector</span>::<span style="color:#008000">Process</span>())
+
* Enables C++ interface to TTree data, provides PROOF-Lite launcher, and much more.
** C++ classes (similar to DANA classes): <span style="color:#0000FF">DTreeCombo</span>, <span style="color:#0000FF">DTreeStep</span>, <span style="color:#0000FF">DTreeParticle</span> (compiled into ROOT dictionary & loadable shared library)
+
* Instructions for making and using a DSelector can be found at: [[DSelector | Link]]
** Can be used to write/execute reusable software that will work for any reaction (e.g. handling double-counting when filling histograms)
+
  
== Usage ==
+
= TTree Format: Simulated Data =
 +
=== Thrown Non-Particle Data ===
 +
<syntaxhighlight>
 +
// EVENT DATA
 +
"RunNumber": UInt_t
 +
"EventNumber": ULong64_t
 +
"MCWeight": Float_t
  
=== Create TTrees ===
+
// # PARTICLES //array size of the thrown particle branches
* To save data to a <span style="color:#0000FF">TTree</span> for a given <span style="color:#0000FF">DReaction</span>, <span style="color:#0000FF">TTree</span> output must be first be enabled for that reaction.  See [https://halldweb1.jlab.org/wiki/index.php/Analysis_DReaction#DReaction_Control_Variables DReaction Control Variables] for details. 
+
"NumThrown": UInt_t
  
<syntaxhighlight>
+
// THROWN REACTION INFO
#include "ANALYSIS/DEventWriterROOT.h"
+
"NumPIDThrown_FinalState": ULong64_t //the # of thrown final-state particles (+ pi0) of each type (multiplexed in base 10)
//In plugin brun():
+
                                      //types (in order from 10^0 -> 10^15): g, e+, e-, nu, mu+, mu-, pi0, pi+, pi-, KLong, K+, K-, n, p, p-bar, n-bar
const DEventWriterROOT* locEventWriterROOT = NULL;
+
                                      //e.g. particles decaying from final-state particles are NOT included (e.g. photons from pi0, muons from pions, etc.)
locEventLoop->GetSingle(locEventWriterROOT);
+
                                    //is sum of #-of-PID * 10^ParticleMultiplexPower() (defined in libraries/include/particleType.h)
locEventWriterROOT->Create_DataTrees(locEventLoop); //creates TTrees for all output-enabled DReactions
+
                                    //ParticleMultiplexPower() returns a different power of 10 for each final-state PID type.
locEventWriterROOT->Create_ThrownTree("tree_b1pi_thrownmc.root"); //optional: create a ttree containing only the thrown data //string is output file name
+
                                    //A value of 9 should be interpreted as >= 9.
 +
"PIDThrown_Decaying": ULong64_t //the types of the thrown decaying particles in the event (multiplexed in base 2)
 +
                                //not the quantity of each, just whether or not they were present (1 or 0)
 +
                                //binary power of a PID is given by ParticleMultiplexPower() (defined in libraries/include/particleType.h)
 +
                                //types: most Particle_t's that aren't final state (e.g. lambda, eta, phi, rho0, etc.) see ParticleMultiplexPower()
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Save Data to TTree ===
+
=== Thrown Beam Particle ===
* The below only saves the particle combinations (for <span style="color:#0000FF">TTree</span>-output-enabled <span style="color:#0000FF">DReaction</span>'s created in the factory specified by the tag) that survived all of the <span style="color:#0000FF">DAnalysisAction</span> cuts.
+
* All branch names are prefixed with <span style="color:red">"ThrownBeam__"</span>
 
<syntaxhighlight>
 
<syntaxhighlight>
//In plugin evnt()
+
//IDENTIFIER
const DEventWriterROOT* locEventWriterROOT = NULL;
+
"PID": Int_t //PDG ID value
locEventLoop->GetSingle(locEventWriterROOT);
+
locEventWriterROOT->Fill_DataTrees(locEventLoop, "b1pi_hists"); //string is the DReaction factory tag that the DReactions were created in
+
</syntaxhighlight>
+
  
* The below allows you to choose which <span style="color:#0000FF">DParticleCombo</span>'s (<span style="color:#008000">locParticleCombos</span>) of which <span style="color:#0000FF">DReaction</span>'s (<span style="color:#008000">locReaction</span>) to save.
+
//KINEMATICS: //At the production vertex
** Beware: the <span style="color:#008000">locParticleCombos</span> MUST have originated from the <span style="color:#008000">locReaction</span> or else this will probably crash (can check <span style="color:#0000FF">DParticleCombo</span>::<span style="color:#008000">Get_Reaction</span>()).
+
"X4": TLorentzVector //This is the TAGGED energy //Use THIS for binning your results //Is ZERO if NOT TAGGED
<syntaxhighlight>
+
"P4": TLorentzVector
//In plugin evnt()
+
"GeneratedEnergy": Float_t
#include "ANALYSIS/DEventWriterROOT.h"
+
vector<const DEventWriterROOT*> locEventWriterROOTVector;
+
locEventLoop->Get(locEventWriterROOTVector); //creates the TTrees for all DReactions upon first call
+
locEventWriterROOTVector[0]->Fill_Tree(locEventLoop, locReaction, locParticleCombos);
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* The below fills a <span style="color:#0000FF">TTree</span> that only contains the thrown particle data.  
+
=== Thrown Products ===
 +
* All branch names are prefixed with <span style="color:red">"Thrown__"</span>
 +
* NOTE: The only contains particles corresponding to the <span style="color:red">"FinalState"</span> and <span style="color:red">"Decaying"</span> tags of <span style="color:#0000FF">DMCThrown</span>.
 +
** In other words: No resonances, no decay products of final-state particles, and no orphan particles.  
 
<syntaxhighlight>
 
<syntaxhighlight>
//In plugin evnt()
+
//IDENTIFIERS / MATCHING
const DEventWriterROOT* locEventWriterROOT = NULL;
+
"ParentIndex": Int_t["NumThrown"] //the thrown particle array index of the particle this particle decayed from (-1 if none (e.g. photoproduced))
locEventLoop->GetSingle(locEventWriterROOT);
+
"PID": Int_t["NumThrown"] //PDG ID value
locEventWriterROOT->Fill_ThrownTree(locEventLoop);
+
</syntaxhighlight>
+
  
=== Accessing TTree Data ===
+
//MATCHING //only present if reconstructed data present (i.e. not if thrown-only tree)
* <span style="color:#0000FF">TTree</span>:
+
"MatchID": Int_t["NumThrown"] //the "NeutralID"/"TrackID" of the reconstructed neutral/track that it is matched with (-1 for no match)
<syntaxhighlight>
+
"MatchFOM": Float_t["NumThrown"] //Neutrals: confidence level //Tracks: #-matched-hits * hit_fraction //(-1 for no match)
MyTree->Draw("PiMinus1__P4_Measured->Theta()"); //draws all particle combinations
+
 
 +
//KINEMATICS: //Reported at the particle's production vertex
 +
"X4": TClonesArray(TLorentzVector["NumThrown"])
 +
"P4": TClonesArray(TLorentzVector["NumThrown"])
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* <span style="color:#0000FF">TBrowser</span> (draws all particle combinations):  
+
= TTree Format: Combo-Independent Data =
[[Image:Mattione_TTreeFormat_b1piTBrowserExample.png|thumb|left|900px|b1pi Events]]
+
 
<br style="clear:both;"/>
+
=== Non-Particle Data ===
* <span style="color:#0000FF">TSelector</span> (histogram b1pi mass distributions):
+
 
<syntaxhighlight>
 
<syntaxhighlight>
GetEntry(entry);
+
// EVENT DATA
 +
"RunNumber": UInt_t
 +
"EventNumber": ULong64_t
 +
"L1TriggerBits": UInt_t
  
//this doesn't take into account double-counting!!
+
// PRODUCTION SPACETIME
TLorentzVector locPiZeroP4 = *Gamma1__P4_KinFit + *Gamma2__P4_KinFit;
+
"X4_Production": TLorentzVector //V3 from DVertex (kinfit), t from RF (propagated to V3)
dPiZeroMassHist->Fill(locPiZeroP4.M());
+
  
TLorentzVector locOmegaP4 = locPiZeroP4 + *PiPlus2__P4_KinFit + *PiMinus2__P4_KinFit;
+
// # PARTICLES //these are the array sizes for the particle branches
dOmegaMassHist->Fill(locOmegaP4.M());
+
"NumBeam": UInt_t
 +
"NumChargedHypos": UInt_t
 +
"NumNeutralHypos": UInt_t
  
TLorentzVector locB1PlusP4 = locOmegaP4 + *PiPlus1__P4_KinFit;
+
// TOPOLOGY //only present if simulated data
dB1PlusMassHist->Fill(locB1PlusP4.M());
+
"IsThrownTopology": Bool_t //Does the DReaction decay chain match the thrown decay chain
  
TLorentzVector locX2000P4 = locB1PlusP4 + *PiMinus1__P4_KinFit;
+
// UNUSED TRACKS
dX2000MassHist->Fill(locX2000P4.M());
+
"NumUnusedTracks": UChar_t
</syntaxhighlight>
+
  
=== Preventing Double-Counting ===
+
//NUM COMBOS
* Since you can have multiple particle combinations per event, you have to be very careful to make sure you aren't double-counting when filling your histograms. 
+
"NumCombos": UInt_t //size of all of the particle-combo-content arrays
** For example, if you're histogramming the invariant mass of the &pi;<sup>0</sup>'s decay to &gamma;&gamma; in b1pi events using the measured photon data, multiple combinations may use the same showers for the photons, while having different tracks for the other particles.  Here's the recommended solution for checking this in your <span style="color:#0000FF">TSelector</span>:
+
 
+
* Keep track of <span style="color:red">"ObjectID"</span>'s of the particles for previous particle combinations that pass each cut that you place in your <span style="color:#0000FF">TSelector</span>
+
<syntaxhighlight>
+
//member variables added to your TSelector
+
vector<vector<int> > sPreviousObjectIDs_Beam; //1st dimension is cut-index
+
vector<vector<int> > sPreviousObjectIDs_PiMinus1; //1st dimension is cut-index
+
vector<vector<int> > sPreviousObjectIDs_PiMinus2; //1st dimension is cut-index
+
vector<vector<int> > sPreviousObjectIDs_PiPlus1; //1st dimension is cut-index
+
vector<vector<int> > sPreviousObjectIDs_PiPlus2; //1st dimension is cut-index
+
vector<vector<int> > sPreviousObjectIDs_Gamma1; //1st dimension is cut-index
+
vector<vector<int> > sPreviousObjectIDs_Gamma2; //1st dimension is cut-index
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* For each new event, clear the lists of previous object-ids
+
=== Beam Particles <span style="color:blue">(If Used in Combo) ===
 +
* Only the beam particles that are included in at least one combo are present.
 +
* All branch names are prefixed with <span style="color:red">"Beam__"</span>
 
<syntaxhighlight>
 
<syntaxhighlight>
//sNumCuts is the number of cuts you're placing in your TSelector
+
//ONLY PRESENT IF BEAM USED IN PARTICLE COMBOS
if((RunNumber != sPreviousRunNumber) || (EventNumber != sPreviousEventNumber))
+
{
+
  sPreviousObjectIDs_Beam.clear();
+
  sPreviousObjectIDs_PiMinus1.clear();
+
  sPreviousObjectIDs_PiMinus2.clear();
+
  sPreviousObjectIDs_PiPlus1.clear();
+
  sPreviousObjectIDs_PiPlus2.clear();
+
  sPreviousObjectIDs_Gamma1.clear();
+
  sPreviousObjectIDs_Gamma2.clear();
+
  sPreviousObjectIDs_Beam.resize(sNumCuts + 1);
+
  sPreviousObjectIDs_PiMinus1.resize(sNumCuts + 1);
+
  sPreviousObjectIDs_PiMinus2.resize(sNumCuts + 1);
+
  sPreviousObjectIDs_PiPlus1.resize(sNumCuts + 1);
+
  sPreviousObjectIDs_PiPlus2.resize(sNumCuts + 1);
+
  sPreviousObjectIDs_Gamma1.resize(sNumCuts + 1);
+
  sPreviousObjectIDs_Gamma2.resize(sNumCuts + 1);
+
}
+
</syntaxhighlight>
+
  
* For each cut you place when processing your event with your <span style="color:#0000FF">TSelector</span>:
+
//IDENTIFIERS / MATCHING
** If it passes the cut: Increase the cut index
+
"PID": Int_t["NumBeam"] //PDG ID value
** If it fails the cut: End the evaluation of the entry, and save the object-ids so that future entries can check against them.
+
"IsGenerator": Bool_t["NumBeam"] // kTRUE/kFALSE if matches the generator beam photon (-1 for no match) //only present if simulated data
<syntaxhighlight>
+
size_t locCutIndex = 0;
+
if(Gamma1__Energy_BCAL < 0.5)
+
  return End_Entry(locCutIndex);
+
++locCutIndex;
+
  
Bool_t MySelector::End_Entry(size_t locCutIndex)
+
//KINEMATICS: MEASURED //At the production vertex
{
+
"X4_Measured": TClonesArray(TLorentzVector["NumBeam"]) //position is at the production vertex (same as X4_Production(), except the time)
  sPreviousRunNumber = RunNumber;
+
"P4_Measured": TClonesArray(TLorentzVector["NumBeam"])
  sPreviousEventNumber = EventNumber;
+
  for(size_t loc_i = 0; loc_i <= locCutIndex; ++loc_i)
+
  {
+
    sPreviousObjectIDs_Beam[loc_i].push_back(Beam__ObjectID);
+
    sPreviousObjectIDs_PiMinus1[loc_i].push_back(PiMinus1__ObjectID);
+
    sPreviousObjectIDs_PiMinus2[loc_i].push_back(PiMinus2__ObjectID);
+
    sPreviousObjectIDs_PiPlus1[loc_i].push_back(PiPlus1__ObjectID);
+
    sPreviousObjectIDs_PiPlus2[loc_i].push_back(PiPlus2__ObjectID);
+
    sPreviousObjectIDs_Gamma1[loc_i].push_back(Gamma1__ObjectID);
+
    sPreviousObjectIDs_Gamma2[loc_i].push_back(Gamma2__ObjectID);
+
  }
+
  return kTRUE;
+
}
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
* Finally, when filling your histogram, first loop over the object-ids of any previous particle combinations to make sure that the result won't be duplicated:
+
=== Charged Track Hypotheses ===
 +
* Includes all hypotheses, whether they appear in the combos or not.
 +
* All branch names are prefixed with <span style="color:red">"ChargedHypo__"</span>
 
<syntaxhighlight>
 
<syntaxhighlight>
bool locDuplicateFlag = false;
+
//IDENTIFIERS / MATCHING
for(size_t loc_i = 0; loc_i < sPreviousObjectIDs_Gamma1[locCutIndex].size(); ++loc_i)
+
"TrackID": Int_t["NumChargedHypos"] //each physical particle has its own # (to keep track of different pid hypotheses for the same particle)
{
+
"PID": Int_t["NumChargedHypos"] //PDG ID value
  if((sPreviousObjectIDs_Gamma1[locCutIndex][loc_i] == Gamma1__ObjectID) && (sPreviousObjectIDs_Gamma2[locCutIndex][loc_i] == Gamma2__ObjectID))
+
"ThrownIndex": Int_t["NumChargedHypos"] //the array index of the thrown particle it is matched with (-1 for no match) //only present if simulated data
  {
+
    locDuplicateFlag = true;
+
    break;
+
  }
+
  if((sPreviousObjectIDs_Gamma1[locCutIndex][loc_i] == Gamma2__ObjectID) && (sPreviousObjectIDs_Gamma2[locCutIndex][loc_i] == Gamma1__ObjectID))
+
  {
+
    locDuplicateFlag = true; //g1 & g2 are switched but the invariant mass will be identical
+
    break;
+
  }
+
}
+
if(!locDuplicateFlag)
+
  MyPiZeroMassHist->Fill(locPiZeroMass);
+
</syntaxhighlight>
+
  
== TTree Format - Detail ==
+
//KINEMATICS: MEASURED  //At the production vertex
 +
"P4_Measured": TClonesArray(TLorentzVector["NumChargedHypos"])
 +
"X4_Measured": TClonesArray(TLorentzVector["NumChargedHypos"]) //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
  
=== Particle Names ===
+
//TRACKING INFO:
 +
"NDF_Tracking": UInt_t["NumChargedHypos"]
 +
"ChiSq_Tracking": Float_t["NumChargedHypos"]
 +
"NDF_DCdEdx": UInt_t["NumChargedHypos"]
 +
"ChiSq_DCdEdx": Float_t["NumChargedHypos"]
 +
"dEdx_CDC": Float_t["NumChargedHypos"]
 +
"dEdx_FDC": Float_t["NumChargedHypos"]
  
* Example Reaction (b1pi):
+
//TIMING INFO
** &gamma; p &rarr; X(2000), (p)
+
"HitTime": Float_t["NumChargedHypos"] //the system that is hit is in order of preference: BCAL/TOF/FCAL/ST
*** X(2000) &rarr; b<sub>1</sub>(1235)<sup>+</sup>, &pi;<sup>-</sup>
+
                                      //to determine which, look whether energy was deposited in these systems
**** b<sub>1</sub>(1235)<sup>+</sup> &rarr; &omega;, &pi;<sup>+</sup>
+
"RFDeltaTVar": Float_t["NumChargedHypos"] //Variance of X4_Measured.T() - RFTime, regardless of which RF bunch is chosen.  
***** &omega; &rarr; &pi;<sup>+</sup>, &pi;<sup>-</sup>, &pi;<sup>0</sup>
+
                                          //Can be used to compute timing ChiSq //RF bunch is combo-dependent
****** &pi;<sup>0</sup> &rarr; &gamma; &gamma;
+
* '''Reaction Particle Names, Beam''': <span style="color:red">"Beam"</span>
+
* '''Reaction Particle Names, Detected''': <span style="color:red">"PiMinus1," "PiPlus1," "PiPlus2," "PiMinus2," "Gamma1," "Gamma2"</span>
+
* '''Reaction Particle Names, Decaying''': <span style="color:red">"X," "b1_1235_Plus," "omega," "Pi0"</span>
+
** No branches are created for these particles.  All of their properties are derivable from the other data in the tree
+
* '''Reaction Particle Names, Missing''': <span style="color:red">"Proton"</span>
+
** No branches are created for these particles.  All of their properties are derivable from the other data in the tree
+
* '''Thrown MC Particle Name''': <span style="color:red">"Thrown"</span>
+
** Array entries do NOT correspond to particle combos: just a different particle in each array index
+
** Note: particles with PID = Unknown, particles decaying from final-state particles, and orphan particles are not saved.  
+
* '''Unused Particle Hypothesis Name''': <span style="color:red">"Unused"</span>
+
** Array entries do NOT correspond to particle combos: just a different particle hypothesis in each array index
+
  
=== Non-Particle/Vertex Data ===
+
//PID INFO
<syntaxhighlight>
+
"Beta_Timing": Float_t["NumChargedHypos"] // = Path_Length/(c*Delta_t)
// EVENT DATA
+
"ChiSq_Timing": Float_t["NumChargedHypos"]
"RunNumber": UInt_t
+
"NDF_Timing": UInt_t["NumChargedHypos"]
"EventNumber": UInt_t
+
  
// # PARTICLES //these are the array sizes for many of the other branches
+
//HIT ENERGY:
"NumThrown": UInt_t
+
"dEdx_TOF": Float_t["NumChargedHypos"]
"NumUnused": UInt_t
+
"dEdx_ST": Float_t["NumChargedHypos"]
 +
"Energy_BCAL": Float_t["NumChargedHypos"]
 +
"Energy_BCALPreshower": Float_t["NumChargedHypos"]
 +
"Energy_FCAL": Float_t["NumChargedHypos"]
  
// RF
+
//SHOWER WIDTH:
"RFTime_Thrown": Double_t
+
"SigLong_BCAL" Float_t["NumChargedHypos"] // Longitudinal (outward radially from the target) shower width
"RFTime_Measured": Double_t
+
"SigTheta_BCAL" Float_t["NumChargedHypos"] // Theta shower width
"RFTime_KinFit": Double_t //only if kinematic fit performed
+
"SigTrans_BCAL" Float_t["NumChargedHypos"] // Transverse (azimuthal) shower width
  
// KINEMATIC FIT
+
//SHOWER MATCHING:
"ChiSq_KinFit": Double_t //only if kinematic fit performed
+
"TrackBCAL_DeltaPhi": Float_t["NumChargedHypos"] //999.0 if not matched //units are radians
"NDF_KinFit": UInt_t //only if kinematic fit performed
+
"TrackBCAL_DeltaZ": Float_t["NumChargedHypos"] //999.0 if not matched //Track position - BCAL Shower
 
+
"TrackFCAL_DOCA": Float_t["NumChargedHypos"] //999.0 if not matched
//THROWN PARTICLES BY PID
+
"NumPIDThrown_FinalState": ULong64_t //the # of thrown final-state particles (+ pi0) of each type (multiplexed in base 10)
+
                                      //types (in order from 10^0 -> 10^15): g, e+, e-, nu, mu+, mu-, pi0, pi+, pi-, KLong, K+, K-, n, p, p-bar, n-bar
+
                                      //e.g. particles decaying from final-state particles are NOT included (e.g. photons from pi0, muons from pions, etc.)
+
                                    //is sum of #-of-PID * 10^ParticleMultiplexPower() (defined in libraries/include/particleType.h)
+
                                    //ParticleMultiplexPower() returns a different power of 10 for each final-state PID type.
+
                                    //A value of 9 should be interpreted as >= 9. 
+
"PIDThrown_Decaying": ULong64_t //the types of the thrown decaying particles in the event (multiplexed in base 2)
+
                                //binary power of a PID is given by ParticleMultiplexPower() (defined in libraries/include/particleType.h)
+
                                //types: most Particle_t's that aren't final state (e.g. lambda, eta, phi, rho0, etc.) see ParticleMultiplexPower()
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Production/Decay Spacetime Vertices ===
+
=== Neutral Particle Hypotheses ===
<syntaxhighlight>
+
* All branch names are prefixed with <span style="color:red">"NeutralHypo__"</span>
"X4_Production": TLorentzVector //only if beam particle is present in DReaction
+
* Includes all hypotheses, whether they appear in the combos or not.
"X4_LambdaDecay": TLorentzVector //only if decaying particles with detached vertices are present in DReaction //Lambda is just an example, could be KShort, etc.
+
* Discussion on P4 & X4:
</syntaxhighlight>
+
** Note that P4 is not present because it is defined by X4, and X4 is not present because it is defined by the tracks, which are combo-dependent
 
+
** For combo particles, P4 & X4 are listed for each combo
=== Particle Data : Thrown ===
+
** If not used in a combo, can be computed using the shower hit information and the vertex & RF-time of your choosing (e.g. combo production-vertex, RF-time)
* Note: particles with PID (<span style="color:#0000FF">Particle_t</span>) = <span style="color:red">Unknown</span>, particles decaying from final-state particles, and orphan particles are not saved.  
+
* To determine whether is BCAL or FCAL, see which system has non-zero energy
 
<syntaxhighlight>
 
<syntaxhighlight>
 
//IDENTIFIERS / MATCHING
 
//IDENTIFIERS / MATCHING
"ParentID": UInt_t["NumThrown"] //the thrown particle array index of the particle this particle decayed from (-1 if none (e.g. photoproduced))
+
"NeutralID": Int_t["NumNeutralHypos"] //each physical particle has its own # (to keep track of different pid hypotheses for the same particle)
"PID_PDG": Int_t["NumThrown"]
+
"PID": Int_t["NumNeutralHypos"] //PDG ID value
"MatchID": Int_t["NumThrown"] //the "ObjectID" of the unused and/or detected reaction particle it is matched with (-1 for no match)
+
"ThrownIndex": Int_t["NumNeutralHypos"] //the array index of the thrown particle it is matched with (-1 for no match) //only present if simulated data
  
//KINEMATICS: THROWN //At the production vertex  
+
//KINEMATICS: MEASURED //At the production vertex  
"X4_Thrown": TClonesArray(TLorentzVector["NumThrown"])
+
"P4_Measured": TClonesArray(TLorentzVector["NumNeutralHypos"])
"P4_Thrown": TClonesArray(TLorentzVector["NumThrown"])
+
"X4_Measured": TClonesArray(TLorentzVector["NumNeutralHypos"]) //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
</syntaxhighlight>
+
  
=== Particle Data : Beam Reaction Particles ===
+
//MEASURED PID INFO
<syntaxhighlight>
+
"Beta_Timing": Float_t["NumNeutralHypos"] // = Path_Length/(c*Delta_t)
//IDENTIFIER
+
"ChiSq_Timing": Float_t["NumNeutralHypos"] //-1 if not photon
"ObjectID": Int_t //each beam particle has its own #
+
"NDF_Timing": UInt_t["NumNeutralHypos"] //0 if not photon
  
//KINEMATICS: MEASURED //At the target center
+
//SHOWER INFO
"X4_Measured": TLorentzVector
+
"X4_Shower": Float_t["NumNeutralHypos"] //location/time of the reconstructed shower
"P4_Measured": TLorentzVector
+
"Energy_BCAL": Float_t["NumNeutralHypos"] //is 0.0 if shower in FCAL
 +
"Energy_BCALPreshower": Float_t["NumNeutralHypos"] //is 0.0 if shower in FCAL
 +
"Energy_FCAL": Float_t["NumNeutralHypos"] //is 0.0 if shower in BCAL
  
//KINEMATICS: KINFIT //At the interaction vertex //only present if kinfit performed
+
//SHOWER WIDTH:
"X4_KinFit": TLorentzVector
+
"SigLong_BCAL" Float_t["NumNeutralHypos"] // Longitudinal (outward radially from the target) shower width
"P4_KinFit": TLorentzVector
+
"SigTheta_BCAL" Float_t["NumNeutralHypos"] // Theta shower width
 +
"SigTrans_BCAL" Float_t["NumNeutralHypos"] // Transverse (azimuthal) shower width
 +
 
 +
//NEARBY TRACKS
 +
"TrackBCAL_DeltaPhi": Float_t["NumNeutralHypos"] //is delta to nearest track, is 999.0 if no tracks on BCAL
 +
"TrackBCAL_DeltaZ": Float_t["NumNeutralHypos"] //is delta to nearest track, is 999.0 if no tracks on BCAL
 +
"TrackFCAL_DOCA": Float_t["NumNeutralHypos"] //is DOCA to nearest track, is 999.0 if no tracks on FCAL
 +
 
 +
//PHOTON PID INFO
 +
  //Computed using DVertex (best estimate of reaction vertex using all "good" tracks)
 +
  //Can be used to compute timing chisq //is invalid (0) for non-photons
 +
"PhotonRFDeltaTVar": Float_t["NumNeutralHypos"] //Variance of DVertexX4.T() - RFTime, regardless of which RF bunch is chosen. //RF bunch is combo-dependent
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Particle Data : Detected Reaction Particles ===
+
= TTree Format: Combo-Dependent Data =
 +
* All particle combo data is stored in arrays: array entries correspond to different particle combos
 +
 
 +
=== Particle-Independent Data ===
 
<syntaxhighlight>
 
<syntaxhighlight>
//IDENTIFIER / MATCHING
+
//CUT FLAG
"ObjectID": Int_t //each physical particle has its own # (to keep track of different pid hypotheses for the same particle)
+
"IsComboCut": Bool_t["NumCombos"] //if true, combo has been previously cut (all kFALSE originally, user can apply cuts in TSelector, change this flag, and output new TTree)
"MatchID": Int_t //the array index of the thrown particle it is matched with (-1 for no match)
+
  
//KINEMATICS: MEASURED //At the production vertex
+
//COMBO THROWN MATCHING //not present if not simulated data
"X4_Measured": TLorentzVector //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
+
"IsTrueCombo": Bool_t["NumCombos"] //"IsThrownTopology" = kTRUE, each particle has the right PID, and the combo particle chain matches the thrown decay chain
"P4_Measured": TLorentzVector
+
"IsBDTSignalCombo": Bool_t["NumCombos"] //Similar to "IsTrueCombo", except other thrown topologies that decay to the DReaction topology are marked as signal
 +
                                        //Note that if you have an &omega; or &phi; in your DReaction, you still have to filter your combos prior to BDT
 +
                                        //input to remove duplicate entries. This is because the omega & phi masses are not constrained in the kinematic fit,
 +
                                        //nor should they be in the BDT, so you have duplicate entries from the point-of-view of the BDT due to combinatorics
 +
                                        //(e.g. which pions decayed from the omega, and which ones didn't, are irrelevant to the BDT).
  
// KINEMATICS: END //at the reconstructed position of the BCAL/FCAL/TOF hit
+
//RF
"X4_End": TLorentzVector
+
"RFTime_Measured": Float_t["NumCombos"] //reported at center of target
"P4_End": TLorentzVector
+
"RFTime_KinFit": Float_t["NumCombos"] //reported at center of target //only if spacetime kinematic fit performed
  
//KINEMATICS: KINFIT //At the production vertex //only present if kinfit performed
+
//KINEMATIC FIT
"X4_KinFit": TLorentzVector
+
"ChiSq_KinFit": Float_t["NumCombos"] //only if kinematic fit performed
"P4_KinFit": TLorentzVector
+
"NDF_KinFit": UInt_t["NumCombos"] //only if kinematic fit performed // = 0 if kinematic fit doesn't converge
  
// KINEMATICS: OTHER
+
//UNUSED ENERGY
"PathLength": Double_t //from dPosition_KinFit/Measured (KinFit if performed) to dPosition_End
+
"Energy_UnusedShowers": Float_t["NumCombos"] // summed energy of neutral showers in the event not included in the combo (requiring unused showers are in time and have a polar angle > 2 degrees to reduce contamination from EM background)
  
// PID QUALITY:
+
//UNUSED TRACKS //For tracks unused by combo, the hypo chosen is the one with the best tracking FOM
"NDF_Tracking": UInt_t //for charged only
+
"SumPMag_UnusedTracks": Float_t["NumCombos"]
"ChiSq_Tracking": Double_t //for charged only
+
"SumP3_UnusedTracks": TClonesArray(TVector3["NumCombos"])
"NDF_Timing": UInt_t
+
"ChiSq_Timing_Measured": Double_t //using measured data
+
"ChiSq_Timing_KinFit": Double_t //using kinematic fit data //only present if kinfit performed
+
"NDF_DCdEdx": UInt_t //for charged only
+
"ChiSq_DCdEdx": Double_t //for charged only
+
  
// DEPOSITED ENERGY:
 
"dEdx_CDC": Double_t //for charged only
 
"dEdx_FDC": Double_t //for charged only
 
"dEdx_TOF": Double_t //for charged only
 
"dEdx_ST": Double_t //for charged only
 
"Energy_BCAL": Double_t
 
"Energy_FCAL": Double_t
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Particle Data : Unused Hypotheses ===
+
=== Particle Branch-Name Prefixes ===
<syntaxhighlight>
+
//IDENTIFIERS / MATCHING
+
"ObjectID": Int_t["NumUnused"] //each physical particle has its own # (to keep track of different pid hypotheses for the same particle)
+
"PID": UInt_t["NumUnused"] //Particle_t value
+
"MatchID": Int_t //the array index of the thrown particle it is matched with (-1 for no match)
+
  
//KINEMATICS: MEASURED  //At the production vertex
+
Example Reaction (b1pi):
"P4_Measured": TClonesArray(TLorentzVector["NumUnused"])
+
* &gamma; p &rarr;&omega;, &pi;<sup>+</sup>, &pi;<sup>-</sup>, (p)
"X4_Measured": TClonesArray(TLorentzVector["NumUnused"]) //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
+
** &omega; &rarr; &pi;<sup>+</sup>, &pi;<sup>-</sup>, &pi;<sup>0</sup>
 +
*** &pi;<sup>0</sup> &rarr; &gamma; &gamma;
  
// KINEMATICS: END //at the reconstructed position of the BCAL/FCAL/TOF hit
+
'''Branch Names:'''
"P4_End": TClonesArray(TLorentzVector["NumUnused"])
+
* Beam: <span style="color:red">"ComboBeam"</span>
"X4_End": TClonesArray(TLorentzVector["NumUnused"])
+
* Detected: <span style="color:red">"PiMinus1"</span>, <span style="color:red">"PiPlus1"</span>, <span style="color:red">"PiPlus2"</span>, <span style="color:red">"PiMinus2"</span>, <span style="color:red">"Photon1"</span>, <span style="color:red">"Photon2"</span>
 +
* Decaying: <span style="color:red">"DecayingPi0"</span>
 +
* Missing: <span style="color:red">"MissingProton"</span>
  
// KINEMATICS: OTHER
+
=== Combo Beam Particles <span style="color:blue">(If Any)</span> ===
"PathLength": Double_t["NumUnused"] //from Position_Measured to Position_End
+
* All branch names are prefixed with <span style="color:red">"ComboBeam__"</span>
 
+
** E.g. <span style="color:red">"ComboBeam__BeamIndex"</span>
// PID QUALITY:
+
<syntaxhighlight>
"NDF_Tracking": UInt_t["NumUnused"] //for charged only
+
//IDENTIFIER
"ChiSq_Tracking": Double_t["NumUnused"] //for charged only
+
"BeamIndex": Int_t["NumCombos"] //array index to the "Beam__" branches that correspond to this particle
"NDF_Timing": UInt_t["NumUnused"]
+
"ChiSq_Timing": Double_t["NumUnused"]
+
"NDF_DCdEdx": UInt_t["NumUnused"] //for charged only
+
"ChiSq_DCdEdx": Double_t["NumUnused"] //for charged only
+
  
// DEPOSITED ENERGY:
+
//KINEMATICS: KINFIT //At the interaction vertex //only present if kinfit performed
"dEdx_CDC": Double_t["NumUnused"] //for charged only
+
"X4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if p4-only fit
"dEdx_FDC": Double_t["NumUnused"] //for charged only
+
"P4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if vertex-only or spacetime-only fit, unless beam is charged
"dEdx_TOF": Double_t["NumUnused"] //for charged only
+
"dEdx_ST": Double_t["NumUnused"] //for charged only
+
"Energy_BCAL": Double_t["NumUnused"]
+
"Energy_FCAL": Double_t["NumUnused"]
+
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== Event-Independent Information ===
+
=== Combo Tracks <span style="color:blue">(If Any)</span> ===
* Stored in <span style="color:#0000FF">TTree</span>::<span style="color:#008000">fUserInfo</span> (a <span style="color:#008000">TList</span>*)
+
* All branch names are prefixed with the particle name
 +
** E.g. <span style="color:red">"Proton__ChargedIndex"</span>, <span style="color:red">"PiMinus1__P4_KinFit"</span>
 +
<syntaxhighlight>
 +
//IDENTIFIER
 +
"ChargedIndex": Int_t["NumCombos"] //array index to the "ChargedHypo__" branches that correspond to this particle
  
* <span style="color:red">"MiscInfoMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:#0000FF">TObjString</span> -> <span style="color:#0000FF">TObjString</span>
+
//PID INFO: MEASURED //using combo RF bunch
** <span style="color:red">"KinFitType"</span> -> <span style="color:#0000FF">DKinFitType</span> (converted to <span style="color:#0000FF">TObjString</span>)
+
"Beta_Timing_Measured": Float_t["NumCombos"] // = Path_Length/(c*Delta_t)
** <span style="color:red">"Target"</span> -> <span style="color:#0000FF">Particle_t</span> (converted to <span style="color:#0000FF">TObjString</span>) //if a target particle was specified
+
"ChiSq_Timing_Measured": Float_t["NumCombos"]
** <span style="color:red">"Missing"</span> -> <span style="color:#0000FF">Particle_t</span> (converted to <span style="color:#0000FF">TObjString</span>) //if a missing particle was specified
+
  
* <span style="color:red">"NameToPIDMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"UniqueParticleName"</span> (<span style="color:#0000FF">TObjString</span>) -> <span style="color:#0000FF">Particle_t</span> (converted to <span style="color:#0000FF">TObjString</span>)
+
//PID INFO: KINFIT //using combo RF bunch //not present if time constrained //uses combo vertex & p4 if kinfit
 +
"Beta_Timing_KinFit": Float_t["NumCombos"] // = Path_Length/(c*Delta_t)
 +
"ChiSq_Timing_KinFit": Float_t["NumCombos"]
  
* <span style="color:red">"NameToPositionMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"UniqueParticleName"</span> (<span style="color:#0000FF">TObjString</span>) -> <span style="color:red">"StepIndex_ParticleIndex"</span> (stored in <span style="color:#0000FF">TObjString</span>) (ParticleIndex = <span style="color:red">-1</span> for initial, <span style="color:red">-2</span> for target, <span style="color:red">0+</span> for final state)
+
//KINEMATIC FIT KINEMATICS //only present if kinfit performed
 +
"X4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if p4-only fit
 +
"P4_KinFit": TClonesArray(TLorentzVector["NumCombos"])
 +
</syntaxhighlight>
  
* <span style="color:red">"PositionToNameMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"StepIndex_ParticleIndex"</span> (stored in <span style="color:#0000FF">TObjString</span>) (ParticleIndex = <span style="color:red">-1</span> for initial, <span style="color:red">-2</span> for target, <span style="color:red">0+</span> for final state) -> <span style="color:red">"UniqueParticleName"</span> (<span style="color:#0000FF">TObjString</span>)
+
=== Combo Neutrals <span style="color:blue">(If Any)</span> ===
 
+
* All branch names are prefixed with the particle name
* <span style="color:red">"PositionToPIDMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"StepIndex_ParticleIndex"</span> (stored in <span style="color:#0000FF">TObjString</span>) (ParticleIndex = <span style="color:red">-1</span> for initial, <span style="color:red">-2</span> for target, <span style="color:red">0+</span> for final state) -> <span style="color:#0000FF">Particle_t</span> (converted to <span style="color:#0000FF">TObjString</span>)
+
** E.g. <span style="color:red">"Photon1__NeutralIndex"</span>, <span style="color:red">"Neutron__P4_KinFit"</span>
 
+
== C++ Classes (<span style="color:red">Not Implemented Yet</span>) ==
+
* '''Data Structures:'''
+
** <span style="color:#0000FF">DTreeParticle</span>: roughly mirrors <span style="color:#0000FF">DKinematicData</span>: kinematics + PID info of track
+
** <span style="color:#0000FF">DTreeStep</span>: roughly mirrors <span style="color:#0000FF">DParticleComboStep</span>: collection of <span style="color:#0000FF">DTreeParticle</span>'s for a given step of a reaction (e.g. photoproduction, &Lambda; decay, &pi;<sup>0</sup> decay, etc.)
+
** <span style="color:#0000FF">DTreeCombo</span>: roughly mirrors <span style="color:#0000FF">DParticleCombo</span> (collection of <span style="color:#0000FF">DTreeStep</span>'s for a given reaction), + detected particles not used in the combo
+
** <span style="color:#0000FF">DTreeEvent</span>: contains <span style="color:#0000FF">DTreeCombo</span>'s for each output <span style="color:#0000FF">DReaction</span>, + thrown tracks
+
* '''Extensible:'''
+
** Each class has maps to contain additional data (<span style="color:#0000FF">TObject</span>* and double, map keys are string): custom branches in the TTree will be added here.
+
* '''Usage:'''
+
** Process with a <span style="color:#0000FF">TSelector</span>.
+
** <span style="color:#0000FF">TTree</span>::<span style="color:#008000">Draw</span>() and <span style="color:#0000FF">TTree</span>::<span style="color:#008000">Project</span>() will not work due to nested classes/containers.
+
 
+
=== DTreeParticle ===
+
* Roughly mirrors <span style="color:#0000FF">DKinematicData</span>: 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 &Xi;<sup>-</sup>, 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.
+
 
<syntaxhighlight>
 
<syntaxhighlight>
class DTreeParticle : public TObject
+
//IDENTIFIER
{
+
"NeutralIndex": Int_t["NumCombos"] //array index to the "NeutralHypo__" branches that correspond to this particle
  public:
+
                                  //Note that they may not have the same PID (and thus P4) as this!!
    // PID:
+
                                      //If this is a PID not created by default (e.g. K0Long)
    Particle_t dPID;
+
  
    // KINEMATICS: Measured
+
//KINEMATICS: MEASURED  //At the production vertex
    TVector3 dPosition_Measured; //the position where the particle is produced
+
"P4_Measured": TClonesArray(TLorentzVector["NumCombos"])
    Double_t dTime_Measured; //time of the track at dPosition_Measured, projected from the TOF/BCAL/FCAL hit
+
"X4_Measured": TClonesArray(TLorentzVector["NumCombos"]) //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
    TVector3 dMomentum_Measured; //momentum of the track at dPosition_Start
+
  
    // KINEMATICS: KinFit
+
//MEASURED PID INFO
    TVector3 dPosition_KinFit; //the position where the particle is produced
+
"Beta_Timing_Measured": Float_t["NumCombos"] // = Path_Length/(c*Delta_t)
    Double_t dTime_KinFit; //time of the track at dPosition_KinFit
+
"ChiSq_Timing_Measured": Float_t["NumCombos"] //only present if photon
    TVector3 dMomentum_KinFit; //momentum of the track at dPosition_KinFit
+
  
    // KINEMATICS: End
+
//KINEMATIC FIT PID INFO
    TVector3 dPosition_End; //detected particles: the reconstructed position of the BCAL/FCAL/TOF hit; decaying particles: the point where it decays
+
"Beta_Timing_KinFit": Float_t["NumCombos"] // = Path_Length/(c*Delta_t) //not present if p4-only fit
    Double_t dTime_End; //time of the track at dPosition_End
+
"ChiSq_Timing_KinFit": Float_t["NumCombos"] //only present if photon //not present if p4-only fit
    TVector3 dMomentum_End; //momentum of the track at dPosition_End
+
  
    // KINEMATICS: Other
+
//KINEMATIC FIT KINEMATICS //only present if kinfit performed
    Double_t dPathLength; //from dPosition_KinFit/Measured (if kinfit performed/not-performed) to dPosition_End
+
"X4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if p4-only fit
 +
"P4_KinFit": TClonesArray(TLorentzVector["NumCombos"])
 +
</syntaxhighlight>
  
    // PID QUALITY:
+
=== Combo Decaying Particles <span style="color:blue">(If Any, If Detached/KinFit)</span> ===
    UInt_t dNDF_Tracking;
+
* All branch names are prefixed with <span style="color:red">"Decaying"</span> and the particle name
    Double_t dChiSq_Tracking;
+
** E.g.: <span style="color:red">"DecayingPi0__X4"</span>
    UInt_t dNDF_Timing;
+
<syntaxhighlight>
    Double_t dChiSq_Timing;
+
    UInt_t dNDF_DCdEdx;
+
    Double_t dChiSq_DCdEdx;
+
 
+
    // DEPOSITED ENERGY:
+
    map<DetectorSystem_t, Double_t> 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_t> dCustomVariables; //key is unique string, Double_t is value
+
    map<string, const TObject*> dCustomObjects; //key is unique string, TObject* is object
+
  
  ClassDef(DTreeParticle, 1)
+
//KINEMATICS: //At the decay vertex
};
+
"X4": TLorentzVector["NumCombos"] //only present if has a detached vertex //kinematic fit result if kinfit performed, else reconstructed from detected particles
 +
"PathLengthSigma": Float_t["NumCombos"] //only present if has a detached vertex and both vertices are fit
 +
"P4_KinFit": TLorentzVector["NumCombos"] //only present if kinfit performed
 
</syntaxhighlight>
 
</syntaxhighlight>
  
=== DTreeStep ===
+
=== Combo Missing Particles <span style="color:blue">(If Any & If KinFit)</span> ===
* Roughly mirrors <span style="color:#0000FF">DParticleComboStep</span>: collection of <span style="color:#0000FF">DTreeParticle</span>'s for a given step of a reaction (e.g. photoproduction, &Lambda; decay, &pi;<sup>0</sup> decay, etc.)
+
* All branch names are prefixed with <span style="color:red">"Missing"</span> and the particle name
* Extensible: maps can be used by users to add their own custom information.
+
** E.g.: <span style="color:red">"MissingProton__P4_KinFit"</span>
 
<syntaxhighlight>
 
<syntaxhighlight>
class DTreeStep : public TObject
+
//KINFIT KINEMATICS: //At its production vertex //only present if kinfit performed
{
+
"P4_KinFit": TLorentzVector["NumCombos"]
  public:
+
</syntaxhighlight>
    // INITIAL PARTICLES:
+
    const DTreeParticle* dInitialParticle; //if is null: decaying or beam particle not yet set!
+
    const DTreeParticle* dTargetParticle; //NULL for no target
+
  
    // FINAL PARTICLES:
+
= TTree Format: <span style="color:#0000FF">DReaction</span> Info =
    deque<DParticle_t> dFinalParticleIDs; //separate in case particle is NULL (e.g. decaying resonance)
+
* Stored in <span style="color:#0000FF">TTree</span>::<span style="color:#008000">fUserInfo</span> (a <span style="color:#0000FF">TList</span>*)
    deque<const DTreeParticle*> dFinalParticles; //particle may be NULL if it is decaying or missing (especially if no kinematic fit was performed!!)
+
  
    // CUSTOM VARIABLES:
+
* <span style="color:red">"ParticleNameList"</span>: <span style="color:#0000FF">TList</span> of the names of the reaction particles in the tree, in the order they were specified in the <span style="color:#0000FF">DReaction</span>.
    map<string, Double_t> dCustomVariables; //key is unique string, Double_t is value
+
    map<string, const TObject*> dCustomObjects; //key is unique string, TObject* is object
+
  
  ClassDef(DTreeStep, 1)
+
* <span style="color:red">"MiscInfoMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:#0000FF">TObjString</span> -> <span style="color:#0000FF">TObjString</span>
};
+
** <span style="color:red">"KinFitType"</span> -> <span style="color:#0000FF">DKinFitType</span> (converted to <span style="color:#0000FF">TObjString</span>)
</syntaxhighlight>
+
** <span style="color:red">"Target__PID"</span> -> <span style="color:#0000FF">int</span> (converted to <span style="color:#0000FF">TObjString</span>): PDG PID of target particle //if a target particle was specified
 +
** <span style="color:red">"Target__Mass"</span> -> <span style="color:#0000FF">double</span> (converted to <span style="color:#0000FF">TObjString</span>): Mass of the target particle. //if a target particle was specified
 +
** <span style="color:red">"Missing__PID"</span> -> <span style="color:#0000FF">int</span> (converted to <span style="color:#0000FF">TObjString</span>): PDG PID of missing particle //if a missing particle was specified
 +
** <span style="color:red">"Target__CenterX"</span> -> <span style="color:#0000FF">double</span> (converted to <span style="color:#0000FF">TObjString</span>): x-coordinate of target center
 +
** <span style="color:red">"Target__CenterY"</span> -> <span style="color:#0000FF">double</span> (converted to <span style="color:#0000FF">TObjString</span>): y-coordinate of target center
 +
** <span style="color:red">"Target__CenterZ"</span> -> <span style="color:#0000FF">double</span> (converted to <span style="color:#0000FF">TObjString</span>): z-coordinate of target center
 +
** <span style="color:red">"MissingNAME__Mass"</span> -> <span style="color:#0000FF">double</span> (converted to <span style="color:#0000FF">TObjString</span>): Mass of the <span style="color:red">'NAME'</span> missing particle (e.g. <span style="color:red">'NAME'</span> = <span style="color:red">Proton</span>). //if a missing particle was specified
 +
** <span style="color:red">"DecayingNAME__Mass"</span> -> <span style="color:#0000FF">double</span> (converted to <span style="color:#0000FF">TObjString</span>): Mass of the <span style="color:red">'NAME'</span> decaying particle (e.g. <span style="color:red">'NAME'</span> = <span style="color:red">Pi0</span>). //if decaying particles were present
  
=== DTreeCombo ===
+
* <span style="color:red">"NameToPIDMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"UniqueParticleName"</span> (<span style="color:#0000FF">TObjString</span>) -> <span style="color:#0000FF">int</span> (PDG) (converted to <span style="color:#0000FF">TObjString</span>)
* Roughly mirrors <span style="color:#0000FF">DParticleCombo</span> (collection of <span style="color:#0000FF">DTreeStep</span>'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.
+
<syntaxhighlight>
+
class DTreeCombo : public TObject
+
{
+
  public:
+
    // STEPS:
+
    deque<const DTreeStep*> dTreeSteps;
+
  
    // RUN, EVENT #'s:
+
* <span style="color:red">"NameToPositionMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"UniqueParticleName"</span> (<span style="color:#0000FF">TObjString</span>) -> <span style="color:red">"StepIndex_ParticleIndex"</span> (stored in <span style="color:#0000FF">TObjString</span>) (ParticleIndex = <span style="color:red">-1</span> for initial, <span style="color:red">-2</span> for target, <span style="color:red">0+</span> for final state)
    UInt_t dRunNumber;
+
    UInt_t dEventNumber;
+
  
    // RF:
+
* <span style="color:red">"PositionToNameMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"StepIndex_ParticleIndex"</span> (stored in <span style="color:#0000FF">TObjString</span>) (ParticleIndex = <span style="color:red">-1</span> for initial, <span style="color:red">-2</span> for target, <span style="color:red">0+</span> for final state) -> <span style="color:red">"UniqueParticleName"</span> (<span style="color:#0000FF">TObjString</span>)
    Double_t dRFTime;
+
    Double_t dRFTime_KinFit;
+
  
    // KINEMATIC FIT:
+
* <span style="color:red">"PositionToPIDMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"StepIndex_ParticleIndex"</span> (stored in <span style="color:#0000FF">TObjString</span>) (ParticleIndex = <span style="color:red">-1</span> for initial, <span style="color:red">-2</span> for target, <span style="color:red">0+</span> for final state) -> <span style="color:#0000FF">int</span> (PDG) (converted to <span style="color:#0000FF">TObjString</span>)
    DKinFitType dKinematicFitType; //Defined in DKinFitResults.h //d_NoFit if not performed
+
    Double_t dChiSq_KinematicFit; //NaN if not performed
+
    UInt_t dNDF_KinematicFit; //0 if not performed
+
  
    // UNUSED PARTICLES:
+
* <span style="color:red">"DecayProductMap"</span>: <span style="color:#0000FF">TMap</span> of <span style="color:red">"DecayingParticleName"</span> (<span style="color:#0000FF">TObjString</span>) -> <span style="color:red">"DecayProductNames"</span> (stored in a <span style="color:#0000FF">TList</span> of <span style="color:#0000FF">TObjString</span> objects).  Excludes resonances and intermediate decays (e.g. if &Xi;<sup>-</sup>&rarr;&pi;<sup>-</sup>&Lambda;&rarr;&pi;<sup>-</sup>&pi;<sup>-</sup>p: will be &Xi;<sup>-</sup>&rarr;&pi;<sup>-</sup>&pi;<sup>-</sup>p and &Lambda; decay not listed)
    vector<const DTreeParticle*> dUnusedDetectedParticles;
+
    vector<const DTreeShower*> dUnusedDetectedShowers;
+
  
    // THROWNS:
+
= Usage =
    Double_t dRFTime_Thrown;
+
    deque<const DTreeParticle*> dThrownParticles;
+
  
    // CUSTOM VARIABLES:
+
=== Create TTrees ===
    map<string, Double_t> dCustomVariables; //key is unique string, Double_t is value
+
* To save data to a <span style="color:#0000FF">TTree</span> for a given <span style="color:#0000FF">DReaction</span>, <span style="color:#0000FF">TTree</span> output must be first be enabled for that reaction.  See [https://halldweb.jlab.org/wiki/index.php/Analysis_DReaction#DReaction_Control_Variables DReaction Control Variables] for details. 
    map<string, const TObject*> dCustomObjects; //key is unique string, TObject* is object
+
** Note: Only one thrown tree will be created during program execution. If the <span style="color:#0000FF">DEventWriterROOT</span>::<span style="color:#008000">Create_ThrownTree</span>() function is called more than once, nothing happens on subsequent calls.
  
  ClassDef(DTreeCombo, 1)
+
<syntaxhighlight>
};
+
#include "ANALYSIS/DEventWriterROOT.h"
 +
//In plugin brun():
 +
const DEventWriterROOT* locEventWriterROOT = NULL;
 +
locEventLoop->GetSingle(locEventWriterROOT);
 +
locEventWriterROOT->Create_DataTrees(locEventLoop); //creates TTrees for all output-enabled DReactions
 +
locEventWriterROOT->Create_ThrownTree("tree_b1pi_thrownmc.root"); //optional: create a ttree containing only the thrown data //string is output file name
 
</syntaxhighlight>
 
</syntaxhighlight>
  
== Custom Branches ==
+
=== Save Data to TTree ===
* This is basically something that you just have to do manually. 
+
* The below only saves the particle combinations (for <span style="color:#0000FF">TTree</span>-output-enabled <span style="color:#0000FF">DReaction</span>'s created in the factory specified by the tag) that survived all of the <span style="color:#0000FF">DAnalysisAction</span> cuts.  
** Note: this actually isn't thread safe: another thread can modify the value to be written to the tree in between the last unlock below and the tree fill call...
+
 
<syntaxhighlight>
 
<syntaxhighlight>
 +
//In plugin evnt()
 +
const DEventWriterROOT* locEventWriterROOT = NULL;
 +
locEventLoop->GetSingle(locEventWriterROOT);
 +
locEventWriterROOT->Fill_DataTrees(locEventLoop, "b1pi_hists"); //string is the DReaction factory tag that the DReactions were created in
 +
</syntaxhighlight>
  
//Create the trees
+
* The below allows you to choose which <span style="color:#0000FF">DParticleCombo</span>'s (<span style="color:#008000">locParticleCombos</span>) of which <span style="color:#0000FF">DReaction</span>'s (<span style="color:#008000">locReaction</span>) to save.
 +
** Beware: the <span style="color:#008000">locParticleCombos</span> MUST have originated from the <span style="color:#008000">locReaction</span> or else this will probably crash (can check <span style="color:#0000FF">DParticleCombo</span>::<span style="color:#008000">Get_Reaction</span>()).
 +
<syntaxhighlight>
 +
//In plugin evnt()
 +
#include "ANALYSIS/DEventWriterROOT.h"
 
vector<const DEventWriterROOT*> locEventWriterROOTVector;
 
vector<const DEventWriterROOT*> locEventWriterROOTVector;
 
locEventLoop->Get(locEventWriterROOTVector); //creates the TTrees for all DReactions upon first call
 
locEventLoop->Get(locEventWriterROOTVector); //creates the TTrees for all DReactions upon first call
 +
locEventWriterROOTVector[0]->Fill_Tree(locEventLoop, locReaction, locParticleCombos);
 +
</syntaxhighlight>
  
//Create the branch
+
* The below fills a <span style="color:#0000FF">TTree</span> that only contains the thrown particle data.
Double_t* locMyVariable = new Double_t;
+
<syntaxhighlight>
string locReactionName = locReaction->Get_ReactionName();
+
//In plugin evnt()
string locTreeName = locReactionName + string("_Tree");
+
const DEventWriterROOT* locEventWriterROOT = NULL;
japp->RootWriteLock(); //always acquire a lock before accessing the global ROOT file
+
locEventLoop->GetSingle(locEventWriterROOT);
{
+
locEventWriterROOT->Fill_ThrownTree(locEventLoop);
  //get the tree
+
</syntaxhighlight>
  gDirectory->cd("/");
+
  gDirectory->cd(locReactionName.c_str());
+
  TTree* locTree = (TTree*)gDirectory->Get(locTreeName.c_str());
+
  locTree->Branch("MyBranchName", locMyVariable, "D");
+
}
+
japp->RootUnLock();
+
  
//Set the data in the branch and fill
+
=== Accessing TTree Data ===
japp->RootWriteLock(); //lock: any thread has access to the tbranch
+
* <span style="color:#0000FF">TTree</span>:
{
+
<syntaxhighlight>
  *locMyVariable = 3.0; //or whatever you want to save
+
MyTree->Draw("PiMinus1__P4_Measured->Theta()"); //draws all particle combinations
}
+
japp->RootUnLock();
+
locEventWriterROOTVector[0]->Fill_Trees(locEventLoop);
+
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
 +
* <span style="color:#0000FF">TBrowser</span> (draws all particle combinations):
 +
[[Image:Mattione_TTreeFormat_b1piTBrowserExample.png|thumb|left|900px|b1pi Events]]
 +
<br style="clear:both;"/>
 +
 +
=== TSelector / TPROOF Links===
 +
* [https://root.cern.ch/drupal/content/proof Documentation Link: PROOF]
 +
* [https://root.cern.ch/drupal/content/proof-multicore-desktop-laptop-proof-lite Documentation Link: PROOF-Lite]
 +
* [https://root.cern.ch/drupal/content/developing-tselector Documentation Link: TSelector]
 +
* [https://root.cern.ch/drupal/content/processing-proof Documentation Link: Full TSelector Example (with PROOF-Lite)]
 +
* [https://root.cern.ch/drupal/content/basic-processing Documentation Link: Process Examples]
 +
* [https://root.cern.ch/drupal/content/handling-large-outputs-root-files Documentation Link: Large Output Files]
 +
* [https://root.cern.ch/drupal/content/loading-macro-or-class Documentation Link: Loading a macro for PROOF]
 +
* [https://root.cern.ch/drupal/content/working-packages-par-files Documentation Link: Working with packages]
 +
 +
= Usage - Advanced =
 +
=== Custom Branches ===
 +
* You can create and fill custom branches by inheriting from the  <span style="color:#0000FF">DEventWriterROOT</span> class to create your own writer class.
 +
* Use the <span style="color:red">trunk/scripts/analysis/MakeEventWriterROOT.pl</span> script to generate the necessary code to do this.
 +
* Run this perl script with no arguments to get complete usage instructions.
 +
 +
=== Preventing Double-Counting ===
 +
* Since you can have multiple particle combinations per event, you have to be very careful to make sure you aren't double-counting when filling your histograms. 
 +
** For example, if you're histogramming the invariant mass of the &pi;<sup>0</sup>'s decay to &gamma;&gamma; in b1pi events using the measured photon data, multiple combinations may use the same showers for the photons, while having different tracks for the other particles.
 +
 +
= Converting for AmpTools =
 +
* To convert the <span style="color:#0000FF">TTree</span> for use as input to AmpTools, use the tree_to_amptools in the gluex_root_analysis repository. Run with no arguments for instructions.

Latest revision as of 10:41, 19 October 2017

TTree Format - Overview

  • Physics Analysis Root TTree (PART) format.

Data Hierarchy

  • One TTree per DReaction, each stored in the ROOT files specified by the user.
    • e.g., If 2 DReactions: missing & detected recoil proton: 2 different trees, could be in separate files or the same file.
  • One TTree entry per event.
  • All particle data stored in arrays/TClonesArray's: one array index per particle.
    • Thrown particles
    • Reconstructed neutral and charged hypotheses (by default: only used ones, but can save all: DReaction setting)
    • Beam photons that are later used in combos (unused beam particles are NOT saved)
    • Combo particle information
  • Event-independent information (e.g. the target, the DReaction decay chain, etc.) is stored in TTree::fUserInfo (a TList*)

DSelector

  • Enables C++ interface to TTree data, provides PROOF-Lite launcher, and much more.
  • Instructions for making and using a DSelector can be found at: Link

TTree Format: Simulated Data

Thrown Non-Particle Data

// EVENT DATA
"RunNumber": UInt_t
"EventNumber": ULong64_t
"MCWeight": Float_t
 
// # PARTICLES //array size of the thrown particle branches
"NumThrown": UInt_t
 
// THROWN REACTION INFO
"NumPIDThrown_FinalState": ULong64_t //the # of thrown final-state particles (+ pi0) of each type (multiplexed in base 10)
                                       //types (in order from 10^0 -> 10^15): g, e+, e-, nu, mu+, mu-, pi0, pi+, pi-, KLong, K+, K-, n, p, p-bar, n-bar
                                       //e.g. particles decaying from final-state particles are NOT included (e.g. photons from pi0, muons from pions, etc.)
                                     //is sum of #-of-PID * 10^ParticleMultiplexPower() (defined in libraries/include/particleType.h)
                                     //ParticleMultiplexPower() returns a different power of 10 for each final-state PID type. 
                                     //A value of 9 should be interpreted as >= 9.  
"PIDThrown_Decaying": ULong64_t //the types of the thrown decaying particles in the event (multiplexed in base 2)
                                //not the quantity of each, just whether or not they were present (1 or 0)
                                //binary power of a PID is given by ParticleMultiplexPower() (defined in libraries/include/particleType.h)
                                //types: most Particle_t's that aren't final state (e.g. lambda, eta, phi, rho0, etc.) see ParticleMultiplexPower()

Thrown Beam Particle

  • All branch names are prefixed with "ThrownBeam__"
//IDENTIFIER
"PID": Int_t //PDG ID value
 
//KINEMATICS: //At the production vertex 
"X4": TLorentzVector //This is the TAGGED energy //Use THIS for binning your results //Is ZERO if NOT TAGGED
"P4": TLorentzVector
"GeneratedEnergy": Float_t

Thrown Products

  • All branch names are prefixed with "Thrown__"
  • NOTE: The only contains particles corresponding to the "FinalState" and "Decaying" tags of DMCThrown.
    • In other words: No resonances, no decay products of final-state particles, and no orphan particles.
//IDENTIFIERS / MATCHING
"ParentIndex": Int_t["NumThrown"] //the thrown particle array index of the particle this particle decayed from (-1 if none (e.g. photoproduced))
"PID": Int_t["NumThrown"] //PDG ID value
 
//MATCHING //only present if reconstructed data present (i.e. not if thrown-only tree)
"MatchID": Int_t["NumThrown"] //the "NeutralID"/"TrackID" of the reconstructed neutral/track that it is matched with (-1 for no match)
"MatchFOM": Float_t["NumThrown"] //Neutrals: confidence level //Tracks: #-matched-hits * hit_fraction //(-1 for no match)
 
//KINEMATICS: //Reported at the particle's production vertex 
"X4": TClonesArray(TLorentzVector["NumThrown"])
"P4": TClonesArray(TLorentzVector["NumThrown"])

TTree Format: Combo-Independent Data

Non-Particle Data

// EVENT DATA
"RunNumber": UInt_t
"EventNumber": ULong64_t
"L1TriggerBits": UInt_t
 
// PRODUCTION SPACETIME
"X4_Production": TLorentzVector //V3 from DVertex (kinfit), t from RF (propagated to V3)
 
// # PARTICLES //these are the array sizes for the particle branches
"NumBeam": UInt_t
"NumChargedHypos": UInt_t
"NumNeutralHypos": UInt_t
 
// TOPOLOGY //only present if simulated data
"IsThrownTopology": Bool_t //Does the DReaction decay chain match the thrown decay chain
 
// UNUSED TRACKS
"NumUnusedTracks": UChar_t
 
//NUM COMBOS
"NumCombos": UInt_t //size of all of the particle-combo-content arrays

Beam Particles (If Used in Combo)

  • Only the beam particles that are included in at least one combo are present.
  • All branch names are prefixed with "Beam__"
//ONLY PRESENT IF BEAM USED IN PARTICLE COMBOS
 
//IDENTIFIERS / MATCHING
"PID": Int_t["NumBeam"] //PDG ID value
"IsGenerator": Bool_t["NumBeam"] // kTRUE/kFALSE if matches the generator beam photon (-1 for no match) //only present if simulated data
 
//KINEMATICS: MEASURED //At the production vertex
"X4_Measured": TClonesArray(TLorentzVector["NumBeam"]) //position is at the production vertex (same as X4_Production(), except the time)
"P4_Measured": TClonesArray(TLorentzVector["NumBeam"])

Charged Track Hypotheses

  • Includes all hypotheses, whether they appear in the combos or not.
  • All branch names are prefixed with "ChargedHypo__"
//IDENTIFIERS / MATCHING
"TrackID": Int_t["NumChargedHypos"] //each physical particle has its own # (to keep track of different pid hypotheses for the same particle)
"PID": Int_t["NumChargedHypos"] //PDG ID value
"ThrownIndex": Int_t["NumChargedHypos"] //the array index of the thrown particle it is matched with (-1 for no match) //only present if simulated data
 
//KINEMATICS: MEASURED  //At the production vertex 
"P4_Measured": TClonesArray(TLorentzVector["NumChargedHypos"])
"X4_Measured": TClonesArray(TLorentzVector["NumChargedHypos"]) //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
 
//TRACKING INFO:
"NDF_Tracking": UInt_t["NumChargedHypos"]
"ChiSq_Tracking": Float_t["NumChargedHypos"]
"NDF_DCdEdx": UInt_t["NumChargedHypos"]
"ChiSq_DCdEdx": Float_t["NumChargedHypos"]
"dEdx_CDC": Float_t["NumChargedHypos"]
"dEdx_FDC": Float_t["NumChargedHypos"]
 
//TIMING INFO
"HitTime": Float_t["NumChargedHypos"] //the system that is hit is in order of preference: BCAL/TOF/FCAL/ST 
                                      //to determine which, look whether energy was deposited in these systems
"RFDeltaTVar": Float_t["NumChargedHypos"] //Variance of X4_Measured.T() - RFTime, regardless of which RF bunch is chosen. 
                                          //Can be used to compute timing ChiSq //RF bunch is combo-dependent
 
//PID INFO
"Beta_Timing": Float_t["NumChargedHypos"] // = Path_Length/(c*Delta_t)
"ChiSq_Timing": Float_t["NumChargedHypos"]
"NDF_Timing": UInt_t["NumChargedHypos"]
 
//HIT ENERGY:
"dEdx_TOF": Float_t["NumChargedHypos"]
"dEdx_ST": Float_t["NumChargedHypos"]
"Energy_BCAL": Float_t["NumChargedHypos"]
"Energy_BCALPreshower": Float_t["NumChargedHypos"]
"Energy_FCAL": Float_t["NumChargedHypos"]
 
//SHOWER WIDTH:
"SigLong_BCAL" Float_t["NumChargedHypos"] // Longitudinal (outward radially from the target) shower width
"SigTheta_BCAL" Float_t["NumChargedHypos"] // Theta shower width
"SigTrans_BCAL" Float_t["NumChargedHypos"] // Transverse (azimuthal) shower width 
 
//SHOWER MATCHING:
"TrackBCAL_DeltaPhi": Float_t["NumChargedHypos"] //999.0 if not matched //units are radians
"TrackBCAL_DeltaZ": Float_t["NumChargedHypos"] //999.0 if not matched //Track position - BCAL Shower
"TrackFCAL_DOCA": Float_t["NumChargedHypos"] //999.0 if not matched

Neutral Particle Hypotheses

  • All branch names are prefixed with "NeutralHypo__"
  • Includes all hypotheses, whether they appear in the combos or not.
  • Discussion on P4 & X4:
    • Note that P4 is not present because it is defined by X4, and X4 is not present because it is defined by the tracks, which are combo-dependent
    • For combo particles, P4 & X4 are listed for each combo
    • If not used in a combo, can be computed using the shower hit information and the vertex & RF-time of your choosing (e.g. combo production-vertex, RF-time)
  • To determine whether is BCAL or FCAL, see which system has non-zero energy
//IDENTIFIERS / MATCHING
"NeutralID": Int_t["NumNeutralHypos"] //each physical particle has its own # (to keep track of different pid hypotheses for the same particle)
"PID": Int_t["NumNeutralHypos"] //PDG ID value
"ThrownIndex": Int_t["NumNeutralHypos"] //the array index of the thrown particle it is matched with (-1 for no match) //only present if simulated data
 
//KINEMATICS: MEASURED  //At the production vertex 
"P4_Measured": TClonesArray(TLorentzVector["NumNeutralHypos"])
"X4_Measured": TClonesArray(TLorentzVector["NumNeutralHypos"]) //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
 
//MEASURED PID INFO
"Beta_Timing": Float_t["NumNeutralHypos"] // = Path_Length/(c*Delta_t)
"ChiSq_Timing": Float_t["NumNeutralHypos"] //-1 if not photon
"NDF_Timing": UInt_t["NumNeutralHypos"] //0 if not photon
 
//SHOWER INFO
"X4_Shower": Float_t["NumNeutralHypos"] //location/time of the reconstructed shower
"Energy_BCAL": Float_t["NumNeutralHypos"] //is 0.0 if shower in FCAL
"Energy_BCALPreshower": Float_t["NumNeutralHypos"] //is 0.0 if shower in FCAL
"Energy_FCAL": Float_t["NumNeutralHypos"] //is 0.0 if shower in BCAL
 
//SHOWER WIDTH:
"SigLong_BCAL" Float_t["NumNeutralHypos"] // Longitudinal (outward radially from the target) shower width
"SigTheta_BCAL" Float_t["NumNeutralHypos"] // Theta shower width
"SigTrans_BCAL" Float_t["NumNeutralHypos"] // Transverse (azimuthal) shower width 
 
//NEARBY TRACKS
"TrackBCAL_DeltaPhi": Float_t["NumNeutralHypos"] //is delta to nearest track, is 999.0 if no tracks on BCAL
"TrackBCAL_DeltaZ": Float_t["NumNeutralHypos"] //is delta to nearest track, is 999.0 if no tracks on BCAL
"TrackFCAL_DOCA": Float_t["NumNeutralHypos"] //is DOCA to nearest track, is 999.0 if no tracks on FCAL
 
//PHOTON PID INFO
   //Computed using DVertex (best estimate of reaction vertex using all "good" tracks)
   //Can be used to compute timing chisq //is invalid (0) for non-photons
"PhotonRFDeltaTVar": Float_t["NumNeutralHypos"] //Variance of DVertexX4.T() - RFTime, regardless of which RF bunch is chosen. //RF bunch is combo-dependent

TTree Format: Combo-Dependent Data

  • All particle combo data is stored in arrays: array entries correspond to different particle combos

Particle-Independent Data

//CUT FLAG
"IsComboCut": Bool_t["NumCombos"] //if true, combo has been previously cut (all kFALSE originally, user can apply cuts in TSelector, change this flag, and output new TTree)
 
//COMBO THROWN MATCHING //not present if not simulated data
"IsTrueCombo": Bool_t["NumCombos"] //"IsThrownTopology" = kTRUE, each particle has the right PID, and the combo particle chain matches the thrown decay chain
"IsBDTSignalCombo": Bool_t["NumCombos"] //Similar to "IsTrueCombo", except other thrown topologies that decay to the DReaction topology are marked as signal
                                        //Note that if you have an &omega; or &phi; in your DReaction, you still have to filter your combos prior to BDT 
                                        //input to remove duplicate entries. This is because the omega & phi masses are not constrained in the kinematic fit, 
                                        //nor should they be in the BDT, so you have duplicate entries from the point-of-view of the BDT due to combinatorics 
                                        //(e.g. which pions decayed from the omega, and which ones didn't, are irrelevant to the BDT). 
 
//RF
"RFTime_Measured": Float_t["NumCombos"] //reported at center of target
"RFTime_KinFit": Float_t["NumCombos"] //reported at center of target //only if spacetime kinematic fit performed
 
//KINEMATIC FIT
"ChiSq_KinFit": Float_t["NumCombos"] //only if kinematic fit performed
"NDF_KinFit": UInt_t["NumCombos"] //only if kinematic fit performed // = 0 if kinematic fit doesn't converge
 
//UNUSED ENERGY
"Energy_UnusedShowers": Float_t["NumCombos"] // summed energy of neutral showers in the event not included in the combo (requiring unused showers are in time and have a polar angle > 2 degrees to reduce contamination from EM background)
 
//UNUSED TRACKS //For tracks unused by combo, the hypo chosen is the one with the best tracking FOM
"SumPMag_UnusedTracks": Float_t["NumCombos"]
"SumP3_UnusedTracks": TClonesArray(TVector3["NumCombos"])

Particle Branch-Name Prefixes

Example Reaction (b1pi):

  • γ p →ω, π+, π-, (p)
    • ω → π+, π-, π0
      • π0 → γ γ

Branch Names:

  • Beam: "ComboBeam"
  • Detected: "PiMinus1", "PiPlus1", "PiPlus2", "PiMinus2", "Photon1", "Photon2"
  • Decaying: "DecayingPi0"
  • Missing: "MissingProton"

Combo Beam Particles (If Any)

  • All branch names are prefixed with "ComboBeam__"
    • E.g. "ComboBeam__BeamIndex"
//IDENTIFIER
"BeamIndex": Int_t["NumCombos"] //array index to the "Beam__" branches that correspond to this particle
 
//KINEMATICS: KINFIT //At the interaction vertex //only present if kinfit performed
"X4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if p4-only fit
"P4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if vertex-only or spacetime-only fit, unless beam is charged

Combo Tracks (If Any)

  • All branch names are prefixed with the particle name
    • E.g. "Proton__ChargedIndex", "PiMinus1__P4_KinFit"
//IDENTIFIER
"ChargedIndex": Int_t["NumCombos"] //array index to the "ChargedHypo__" branches that correspond to this particle
 
//PID INFO: MEASURED //using combo RF bunch
"Beta_Timing_Measured": Float_t["NumCombos"] // = Path_Length/(c*Delta_t)
"ChiSq_Timing_Measured": Float_t["NumCombos"]
 
//PID INFO: KINFIT //using combo RF bunch //not present if time constrained //uses combo vertex & p4 if kinfit
"Beta_Timing_KinFit": Float_t["NumCombos"] // = Path_Length/(c*Delta_t)
"ChiSq_Timing_KinFit": Float_t["NumCombos"]
 
//KINEMATIC FIT KINEMATICS //only present if kinfit performed
"X4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if p4-only fit
"P4_KinFit": TClonesArray(TLorentzVector["NumCombos"])

Combo Neutrals (If Any)

  • All branch names are prefixed with the particle name
    • E.g. "Photon1__NeutralIndex", "Neutron__P4_KinFit"
//IDENTIFIER
"NeutralIndex": Int_t["NumCombos"] //array index to the "NeutralHypo__" branches that correspond to this particle
                                   //Note that they may not have the same PID (and thus P4) as this!!
                                      //If this is a PID not created by default (e.g. K0Long)
 
//KINEMATICS: MEASURED  //At the production vertex 
"P4_Measured": TClonesArray(TLorentzVector["NumCombos"])
"X4_Measured": TClonesArray(TLorentzVector["NumCombos"]) //t is the measured value in TOF/BCAL/FCAL projected back to Position_Measured
 
//MEASURED PID INFO
"Beta_Timing_Measured": Float_t["NumCombos"] // = Path_Length/(c*Delta_t)
"ChiSq_Timing_Measured": Float_t["NumCombos"] //only present if photon
 
//KINEMATIC FIT PID INFO
"Beta_Timing_KinFit": Float_t["NumCombos"] // = Path_Length/(c*Delta_t) //not present if p4-only fit
"ChiSq_Timing_KinFit": Float_t["NumCombos"] //only present if photon //not present if p4-only fit
 
//KINEMATIC FIT KINEMATICS //only present if kinfit performed
"X4_KinFit": TClonesArray(TLorentzVector["NumCombos"]) //not present if p4-only fit
"P4_KinFit": TClonesArray(TLorentzVector["NumCombos"])

Combo Decaying Particles (If Any, If Detached/KinFit)

  • All branch names are prefixed with "Decaying" and the particle name
    • E.g.: "DecayingPi0__X4"
//KINEMATICS: //At the decay vertex 
"X4": TLorentzVector["NumCombos"] //only present if has a detached vertex //kinematic fit result if kinfit performed, else reconstructed from detected particles
"PathLengthSigma": Float_t["NumCombos"] //only present if has a detached vertex and both vertices are fit
"P4_KinFit": TLorentzVector["NumCombos"] //only present if kinfit performed

Combo Missing Particles (If Any & If KinFit)

  • All branch names are prefixed with "Missing" and the particle name
    • E.g.: "MissingProton__P4_KinFit"
//KINFIT KINEMATICS: //At its production vertex //only present if kinfit performed
"P4_KinFit": TLorentzVector["NumCombos"]

TTree Format: DReaction Info

  • Stored in TTree::fUserInfo (a TList*)
  • "ParticleNameList": TList of the names of the reaction particles in the tree, in the order they were specified in the DReaction.
  • "MiscInfoMap": TMap of TObjString -> TObjString
    • "KinFitType" -> DKinFitType (converted to TObjString)
    • "Target__PID" -> int (converted to TObjString): PDG PID of target particle //if a target particle was specified
    • "Target__Mass" -> double (converted to TObjString): Mass of the target particle. //if a target particle was specified
    • "Missing__PID" -> int (converted to TObjString): PDG PID of missing particle //if a missing particle was specified
    • "Target__CenterX" -> double (converted to TObjString): x-coordinate of target center
    • "Target__CenterY" -> double (converted to TObjString): y-coordinate of target center
    • "Target__CenterZ" -> double (converted to TObjString): z-coordinate of target center
    • "MissingNAME__Mass" -> double (converted to TObjString): Mass of the 'NAME' missing particle (e.g. 'NAME' = Proton). //if a missing particle was specified
    • "DecayingNAME__Mass" -> double (converted to TObjString): Mass of the 'NAME' decaying particle (e.g. 'NAME' = Pi0). //if decaying particles were present
  • "NameToPIDMap": TMap of "UniqueParticleName" (TObjString) -> int (PDG) (converted to TObjString)
  • "NameToPositionMap": TMap of "UniqueParticleName" (TObjString) -> "StepIndex_ParticleIndex" (stored in TObjString) (ParticleIndex = -1 for initial, -2 for target, 0+ for final state)
  • "PositionToNameMap": TMap of "StepIndex_ParticleIndex" (stored in TObjString) (ParticleIndex = -1 for initial, -2 for target, 0+ for final state) -> "UniqueParticleName" (TObjString)
  • "PositionToPIDMap": TMap of "StepIndex_ParticleIndex" (stored in TObjString) (ParticleIndex = -1 for initial, -2 for target, 0+ for final state) -> int (PDG) (converted to TObjString)
  • "DecayProductMap": TMap of "DecayingParticleName" (TObjString) -> "DecayProductNames" (stored in a TList of TObjString objects). Excludes resonances and intermediate decays (e.g. if Ξ-→π-Λ→π-π-p: will be Ξ-→π-π-p and Λ decay not listed)

Usage

Create TTrees

  • To save data to a TTree for a given DReaction, TTree output must be first be enabled for that reaction. See DReaction Control Variables for details.
    • Note: Only one thrown tree will be created during program execution. If the DEventWriterROOT::Create_ThrownTree() function is called more than once, nothing happens on subsequent calls.
#include "ANALYSIS/DEventWriterROOT.h"
//In plugin brun():
const DEventWriterROOT* locEventWriterROOT = NULL;
locEventLoop->GetSingle(locEventWriterROOT);
locEventWriterROOT->Create_DataTrees(locEventLoop); //creates TTrees for all output-enabled DReactions
locEventWriterROOT->Create_ThrownTree("tree_b1pi_thrownmc.root"); //optional: create a ttree containing only the thrown data //string is output file name

Save Data to TTree

  • The below only saves the particle combinations (for TTree-output-enabled DReaction's created in the factory specified by the tag) that survived all of the DAnalysisAction cuts.
//In plugin evnt()
const DEventWriterROOT* locEventWriterROOT = NULL;
locEventLoop->GetSingle(locEventWriterROOT);
locEventWriterROOT->Fill_DataTrees(locEventLoop, "b1pi_hists"); //string is the DReaction factory tag that the DReactions were created in
  • The below allows you to choose which DParticleCombo's (locParticleCombos) of which DReaction's (locReaction) to save.
    • Beware: the locParticleCombos MUST have originated from the locReaction or else this will probably crash (can check DParticleCombo::Get_Reaction()).
//In plugin evnt()
#include "ANALYSIS/DEventWriterROOT.h"
vector<const DEventWriterROOT*> locEventWriterROOTVector;
locEventLoop->Get(locEventWriterROOTVector); //creates the TTrees for all DReactions upon first call
locEventWriterROOTVector[0]->Fill_Tree(locEventLoop, locReaction, locParticleCombos);
  • The below fills a TTree that only contains the thrown particle data.
//In plugin evnt()
const DEventWriterROOT* locEventWriterROOT = NULL;
locEventLoop->GetSingle(locEventWriterROOT);
locEventWriterROOT->Fill_ThrownTree(locEventLoop);

Accessing TTree Data

  • TTree:
MyTree->Draw("PiMinus1__P4_Measured->Theta()"); //draws all particle combinations
  • TBrowser (draws all particle combinations):
b1pi Events


TSelector / TPROOF Links

Usage - Advanced

Custom Branches

  • You can create and fill custom branches by inheriting from the DEventWriterROOT class to create your own writer class.
  • Use the trunk/scripts/analysis/MakeEventWriterROOT.pl script to generate the necessary code to do this.
  • Run this perl script with no arguments to get complete usage instructions.

Preventing Double-Counting

  • Since you can have multiple particle combinations per event, you have to be very careful to make sure you aren't double-counting when filling your histograms.
    • For example, if you're histogramming the invariant mass of the π0's decay to γγ in b1pi events using the measured photon data, multiple combinations may use the same showers for the photons, while having different tracks for the other particles.

Converting for AmpTools

  • To convert the TTree for use as input to AmpTools, use the tree_to_amptools in the gluex_root_analysis repository. Run with no arguments for instructions.