| On this page |
|---|
| How do I use this thing? |
| Great, what does it do (and how)? |
| The Histograms |
| Adding NEW histograms |
| To Create a new histogram class |
After compiling LoadPlots.C in root, the first time you run the Loop() function you may get a crash (segmentation violation), but if you quit root, load LoadPlots.C again, it should be fine. The problem has to do with compiling but hasn't been sorted out yet. Also don't run ReInit() after running Loop(true), it will crash (it's fine with just Loop() ).
When you call the Plots constructor the root files are opened and the root trees loaded into a chain (however the reference file is not yet opened). Histograms and trigsimcert objects are created and initialized but nothing else will happen until you call the Loop function. The Loop function opens the reference file, and loops over all events pulling out the trigsimcert objects (that is things like L1Cal, L1Track etc...) These objects are passed to the histogram class objects which handle all the plotting. The resulting histograms are saved in a postscript file (plots.ps in your output directory). The histograms themselves will be plotted against a set of reference data. The loop function can also be used to generate the reference histograms. Just run the loop function as Loop(true), the input file will be taken to be a set of reference data, and the histograms will be put in a root file called Ref.root in the output directory.
Loading + Compiling:
Running LoadPlots.C within root will load and compile all the
necessary files to run the macro.
Constructor:
As mentioned above, the constructor will open the root files. The input
file is checked before it is opened, if it doesn't exit or can't be
opened for whatever reason, the user is notified of the problem and the
constructor will bail out. Similar for the output directory, however
instead of trying to open a file, a test file is created (called
"test") and will be placed in the directory. If the file can't be
created (ie if the directory doesn't exist) the user is notified and
the constructor bails. The constructor accepts output directories with
or without a '/' at the end. That is "output/dir" and "output/dir/"
are both acceptable. By default the working directory is used for
output, so the constructor can be called with only an input file.
Once the input and output are tested, the input file is opened and
read. The input file should be a text file listing root files to
analyze. A note for the pathological: don't use a path that is longer
than 200 characters, it won't work. It's also not a good idea to have
blank lines, they will can cause problems. Each line is interperted as
a file name, so a blank line is considered a file. Each 'file' (that
is each line) is tested for validity before being accessed and if the
file is not found, you'll get a message that says "Could not open
$filename". So a blank line shouldn't be a problem, you'll just get
error messages saying "Could not open " and the constructor will carry
on trying to open the rest of the input files. As the files are opened
the root trees are extracted and added to a chain. The trees MUST be
labeled as "trigcertTree," so long as they came from trigsimcert, this
should always be true.
Initialization (function Init() ):
Once all the input/output is taken care of the initializing function is
called (a private function, if you want to reinitialize see the section
on ReInit). Here the trigsimcert objects are created (ie L1Cal, etc...)
as well as TClonesArray's which will act as branches. Once created the
TClonesArrays are initialized to the proper branches from the tree
chain. Finally histogram classes are created and initialized via their
respective constructors (which make create empty histograms).
Reinitializing (function ReInit() ):
Once you have created a Plots object, you can explicitly reinitialize
it. This public function will delete the TClonesArrays and the
histograms and then call Init() to recreate them. If you want to run
Loop twice on the same Plots object, call this function after the 1st
Loop. NOTE calling ReInit() after running the Loop function with 'true'
(ie to produce a reference file) will crash. It's beter to just quit
root and load it again if you generate a reference.
Loop:
The looping function, it loops over all events in the chain extracting
trigsimcert objects. Once an object is extracted it is passed to it's
histogram object which fills the histograms for that particular object.
Internal loops are used for branches which have more that one object
per event (ie electrons, jets etc... that is, most branches). All the
histogram classes have a function called Fill(Object) which take an
instance of the object it plots.
Example: We have an L2Jet histogram object called hl2jet, and we loop
over the number of level 2 jets, each time we extract a L2Jet object
and call it l2jet, and pass it to the level 2 jet histograms via
hl2jet->Fill(l2jet).
There is a histogram object for each branch in the chain (tree), and
they all call their respective Fill function, even if they don't
currently do anything.
There is also a DoneEvent fucntion which gets called by every
histogram object. This function is used to fill histograms which
contain only one entry per event (ie #things/event etc...).
Once the loop is finished, the reference file is opened (with the standard check to make sure it exists), and a post script file is created. Calls to each histogram objects Draw function are made. The Draw function takes the reference file and postscript file as parameters. The drawing of the histograms is discussed below. Once the histograms are drawn, the reference and postscript files are closed and the Loop will return a value of true (and everyone lived happily ever after).
Loop can also be used to generate a reference file by running
Loop(true). In this case the input is taken to be a list of reference
data. Everything runs the same up to the point where it finishes with
looping over events. Now a reference file is created (as opposed to
opened) and the histograms are writen to this file. Each histogram
object has a Save(file) function. There is no call the the Draw
functions and no postscript file is created. Once the save is complete
the function returns true.
Histogram Classes (for L1L2, L3 is a little different, see below):
All the histogram classes have the same overall structure. They all
start off with a warning to regenerate the reference histograms should
you decide to modify any histogram parameters. And just because it's
really really important, I'll warn you here too: (however it doesn't
look very nice in HTML)
Histogram Classes (for L3):
These classes have the same interface and overall structure, however
they are implemented differently. At L3 the number of different plots
may be dynamic depending on the number of L3 tools used. The histograms
are stored in vectors and created as new tools are found in the
loop. Note that if a tool wasn't present in the reference data set,
there will be no reference to plot against.
HDraw:
This class is inherited by all the histogram classes. It's a general
purpose histogram plotter. Any changes to the format of the histograms
can be done here and will be passed on to all the histogram classes.
The drawing function is called DrawHisto, and takes a rather long list
of arguments:
DrawHisto(TH1F *DATA, bool drawref, TH1F *REF,TLegend *Leg,
char *hist_name,char *file_name,bool Gaussian)
DATA is the histogram to to be plotted as data points. If drawref is true, the reference will be plotted. REF is the reference histogram, if drawref is false, this is ignored (but still needs to be something). Leg is an existing legend to which entries will be added. Thus if you like you can pass a legend with enties already added and they will not be overwritten. hist_name and file_name are strings that are used in error notification (to let user know which class + histogram has the problem). The boolean variable Gaussian defaults to false (ie can skip it). If set as true the histogram is 'treated' as a gaussian like distribution (has a peak...), currently all this actually does is has the RMS displayed in the legend.
Since all the histograms are plotted by the same function, they will have the same format:
- Data appear as black cross'
- Reference appears as solid red line with a red axis on the right
- The histograms are rescaled to provide a little extra clearance on
the top margin.
- Reference is scaled by area
- The Legend will displat the reduced chi^2 (unless it's 0), and
the underflow/overflow of the data (if there is any) as well as the
root-mean-square of the data and reference (format is
'DataRMS/RefRMS') if the 'Gaussian' variable is true. If the chi^2
value if higher that some parameter (currently set to 3), a red star
will appear beside the chi^2.
In determining the reduced chi^2 from the 'full' chi^2, only bins with a non-zero entry in the reference are used. That is, if there are 50 bins in a histogram, but only 40 bins in the reference have non-zero entries then the reduced chi^2 is chi^2 / 40.

There are two ways to do this, the easiest is to simply add another
histogram to an existing histogram class. This might be best if the
desired histogram makes use of a branch that already has plots. On the
other hand, if you've created a new trigsimcert class and want to plot
histograms for it you'll have to create a NEW histogram class and then
include it in the appropriate places (see below).
This is rather straight forward and can be done by modifying the
appropriate histogram class, you won't have to touch any other files.
As mentioned before, L1L2 and L3 are handled differently, first we'll
go through adding to a L1L2 histogram class.
Open up the desired histogram class source located in macros/HistoFill/
First define the parameters for the histogram (about line 40 or so).
Say we want to make a new histogram called NEWHISTO, define:
const Float_t HISTOmax = 10;
const Float_t HISTOmin = 0;
const Int_t HISTObins= 20;
const char HISTOaxis[]="The X axis";
Note that these are GLOBAL constants, they CAN NOT conflict this other
histogram classes. By convention the histograms are all names with
uppercase letters. Next define the histogram itself in the class
declaration:
...
private:
TH1F *NEWHISTO;
...
Now initialize the histogram in the constructor:
NEWHISTO = new TH1F("l2histoclass_NEWHISTO","A TITLE",HISTObins,HISTOmin,HISTOmax);
//Set x axis titles:
NEWHISTO->GetXaxis()->SetTitle(HISTOaxis);NEWHISTO->GetXaxis()->CenterTitle();
Add a delete command in the destructor:
delete NEWHISTO;
Add a Fill command to either the Fill function, or the DoneEvent
function (to Fill if there is more than one instance/event, or
to DoneEvent if there is only one instance/event). If you use DoneEvent
you may need to change the declaration to include the trigsimcert
object
ie before: after:
void DoneEvent(); void DoneEvent(L1Cal *l1cal);
Add the fill command as (supstitute the appropriate class + accessor):
NEWHISTO->Fill(l1cal->Et());
Add a Write command to the Save function:
NEWHISTO->Write();
Now Draw the histogram (...using the Draw function...)
Histograms are drawn on canvas' of four plots each, If there are less
than four histogram when you add, then you need only select the next
pad and draw. If there are already four plots, you will have to clear
the canvas after it has been written to the postscript file:
Less than four plots (this example assumes there are three):
After the last plot but before the ps-NewPage() add:
cl1cal->cd(4);
TLegend *Leg4=new TLegend(.75,.75,.99,.99,"");
if(drawref)
{
//DRAW WITH REFERENCE:
TH1F *NEWHISTOref=(TH1F*) ref->Get("l1cal_NEWHISTO");
DrawHisto(NEWHISTO,drawref,NEWHISTOref,Leg1,"NEWHISTO",THISFILE);
}
//DRAW WITHOUT REFERENCE:
else DrawHisto(NEWHISTO,drawref,0,Leg1,"NEWHISTO",THISFILE);
If there is four (or 8 or whatever):
After the canvasname->Update() command:
First turn off the postscript and clear the canvas:
if(post) ps->Off();
canvasname->Clear(); //NOTE: This hasn't yet been tested, you may need to fiddle with it.
canvasname->Divide(2,2);
then draw as above, and repeat the updating of the postscript:
if(post){ ps->On(); ps->NewPage();}
canvasname->Update();
if(!debug) canvasname->Close();
And that's it, you're ready to go.
The Best way to do this is just to copy one of the existing classes and
modify to suit your needs. Here we'll outline how this is done.
We'll make a skeleton histogram class to use a working trigsimcert
class. To add plots see the above example of adding plots to an
existing class.
1st copy one of the existing histogram classes (make sure you copy an
appropriate class, remember L1L2 and L3 are different).
Similar to above, we'll make a class called Hl3new.C (copied from say
Hl3ele.C) which plots stuff from L3TSCclass.
Proceed as above, with the exception that instead of histogram
declarations we have vectors (change there names as you the histograms)
There are also histograms declared which end in '_T', these are
used as 'temporary histograms', change their names as well. The rest
of the code my look different from L1L2, but the procedure for changing
is the same... go through chaning all 'l3ele' to 'l3new' and change
the histogram/vector names where ever they appear (just look
for anything in uppercase). There are also strings that will need to be
changed, they begin with 'l_' and then the histogram name. Change these
as needed.
The last step that is common to both L1L2 and L3 is adding the
histogram class to the Plots macro. The procedure is the same from
both L1L2 and L3 so we'll just work with the L1 example (Hl1new.C):
In Plots.h:
You need to add your class to all those lengthy lists of declarations
and initializations etc (they're easy to spot, each is about 25 lines
of the same thing). Be consistent in where you add your class. If it's
an L1 class group it with the rest of the L1 stuff, and always put it
in the same position in the lists.
In Class definition:
1st - add a '#include "HistoFill/Hl1new.C" '
2nd - add a 'L1TSCclass *l1tscclass;'
3rd - add a 'TClonesArray * fl1new;'
4th - add a 'Hl1new *hl1new;'
Nothing in the constructor...
In Init():
5th - add a 'l1tscclass = new L1TSCclass();'
6th - add a 'fl1new = new TClonesArray("L1TSCclass",1);'
//Note on 6: the 1 is the number of objects to start out with.
// ie for l1caltwrs there are 1280 towers, so this value is
// 1280.
7th - add a 'fChain->SetBranchAddress("L1TSCclass",&fl1new);'
//Note on 7: the string is the branch name, and is not always the name
// of the trigsimcert class. Particularly if there are two
// branches that use the same class (ie the L1CalTwr class)
8th - add a 'hl1new = new Hl1new();'
In ReInit():
9th - add a 'delete fl1new;'
10th - add a 'delete hl1new;'
DONE
In Plots.C:
First have your new class get filled (keep the same order as above).
Generally this works by:
for(int j=0;j<(fl1new->GetLast()+1);j++)
{
l1new = dynamic_cast
hl1new->Fill(l1new);
}
If you know that there is only one instance of this object you can skip
the loop.
Be sure to add a 'hl1new->DoneEvent(); ' alone with the rest (even if
your DoneEvent function doesn't do anything). add a hl1new->Save(OUT)
with the rest and a hl1new->Draw(REF,ps).
DONE
in loadstuff.C:
add the trigsimcert class you used:
#include "trigsimcert/src/L1TSCclass.cpp"
in loadstuff_linkdef.h:
add you trigsimcert class:
#pragma link C++ class L1TSCclass+;
And that's it. Your new histogram class should now be ready to plot!