Go to the U of M home page
School of Physics & Astronomy
School of Physics and Astronomy Wiki

User Tools


computing:contrib:root:localdoc

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
computing:contrib:root:localdoc [2009/02/19 08:57] – reasons straitcomputing:contrib:root:localdoc [2009/06/01 15:47] (current) – more strait
Line 27: Line 27:
  
 ROOT also makes heavy use of "interpreted C++" (using Cint, the C++ Interpreter), a concept which essentially does not exist outside of ROOT.  It encourages sloppiness with pointers and other woes. ROOT also makes heavy use of "interpreted C++" (using Cint, the C++ Interpreter), a concept which essentially does not exist outside of ROOT.  It encourages sloppiness with pointers and other woes.
 +
 +ROOT is written without the use of namespaces, a C++ concept that helps organize code.  This is why all ROOT classes start with "T", as in TTree, TFile, etc.  The correct (or perhaps "modern") way to do this would be to make a ROOT namespace so that the objects are called ROOT::Tree and ROOT::File.  Or with "using namespace ROOT;" at the top of your code, they would be simply Tree and File.
  
 ===== ROOT's Object Orientation ===== ===== ROOT's Object Orientation =====
Line 36: Line 38:
 ===== Recommendations to ROOT users ===== ===== Recommendations to ROOT users =====
  
-==== Use the STL, not ROOT Classes ====+==== Programming Style ==== 
 + 
 +=== Use the STL, not ROOT Classes ===
  
 The Standard Template Library, which defines the usual versions of strings, vectors, lists, maps, and so on, is documented [[http://www.sgi.com/tech/stl/|at sgi.com]] and in many books and other webpages.  **Always** use these instead of the incompatible versions that ROOT provides (i.e. TString, TVector) unless you are forced not to by pre-existing code. The Standard Template Library, which defines the usual versions of strings, vectors, lists, maps, and so on, is documented [[http://www.sgi.com/tech/stl/|at sgi.com]] and in many books and other webpages.  **Always** use these instead of the incompatible versions that ROOT provides (i.e. TString, TVector) unless you are forced not to by pre-existing code.
Line 42: Line 46:
 If you follow this, your code will be easier to port to a different system if you decide to move away from ROOT.  You will also be able to communicate better with people outside of the ROOT world and you will have better programming skills for when //you// are outside of the ROOT world. If you follow this, your code will be easier to port to a different system if you decide to move away from ROOT.  You will also be able to communicate better with people outside of the ROOT world and you will have better programming skills for when //you// are outside of the ROOT world.
  
-==== Resist Overuse of Objects ====+=== Resist Overuse of Objects ===
  
 ROOT's documentation encourages use of objects when writing procedural code would be easier and more clear.  For instance, they push you to load your data into an object which has functions defined on it that print and loop over the data (abbreviated from [[http://www-root.fnal.gov/root/102/Files.htm|this Fermilab page]]): ROOT's documentation encourages use of objects when writing procedural code would be easier and more clear.  For instance, they push you to load your data into an object which has functions defined on it that print and loop over the data (abbreviated from [[http://www-root.fnal.gov/root/102/Files.htm|this Fermilab page]]):
Line 63: Line 67:
   };   };
  
-This is insanity.  Instead, simply prepare your TTree object (probably loaded from a file) and write the ordinary functions that operate on it:+This is insanity.  Instead, simply prepare your TTree object (probably loaded from a file) and write ordinary functions that operate on it:
  
   void Loop(TTree * awesomedata)   void Loop(TTree * awesomedata)
   {   {
 +    yourdataobject * onedatum = 0;
 +    awesomedata->SetBranchAddress("yourdataobject", &onedatum);
     for(int i = 0; i < awesomedata->GetEntries(); i++){     for(int i = 0; i < awesomedata->GetEntries(); i++){
       awesomedata->GetEntry(i);       awesomedata->GetEntry(i);
Line 80: Line 86:
   }   }
  
-==== Use Good Names ====+The class "yourdataobject" needs only contain the data and not any functions. 
 + 
 +=== Use Good Names ===
  
 Root encourages or uses the following names: Root encourages or uses the following names:
Line 91: Line 99:
 These names are extremely problematic.  "MyClass" is bad because it is totally undescriptive.  Use a name that actually represents what data your class holds.  (It also may give the impression that the names of classes have to start with "My" This is not the case.)  The other, very short, names are bad both because they are undescriptive and because it is nearly impossible to search for them in files. These names are extremely problematic.  "MyClass" is bad because it is totally undescriptive.  Use a name that actually represents what data your class holds.  (It also may give the impression that the names of classes have to start with "My" This is not the case.)  The other, very short, names are bad both because they are undescriptive and because it is nearly impossible to search for them in files.
  
-C++ has, in practical terms, no limit on the length of variable or function names.  While it's not good to use extremely long names either, it's perfectly fine to name your histogram "december_data_hist" If you totally can't think of a good name for the new variable you just made, run the program <code>/local/minos/bin/variablename</code>.  It outputs two short nouns stuck together.  It won't be very descriptive, but at least it will be searchable.+C++ has, in practical terms, no limit on the length of variable or function names.  While it's not good to use extremely long names either, it's perfectly fine to name your histogram "december_data_hist" If you totally can't think of a good name for the new variable you just made, run
 + 
 +<code>/local/minos/bin/variablename</code> 
 + 
 +It outputs two short nouns stuck together.  It probably won't be very descriptive, but at least it will be searchable. 
 + 
 +=== Avoid Unnecessary Pointers === 
 + 
 +ROOT examples often declare //every// object as a pointer (with '*') and with dynamically allocated memory (with 'new').  For example: 
 + 
 +  TH1F * queengrid = new TH1F("it's a grid", "with queens", 10, 0, 10); 
 + 
 +This is dangerous because if you do not call: 
 + 
 +  delete queengrid; 
 + 
 +when you're done with the object, the memory is never released.  This is fine if you're just drawing one plot, but in a large program, you can quickly lose track of things like this and you will then wonder why it uses 3GB of RAM.  The alternative is: 
 + 
 +  TH1F queengrid("it's a grid", "with queens", 10, 0, 10); 
 + 
 +which, besides being safer, is also less typing. 
 + 
 +Now!  Graphical objects like histograms that are meant to appear on the screen //do// need to be allocated with 'new', because otherwise they will disappear from the screen when their function ends.  However, suppose you want to make a histogram, fill it and do a fit, but all you care about is the result of the fit; you never need to see the histogram.  Then declare the histogram without '*' and 'new'
 + 
 +For non-graphical objects like TRandom3, it's an easier call.  Don't make them pointers unless you have a particular reason to.  Despite the example you see that says to do this: 
 + 
 +  TRandom3 * laserfocus = new TRandom3(); 
 + 
 +instead do simply: 
 + 
 +  TRandom3 laserfocus; 
 + 
 +These generate the same random numbers, but the first one stays in memory until you delete it explicitly, while the second stays in memory until the bottom of the function.  By the way, to pass each of these to another function, the functions are declared as: 
 + 
 +  // If you declared with '*' and 'new' 
 +  void IWantRandomNumbers(TRandom3 * laserfocus) 
 +   
 +  // If you simply declared the object: 
 +  // This copies the object: the sequence of random 
 +  // numbers will not be advanced in the calling function 
 +  void IWantRandomNumbers(TRandom3 laserfocus) 
 +   
 +  // This uses the object itself: the sequence of random 
 +  // numbers *will* be advanced in the calling function 
 +  void IWantRandomNumbers(TRandom3 & laserfocus) 
 + 
 +===== How to Run Code ===== 
 + 
 +There are three generic options for running ROOT-based code: 
 + 
 +  - Interpreted in the ROOT (Cint) shell via running the program "root" 
 +  - Compiled via running the program "root" 
 +  - Compiled into a standalone executable 
 + 
 +The first two options are widely used and well documented (?) elsewhere.  Briefly, if one has the program "domyanalysis.C", it must contain the function domyanalysis().  It is run interpreted with 
 + 
 +<code>root 'domyanalysis.C("datafile1.root", 47)'</code> 
 + 
 +where the single quotes protect the parentheses and double quotes from the shell, which otherwise assigns special meaning to them.  To run compiled: 
 + 
 +<code>root 'domyanalysis.C+("datafile1.root", 47)'</code> 
 + 
 +or  
 + 
 +<code>root 'domyanalysis.C++("datafile1.root", 47)'</code> 
 + 
 +where the second form forces recompilation (sometimes necessary if you move to a new machine, for instance). 
 + 
 +The third is rarely used, but probably should be used more.  In this case, you write an ordinary C++ program with the function main() that uses some ROOT objects, i.e.: 
 + 
 +<code> 
 +using namespace std; 
 +#include "TRandom3.h" 
 +#include <iostream> 
 +#include <string> 
 + 
 +int main(int argc, char ** argv) 
 +
 +   int seed = 0; 
 +   string filename; 
 + 
 +   if(argc >= 2) seed = atoi(argv[1]); 
 +   TRandom3 atomlitre(seed); 
 +   cout << "Your random number is " << atomlitre.Rndm() << endl; 
 +    
 +   if(argc >= 3){ 
 +     filename = argv[2]; 
 +     cout << "Your file name is " << filename << endl; 
 +   } 
 + 
 +   return 0; 
 +}  
 +</code> 
 + 
 +and compile it with: 
 + 
 +<code>g++ -o printrandomnumber printrandomnumber.C `root-config --cflags --libs`</code> 
 + 
 +and run it with: 
 + 
 +<code>printrandomnumber 17 datafile.root</code> 
 + 
 +This has two big advantages.  First, you do not need to type all of those quotation marks and parentheses.  Second, your compiled program can run on machines that don't have ROOT installed.  Third, your code is less likely to stop working when the ROOT version changes.  Fourth, it probably runs faster because it doesn't have all the overhead of running root itself.  Fifth, your code looks much more like the ordinary C++ that most programmers are familiar with. Sixth, the compile error messages from g++ are **much** more helpful than those from the ROOT compiler. Ok, more than two. 
 + 
 +====== Making Attractive Plots ====== 
 + 
 +The default ROOT plot is quite nice for screen display.  However, when you print it or use it in a talk, you will discover that the background is grey, which is ugly and wastes toner.  The lines used for histograms and axes are often too thin for easy reading when shown in a talk or paper.  Canvases have beveled edges and legends have drop shadows; whiz-bang, but not really suitable for many environments. 
 + 
 +These things can all be modified either by fiddling with the individual objects or by setting things in the active TStyle.  This code sets things up in a sensible way, although you probably want to pick and choose to suit your own tastes: 
 + 
 +<code> 
 +void SetOKStyle() 
 +
 +  TStyle* OKStyle = new  TStyle("OKStyle", "OK Default Style"); 
 + 
 +  // Colors 
 + 
 +  //set the background color to white 
 +  OKStyle->SetFillColor(10); 
 +  OKStyle->SetFrameFillColor(10); 
 +  OKStyle->SetFrameFillStyle(0); 
 +  OKStyle->SetFillStyle(0); 
 +  OKStyle->SetCanvasColor(10); 
 +  OKStyle->SetPadColor(10); 
 +  OKStyle->SetTitleFillColor(0); 
 +  OKStyle->SetStatColor(10); 
 + 
 +  // Get rid of drop shadow on legends 
 +  // This doesn't seem to work.  Call SetBorderSize(1) directly on your TLegends 
 +  OKStyle->SetLegendBorderSize(1); 
 + 
 +  //don't put a colored frame around the plots 
 +  OKStyle->SetFrameBorderMode(0); 
 +  OKStyle->SetCanvasBorderMode(0); 
 +  OKStyle->SetPadBorderMode(0); 
 + 
 +  //use the primary color palette 
 +  OKStyle->SetPalette(1,0); 
 + 
 +  //set the default line color for a histogram to be black 
 +  OKStyle->SetHistLineColor(kBlack); 
 + 
 +  //set the default line color for a fit function to be red 
 +  OKStyle->SetFuncColor(kRed); 
 + 
 +  //make the axis labels black 
 +  OKStyle->SetLabelColor(kBlack,"xyz"); 
 + 
 +  //set the default title color to be black 
 +  OKStyle->SetTitleColor(kBlack); 
 + 
 +  //set the margins 
 +  OKStyle->SetPadBottomMargin(0.15); 
 +  OKStyle->SetPadLeftMargin(0.15); 
 +  OKStyle->SetPadTopMargin(0.075); 
 +  OKStyle->SetPadRightMargin(0.15); 
 + 
 +  //set axis label and title text sizes 
 +  OKStyle->SetLabelSize(0.05,"xyz"); 
 +  OKStyle->SetTitleSize(0.07,"xyz"); 
 +  OKStyle->SetTitleOffset(0.9,"xyz"); 
 +  OKStyle->SetStatFontSize(0.05); 
 +  OKStyle->SetTextSize(0.07); 
 +  OKStyle->SetTitleBorderSize(0); 
 + 
 +  //set line widths 
 +  OKStyle->SetHistLineWidth(2); 
 +  OKStyle->SetFrameLineWidth(2); 
 +  OKStyle->SetFuncWidth(2); 
 + 
 +  // Misc 
 + 
 +  //align the titles to be centered 
 +  //OKStyle->SetTextAlign(22); 
 + 
 +  //turn off xy grids 
 +  OKStyle->SetPadGridX(0); 
 +  OKStyle->SetPadGridY(0); 
 + 
 +  //set the tick mark style 
 +  OKStyle->SetPadTickX(1); 
 +  OKStyle->SetPadTickY(1); 
 + 
 +  //don't show the fit parameters in a box 
 +  OKStyle->SetOptFit(0000); 
 + 
 +  //set the default stats shown 
 +  OKStyle->SetOptStat("neimr"); 
 + 
 +  //marker settings 
 +  OKStyle->SetMarkerStyle(8); 
 +  OKStyle->SetMarkerSize(0.7); 
 + 
 +  // Fonts 
 +  OKStyle->SetStatFont(12); 
 +  OKStyle->SetLabelFont(12,"xyz"); 
 +  OKStyle->SetTitleFont(12,"xyz"); 
 +  OKStyle->SetTextFont(12); 
 + 
 +  // Set the paper size for output 
 +  OKStyle->SetPaperSize(TStyle::kUSLetter); 
 + 
 +  //done 
 +  OKStyle->cd(); 
 + 
 +  cout << "Using OKStyle" << endl; 
 +
 +</code> 
 + 
computing/contrib/root/localdoc.1235055427.txt.gz · Last modified: 2009/02/19 08:57 by strait