To allow easy access to the data stored on HAT and ODS, the SFH package provides additional classes derived from FloatFun, IntFun, and FillIterator, plus a set of predefined variables that can be used to immediately access large parts of the available data.
These classes are declared in jbltools/sfh/h1/H1Funs.h, the predefined variables for HAT access are in jbltools/sfh/h1/H1HATVariables.h, and the variables for mODS access are in jbltools/sfh/h1/H1ModsVariables.h.
Depending on whether the variable concerned is of an integer type (char/byte, short, int) or of floating point type (float or double), the corresponding variable is either a IntFun or a FloatFun.
Such variables can immediately be used like this:
#include "jbltools/sfh/h1/H1HatVariables.h" DataLoop::DataLoop() { SFH1F *hRunNumber = new SFH1F ("RunNumber", "RunNumber", 100, 300000., 400000., this, Hat_RunNumber.Float()); SFH1F *hQ2da = new SFH1F ("Q2da", "Q2da", 100, 0., 100., this, Hat_Q2da); SFH1F *hEpz = new SFH1F ("Epz", "Epz", 100, 0., 100., this, Hat_Epz); }
For array type data, like subtrigger information in Hat_Il1ac, we have defined an operator[] that can be used like this:
#include "jbltools/sfh/FillIterators.h" #include "jbltools/sfh/h1/H1HatVariables.h" DataLoop::DataLoop() { // An iterator that loops from 0 to 127 FillIterator& st_iter = *new RangeIterator (0, 127); // A histogram that shows how often raw subtriggers 0 to 127 have fired SFH1F *h_rwst = new SFH1F ("l1rw", "Raw Subtriggers", 128, -0.5, 127.5, this, st_iter.Float(), Hat_Il1rw[st_iter]==1, 0, st_iter); // A histogram that shows Q2 for ST9 events SFH1F *h_q2 = new SFH1F ("Q2", "Q2(DA), ST9", 100, 0., 100., this, Hat_Q2da, Hat_Il1ac[9]==1); }
The operator[] actually returns an object (of a subclass of FloatFun or IntFun), so we could also write
IntFun& Hat_Il1ac[st_iter]; IntFun& Hat_Il1ac[9]; BaseCut& Hat_Il1ac[st_iter]==1; BaseCut& Hat_Il1ac[9]==1;
However, to make a few simple things simple, we have defined a number of predefined variables in file jbltools/sfh/h1/H1ModsVariables.h.
For once, there exist objects that represent the number of particle candidates in the different arrays; these are called mods_NumParticles, mods_NumFNCPart, etc., and are basically of type IntFun.
These numbers are, however, not very interesing, especially, because equivalent HAT variables exist anyway.
Additionally, we have defined iterators over these arrays, with names like mods_Particles, mods_FNCPart, etc.
These iterators are of a special type, so that they can return function objects that give you basic quantities like momentum P, transverse momentum Pt, Mass, etc. These methods have the same names as in class H1Part:
\code #include "jbltools/sfh/h1/H1ModsJpsi.h" DataLoop::DataLoop() { // A histogram that shows the mass of all J/psi candidates SFH1F *h_mass = new SFH1F ("jpsimass", "J/psi mass", 40, 2., 4., this, mods_JPsi.GetMass()); // A histogram that shows the pt distribution of all tracks // with 20 deg < theta < 160deg: SFH1F *h_pt = new SFH1F ("pt", "Track pt", 100, 0., 10., this, mods_SelectedTracks.GetPt(), 20 < 57.2958*mods_SelectedTracks.GetTheta() < 160); }
Additionally, one can use access methods that are specific to the H1Part subclass under consideration like this:
SFH1F *h_t = new SFH1F ("jpsit", "J/psi t", 40, 0., 1., this, mods_JPsi.Float(&H1PartJpsi::Get_t)); }
The predefined iterators have a method Float() that returns a FloatFun object which uses an access methyod (in our case H1PartJpsi::Get_t()).
More complicated things, like cuts on the properties of J/psi decay particles, will, however, involve the writing of your own cut classes, for example:
#include "jbltools/sfh/BaseCut.h" #include "H1Mods/H1PartSelTrack.h" #include "H1Mods/H1PartJPsi.h" #include "H1Mods/H1PartJPsiArrayPtr.h" #include "H1Mods/H1PartMuon.h" static H1PartJPsiArrayPtr jpsi; // Base class: Stores the iterator class JpsiBaseCut: public BaseCut { public: JpsiBaseCut (FillIterator& iter_) : iter(iter_) {}; protected: FillIterator& iter; }; // Selects only elastic J/psi candidates class JpsiElasticCut: public JpsiBaseCut { public: JpsiElasticCut (FillIterator& iter_) : JpsiBaseCut(iter_) {}; virtual bool operator() () const { return (iter() > -1) && (jpsi[iter()]->IsElastic() == kTRUE); }; }; // Selects only J/psi candidates decaying to 2 identified muons class Jpsi2MuCut: public JpsiBaseCut { public: Jpsi2MuCut (FillIterator& iter_) : JpsiBaseCut(iter_) {}; virtual bool operator() () const { return (iter() > -1) && (jpsi[iter()]->GetTrack1()->GetParticle()->IsMuon()) && (jpsi[iter()]->GetTrack2()->GetParticle()->IsMuon()); }; };
But this code is still easy enough to be completely contained in a single header file, without the need for a .C file, and the resulting analysis code will look very clean:
BaseCut& jpsielastic = *new JpsiElasticCut (mods_JPsi); BaseCut& jpsi2mu = *new Jpsi2MuCut (mods_JPsi); FloatFun& jpsimass = mods_JPsi.GetMass(); Binning massbinning (40, 2., 4.); // Mass histogram for elastic J/psi mesons decaying to 2 muons: SFH1F *hJpsiElasticTT = new SFH1F ("jpsi", "J/psi->(#mu-#mu)", massbinning, this, jpsimass, jpsielastic && jpsi2mu, 0, mods_JPsi);
The SFH package provides means for a generic access to bank objects through classes defined in jbltools/sfh/h1/H1BankFuns.h.
Here is some example code:
#include "jbltools/sfh/h1/H1BankFuns.h" DataLoop::DataLoop() { // An object that represents the dtra (DST track) bank: JBLH1Bank& dtra = *new JBLH1Bank ("DTRA"); // An iterator that loops over all DTRA tracks JBLH1BankIterator& dtra_it = dtra.iter(); // A histogram that the pt of all DTRA tracks with 20<theta<160 deg: // (column 0 of the bank contains 1/pt, signed, // column 2 contains the theta value): SFH *h = new SFH1F ("dtrapt", "DTRA track pt", 100, 0., 10., this, 1/abs(dtra_it.GetFloat(0)), // the track pt 20 < 57.2958*dtra_it.GetFloat(2) < 160, // cut on theta 0, // weight 1 dtra_it); // the track iterator }
Objects of type JBLH1Bank represent an H1 bank. Upon creation, they create an H1BankPtr object that points to the bank.
An JBLH1Bank object has a method iter() that returns an JBLH1BankIterator object, i.e. a special FillIterator, that can be used to loop over the rows of the bank.
An JBLH1BankIterator object has methods GetFloat(i), GetFloatFromInt(i), and GetInt(i) which create function objects that return the value of column i of the row selected by the iterator. GetFloat and GetFloatFromInt return FloatFun objects for columns that are float- or int-valued, respectively, and GetInt returns an IntFun object for an int-valued column.
Therefore, one could also write code like this:
JBLH1Bank& dtra = *new JBLH1Bank ("DTRA"); JBLH1BankIterator& dtra_it = dtra.iter(); // Azimuthal angle phi FloatFun& dtraPhi = dtra_it.GetFloat(1); // Track transverse momentum FloatFun& dtraPt = 1./abs(dtra_it.GetFloat(0)); // Link to forward track, 0 for central tracks IntFun& dtraForw = dtra_it.GetInt(14); // Cut on theta: BaseCut& thetaCut = 20 < 57.2958*dtra_it.GetFloat(2) < 160; // Cut on central tracks BaseCut& centralCut = dtra_it.GetInt(14)==0;