Logo ROOT   6.12/07
Reference Guide
runProof.C File Reference

Detailed Description

Macro to run examples of analysis on PROOF, corresponding to the TSelector implementations found under <ROOTSYS>/tutorials/proof .

This macro uses an existing PROOF session or starts one at the indicated URL. In the case non existing PROOF session is found and no URL is given, the macro tries to start a local PROOF session.

To run the macro:

root[] .L proof/runProof.C+ root[] runProof("<analysis>")

Currently available analysis are (to see how all this really works check the scope for the specified option inside the macro):

  1. "simple"

    Selector: ProofSimple.h.C

    root[] runProof("simple")

    This will create a local PROOF session and run an analysis filling 100 histos with 100000 gaussian random numbers, and displaying them in a canvas with 100 pads (10x10). The number of histograms can be passed as argument 'nhist' to 'simple', e.g. to fill 16 histos with 1000000 entries use

    root[] runProof("simple(nevt=1000000,nhist=16)")

    The argument nhist3 controls the creation of 3d histos to simulate merging load. By default, no 3D hitogram is created.

  2. "h1"

    Selector: tutorials/tree/h1analysis.h.C

    root[] runProof("h1")

    This runs the 'famous' H1 analysis from $ROOTSYS/tree/h1analysis.C.h. By default the data are read from the HTTP server at root.cern.ch, the data source can be changed via the argument 'h1src', e.g.

    root[] runProof("h1,h1src=/data/h1")

    (the directory specified must contain the 4 H1 files).

    The 'h1' example is also used to show how to use entry-lists in PROOF. To fill the list for the events used for the final plots add the option 'fillList':

    root[] runProof("h1,fillList")

    To use the list previously created for the events used for the final plots add the option 'useList':

    root[] runProof("h1,useList")

  3. "event"

    Selector: ProofEvent.h,.C

    This is an example of using PROOF par files. It runs event generation and simple analysis based on the 'Event' class found under test.

    root[] runProof("event")

  4. "eventproc"

    Selector: ProofEventProc.h.C

    This is an example of using PROOF par files and process 'event' data from the ROOT HTTP server. It runs the ProofEventProc selector which is derived from the EventTree_Proc one found under test/ProofBench. The following specific arguments are available:

    • 'readall' to read the whole event, by default only the branches needed by the analysis are read (read 25% more bytes)
    • 'datasrc=<dir-with-files>' to read the files from another server, the files must be named 'event_<num>.root' where <num>=1,2,... or
    • 'datasrc=<file-with-files>' to take the file content from a text file, specified one file per line; usefull when testing differences between several sources and distributions
    • 'files=N' to change the number of files to be analysed (default is 10, max is 50 for the HTTP server).
    • 'uneven' to process uneven entries from files following the scheme {50000,5000,5000,5000,5000} and so on

    root[] runProof("eventproc")

  5. "pythia8"

    Selector: ProofPythia.h.C

    This runs Pythia8 generation based on main03.cc example in Pythia 8.1

    To run this analysis ROOT must be configured with pythia8.

    Note that before executing this analysis, the env variable PYTHIA8 must point to the pythia8100 (or newer) directory, in particular, $PYTHIA8/xmldoc must contain the file Index.xml. The tutorial assumes that the Pythia8 directory is the same on all machines, i.e. local and worker ones.

    root[] runProof("pythia8")

  6. "ntuple"

    Selector: ProofNtuple.h.C

    This is an example of final merging via files created on the workers, using TProofOutputFile. The final file is called ProofNtuple.root and it is created in the directory where the tutorial is run. If the PROOF cluster is remote, the file is received by a local xrootd daemon started for the purpose. Because of this, this example can be run only on unix clients.

    root[] runProof("ntuple")

    By default the random numbers are generate anew. There is the possibility use a file of random numbers (to have reproducible results) by specify the option 'inputrndm', e.g.

    root[] runProof("ntuple(inputrndm)")

    By default the output will be saved in the local file SimpleNtuple.root; location and name of the file can be changed via the argument 'outfile', e.g.

    root[] runProof("simplefile(outfile=/data0/testntuple.root)") root[] runProof("simplefile(outfile=root://aserver//data/testntuple.root)")

  7. "dataset"

    Selector: ProofNtuple.h.C

    This is an example of automatic creation of a dataset from files created on the workers, using TProofOutputFile. The dataset is called testNtuple and it is automatically registered and verified. The files contain the same ntuple as in previous example/tutorial 6 (the same selector ProofNTuple is used with a slightly different configuration). The dataset is then used to produce the same plot as in 5 but using the DrawSelect methods of PROOF, which also show how to set style, color and other drawing attributes in PROOF. Depending on the relative worker perforance, some of the produced files may result in having no entries. If this happens, the file will be added to the missing (skipped) file list. Increasing the number of events (via nevt=...) typically solves this issue.

    root[] runProof("dataset")

  8. "friends"

    Selectors: ProofFriends.h(.C), ProofAux.h(.C)

    This is an example of TTree friend processing in PROOF. It also shows how to use the TPacketizerFile to steer creation of files.

    root[] runProof("friends")

    The trees are by default created in separate files; to create them in the same file use option 'samefile', e.g.

    root[] runProof("friends(samefile)")

  9. "simplefile"

    Selector: ProofSimpleFile.h.C

    root[] runProof("simplefile")

    This will create a local PROOF session and run an analysis filling 16+16 histos with 100000 gaussian random numbers. The merging of these histos goes via file; 16 histos are saved in the top directory, the other 16 into a subdirectory called 'blue'. The final display is done in two canvanses, one for each set of histograms and with 16 pads each (4x4). The number of histograms in each set can be passed as argument 'nhist' to 'simplefile', e.g. to fill 25 histos with 1000000 entries use

    root[] runProof("simplefile(nevt=1000000,nhist=25)")

    By default the output will be saved in the local file SimpleFile.root; location and name of the file can be changed via the argument 'outfile', e.g.

    root[] runProof("simplefile(outfile=/data0/testsimple.root)") root[] runProof("simplefile(outfile=root://aserver//data/testsimple.root)")

  10. "stdvec"

    Selector: ProofStdVect.h.C

    This is an example of using standard vectors (vector<vector<bool> > and vector<vector<float> >) in a TSelector. The same selector is run twice: in 'create' mode it creates a dataset with the tree 'stdvec' containing 3 branches, a vector<vector<bool> > and two vector<vector<float> >. The tree is saved into a file on each worker and a dataset is created with these files (the dataset is called 'TestStdVect'); in 'read' mode the dataset is read and a couple fo histograms filled and displayed.

    root[] runProof("stdvec")

General arguments

The following arguments are valid for all examples (the ones specific to each tutorial have been explained above)

  1. ACLiC mode

    By default all processing is done with ACLiC mode '+', i.e. compile if changed. However, this may lead to problems if the available selector libs were compiled in previous sessions with a different set of loaded libraries (this is a general problem in ROOT). When this happens the best solution is to force recompilation (ACLiC mode '++'). To do this just add one or more '+' to the name of the tutorial, e.g. runProof("simple++")

  2. debug=[what:]level

    Controls verbosity; 'level' is an integer number and the optional string 'what' one or more of the enum names in TProofDebug.h . e.g. runProof("eventproc(debug=kPacketizer|kCollect:2)") runs 'eventproc' enabling all printouts matching TProofDebug::kPacketizer and having level equal or larger than 2 .

  3. nevt=N and/or first=F

    Set the number of entries to N, eventually (when it makes sense, i.e. when processing existing files) starting from F e.g. runProof("simple(nevt=1000000000)") runs simple with 1000000000 runProof("eventproc(first=65000)") runs eventproc processing starting with event 65000 runProof("eventproc(nevt=100000,first=65000)") runs eventproc processing 100000 events starting with event 65000

  4. asyn

    Run in non blocking mode e.g. root[] runProof("h1(asyn)")

  5. nwrk=N

    Set the number of active workers to N, usefull to test performance on a remote cluster where control about the number of workers is not possible, e.g. runProof("event(nwrk=2)") runs 'event' with 2 workers.

  6. punzip

    Use parallel unzipping in reading files where relevant e.g. root[] runProof("eventproc(punzip)")

  7. cache=<bytes> (or <kbytes>K or <mbytes>M)

    Change the size of the tree cache; 0 or <0 disables the cache, value cane be in bytes (no suffix), kilobytes (suffix 'K') or megabytes (suffix 'M'), e.g. root[] runProof("eventproc(cache=0)")

  8. submergers[=S]

    Enabling merging via S submergers or the optimal number if S is not specified, e.g. root[] runProof("simple(hist=1000,submergers)")

  9. rateest=average

    Enable processed entries estimation for constant progress reporting based on the measured average. This may screw up the progress bar in some cases, which is the reason why it is not on by default . e.g. root[] runProof("eventproc(rateest=average)")

  10. perftree=perftreefile.root

    Generate the perfomance tree and save it to file 'perftreefile.root', e.g. root[] runProof("eventproc(perftree=perftreefile.root)")

  11. feedback=name1[,name2,name3,...]|off

    Enable feedback for the specified names or switch it off; by default it is enabled for the 'stats' histograms (events,packest, packets-being processed).

In all cases, to run on a remote PROOF cluster, the master URL must be passed as second argument; e.g.

root[] runProof("simple","master.do.main")

A rough parsing of the URL is done to determine the locality of the cluster. If using a tunnel the URL can start by localhost even for external clusters: in such cases the default locality determination will be wrong, so one has to tell explicity that the cluster is external via the option field, e.g.

root[] runProof("simple","localhost:33002/?external")

In the case of local running it is possible to specify the number of workers to start as third argument (the default is the number of cores of the machine), e.g.

root[] runProof("simple",0,4)

will start 4 workers. Note that the real number of workers is changed only the first time you call runProof into a ROOT session. Following calls can reduce the number of active workers, but not increase it. For example, in the same session of the call above starting 4 workers, this

root[] runProof("simple",0,8)

will still use 4 workers, while this

root[] runProof("simple",0,2)

will disable 2 workers and use the other 2.

Finally, it is possible to pass as 4th argument a list of objects to be added to the input list to further control the PROOF behaviour:

root [] TList *ins = new TList root [] ins->Add(new TParameter<Int_t>("MyParm", 3)) root [] runProof("simple",0,4,ins)

the content of 'ins' will then be copied to the input list before processing.

#include "TCanvas.h"
#include "TChain.h"
#include "TDSet.h"
#include "TEnv.h"
#include "TEntryList.h"
#include "TFile.h"
#include "TFrame.h"
#include "THashList.h"
#include "TList.h"
#include "TPad.h"
#include "TPaveText.h"
#include "TProof.h"
#include "TProofDebug.h"
#include "TString.h"
#include "getProof.C"
void plotNtuple(TProof *p, const char *ds, const char *ntptitle);
void SavePerfTree(TProof *proof, const char *fn);
// Variable used to locate the Pythia8 directory for the Pythia8 example
const char *pythia8dir = 0;
const char *pythia8data = 0;
void runProof(const char *what = "simple",
const char *masterurl = "proof://localhost:40000",
Int_t nwrks = -1, TList *ins = 0)
{
gEnv->SetValue("Proof.StatsHist",1);
TString u(masterurl);
// Determine locality of this session
Bool_t isProofLocal = kFALSE;
if (!u.IsNull() && u != "lite://") {
TUrl uu(masterurl);
TString uopts(uu.GetOptions());
if ((!strcmp(uu.GetHost(), "localhost") && !uopts.Contains("external")) ||
!strcmp(uu.GetHostFQDN(), TUrl(gSystem->HostName()).GetHostFQDN())) {
isProofLocal = kTRUE;
}
// Adjust URL
if (!u.BeginsWith(uu.GetProtocol())) uu.SetProtocol("proof");
uopts.ReplaceAll("external", "");
uu.SetOptions(uopts.Data());
u = uu.GetUrl();
}
const char *url = u.Data();
// Temp dir for PROOF tutorials
// Force "/tmp/<user>" whenever possible to avoid length problems on MacOsX
TString tmpdir("/tmp");
if (!ug) {
Printf("runProof: could not get user info");
return;
}
us.Form("/%s", ug->fUser.Data());
if (!tmpdir.EndsWith(us.Data())) tmpdir += us;
gSystem->mkdir(tmpdir.Data(), kTRUE);
Printf("runProof: unable to get a writable tutorial directory (tried: %s)"
" - cannot continue", tmpdir.Data());
return;
}
TString tutdir = Form("%s/.proof-tutorial", tmpdir.Data());
if (gSystem->AccessPathName(tutdir)) {
Printf("runProof: creating the temporary directory"
" for the tutorial (%s) ... ", tutdir.Data());
if (gSystem->mkdir(tutdir, kTRUE) != 0) {
Printf("runProof: could not assert / create the temporary directory"
" for the tutorial (%s)", tutdir.Data());
return;
}
}
// For the Pythia8 example we need to set some environment variable;
// This must be done BEFORE starting the PROOF session
if (what && !strncmp(what, "pythia8", 7)) {
// We assume that the remote location of Pythia8 is the same as the local one
pythia8dir = gSystem->Getenv("PYTHIA8");
if (!pythia8dir || strlen(pythia8dir) <= 0) {
Printf("runProof: pythia8: environment variable PYTHIA8 undefined:"
" it must contain the path to pythia81xx root directory (local and remote) !");
return;
}
pythia8data = gSystem->Getenv("PYTHIA8DATA");
if (!pythia8data || strlen(pythia8data) <= 0) {
gSystem->Setenv("PYTHIA8DATA", Form("%s/xmldoc", pythia8dir));
pythia8data = gSystem->Getenv("PYTHIA8DATA");
if (!pythia8data || strlen(pythia8data) <= 0) {
Printf("runProof: pythia8: environment variable PYTHIA8DATA undefined:"
" it one must contain the path to pythia81xx/xmldoc"
" subdirectory (local and remote) !");
return;
}
}
TString env = Form("echo export PYTHIA8=%s; export PYTHIA8DATA=%s",
pythia8dir, pythia8data);
TProof::AddEnvVar("PROOF_INITCMD", env.Data());
}
Printf("tutorial dir:\t%s", tutdir.Data());
// Get the PROOF Session
TProof *proof = getProof(url, nwrks, tutdir.Data(), "ask");
if (!proof) {
Printf("runProof: could not start/attach a PROOF session");
return;
}
// Refine locality (PROOF-Lite always local)
if (proof->IsLite()) isProofLocal = kTRUE;
#ifdef WIN32
if (isProofLocal && what && !strcmp(what, "ntuple", 6)) {
// Not support on windows
Printf("runProof: the 'ntuple' example needs to run xrootd to receive the output file, \n"
" but xrootd is not supported on Windows - cannot continue");
return;
}
#endif
TString proofsessions(Form("%s/sessions",tutdir.Data()));
// Save tag of the used session
FILE *fs = fopen(proofsessions.Data(), "a");
if (!fs) {
Printf("runProof: could not create files for sessions tags");
} else {
fprintf(fs,"session-%s\n", proof->GetSessionTag());
fclose(fs);
}
if (!proof) {
Printf("runProof: could not start/attach a PROOF session");
return;
}
// Set the number of workers (may only reduce the number of active workers
// in the session)
if (nwrks > 0)
proof->SetParallel(nwrks);
// Where is the code to run
char *rootbin = gSystem->Which(gSystem->Getenv("PATH"), "root.exe", kExecutePermission);
if (!rootbin) {
Printf("runProof: root.exe not found: please check the environment!");
return;
}
TString rootsys(gSystem->DirName(rootbin));
rootsys = gSystem->DirName(rootsys);
TString tutorials(Form("%s/tutorials", rootsys.Data()));
delete[] rootbin;
// Parse 'what'; it is in the form 'analysis(arg1,arg2,...)'
TString args(what);
args.ReplaceAll("("," ");
args.ReplaceAll(")"," ");
args.ReplaceAll(","," ");
Ssiz_t from = 0;
TString act, tok;
if (!args.Tokenize(act, from, " ")) {
// Cannot continue
Printf("runProof: action not found: check your arguments (%s)", what);
return;
}
// Extract ACLiC mode
TString aMode = "+";
if (act.EndsWith("+")) {
aMode += "+";
while (act.EndsWith("+")) { act.Remove(TString::kTrailing,'+'); }
}
Printf("runProof: %s: ACLiC mode: '%s'", act.Data(), aMode.Data());
// Parse out number of events and 'asyn' option, used almost by every test
TString aNevt, aFirst, aNwrk, opt, sel, punzip("off"), aCache, aOutFile,
aH1Src("http://root.cern.ch/files/h1"),
aDebug, aDebugEnum, aRateEst, aPerfTree("perftree.root"),
aFeedback("fb=stats");
Long64_t suf = 1;
Int_t aSubMg = -1;
Bool_t useList = kFALSE, makePerfTree = kFALSE;
while (args.Tokenize(tok, from, " ")) {
// Debug controllers
if (tok.BeginsWith("debug=")) {
aDebug = tok;
aDebug.ReplaceAll("debug=","");
Int_t icol = kNPOS;
if ((icol = aDebug.Index(":")) != kNPOS) {
aDebugEnum = aDebug(0, icol);
aDebug.Remove(0, icol+1);
}
if (!aDebug.IsDigit()) {
Printf("runProof: %s: error parsing the 'debug=' option (%s) - ignoring", act.Data(), tok.Data());
aDebug = "";
aDebugEnum = "";
}
}
// Number of events
if (tok.BeginsWith("nevt=")) {
aNevt = tok;
aNevt.ReplaceAll("nevt=","");
if (!aNevt.IsDigit()) {
Printf("runProof: %s: error parsing the 'nevt=' option (%s) - ignoring", act.Data(), tok.Data());
aNevt = "";
}
}
// First event
if (tok.BeginsWith("first=")) {
aFirst = tok;
aFirst.ReplaceAll("first=","");
if (!aFirst.IsDigit()) {
Printf("runProof: %s: error parsing the 'first=' option (%s) - ignoring", act.Data(), tok.Data());
aFirst = "";
}
}
// Sync or async ?
if (tok.BeginsWith("asyn"))
opt = "ASYN";
// Number of workers
if (tok.BeginsWith("nwrk=")) {
aNwrk = tok;
aNwrk.ReplaceAll("nwrk=","");
if (!aNwrk.IsDigit()) {
Printf("runProof: %s: error parsing the 'nwrk=' option (%s) - ignoring", act.Data(), tok.Data());
aNwrk = "";
}
}
// Parallel unzipping ?
if (tok.BeginsWith("punzip"))
punzip = "on";
// Number of workers
if (tok.BeginsWith("cache=")) {
aCache = tok;
aCache.ReplaceAll("cache=","");
if (aCache.EndsWith("k")) { aCache.Remove(TString::kTrailing, 'k'); suf = 1024; }
if (aCache.EndsWith("K")) { aCache.Remove(TString::kTrailing, 'K'); suf = 1024; }
if (aCache.EndsWith("M")) { aCache.Remove(TString::kTrailing, 'M'); suf = 1024*1024; }
if (!aCache.IsDigit()) {
Printf("runProof: %s: error parsing the 'cache=' option (%s) - ignoring", act.Data(), tok.Data());
aCache = "";
}
}
// Use submergers?
if (tok.BeginsWith("submergers")) {
tok.ReplaceAll("submergers","");
aSubMg = 0;
if (tok.BeginsWith("=")) {
tok.ReplaceAll("=","");
if (tok.IsDigit()) aSubMg = tok.Atoi();
}
}
// H1: use entry-lists ?
if (tok.BeginsWith("useList")) {
useList = kTRUE;
}
if (tok.BeginsWith("fillList")) {
opt += "fillList";
}
// H1: change location of files?
if (tok.BeginsWith("h1src=")) {
tok.ReplaceAll("h1src=","");
if (!(tok.IsNull())) aH1Src = tok;
Printf("runProof: %s: reading data files from '%s'", act.Data(), aH1Src.Data());
}
// Rate estimation technique
if (tok.BeginsWith("rateest=")) {
tok.ReplaceAll("rateest=","");
if (!(tok.IsNull())) aRateEst = tok;
Printf("runProof: %s: progress-bar rate estimation option: '%s'", act.Data(), aRateEst.Data());
}
// Create and save the preformance tree?
if (tok.BeginsWith("perftree")) {
makePerfTree = kTRUE;
if (tok.BeginsWith("perftree=")) {
tok.ReplaceAll("perftree=","");
if (!(tok.IsNull())) aPerfTree = tok;
}
Printf("runProof: %s: saving performance tree to '%s'", act.Data(), aPerfTree.Data());
}
// Location of the output file, if any
if (tok.BeginsWith("outfile")) {
if (tok.BeginsWith("outfile=")) {
tok.ReplaceAll("outfile=","");
if (!(tok.IsNull())) aOutFile = tok;
}
Printf("runProof: %s: output file: '%s'", act.Data(), aOutFile.Data());
}
// Feedback
if (tok.BeginsWith("feedback=")) {
tok.ReplaceAll("feedback=","");
if (tok == "off" || tok == "OFF" || tok == "0") {
aFeedback = "";
} else if (!(tok.IsNull())) {
if (tok.BeginsWith("+")) {
tok[0] = ',';
aFeedback += tok;
} else {
aFeedback.Form("fb=%s", tok.Data());
}
}
Printf("runProof: %s: feedback: '%s'", act.Data(), aFeedback.Data());
}
}
Long64_t nevt = (aNevt.IsNull()) ? -1 : aNevt.Atoi();
Long64_t first = (aFirst.IsNull()) ? 0 : aFirst.Atoi();
Long64_t nwrk = (aNwrk.IsNull()) ? -1 : aNwrk.Atoi();
from = 0;
// Set number workers
if (nwrk > 0) {
if (proof->GetParallel() < nwrk) {
Printf("runProof: %s: request for a number of workers larger then available - ignored", act.Data());
} else {
proof->SetParallel(nwrk);
}
}
// Debug controllers
if (!aDebug.IsNull()) {
Int_t dbg = aDebug.Atoi();
if (!aDebugEnum.IsNull()) scope = getDebugEnum(aDebugEnum.Data());
proof->SetLogLevel(dbg, scope);
Printf("runProof: %s: verbose mode for '%s'; level: %d", act.Data(), aDebugEnum.Data(), dbg);
}
// Have constant progress reporting based on estimated info
// (NB: may screw up the progress bar in some cases)
if (aRateEst == "average")
proof->SetParameter("PROOF_RateEstimation", aRateEst);
// Parallel unzip
if (punzip == "on") {
proof->SetParameter("PROOF_UseParallelUnzip", (Int_t)1);
Printf("runProof: %s: parallel unzip enabled", act.Data());
} else {
proof->SetParameter("PROOF_UseParallelUnzip", (Int_t)0);
}
// Tree cache
if (!aCache.IsNull()) {
Long64_t cachesz = aCache.Atoi() * suf;
if (cachesz <= 0) {
proof->SetParameter("PROOF_UseTreeCache", (Int_t)0);
Printf("runProof: %s: disabling tree cache", act.Data());
} else {
proof->SetParameter("PROOF_UseTreeCache", (Int_t)1);
proof->SetParameter("PROOF_CacheSize", cachesz);
Printf("runProof: %s: setting cache size to %lld", act.Data(), cachesz);
}
} else {
// Use defaults
proof->DeleteParameters("PROOF_UseTreeCache");
proof->DeleteParameters("PROOF_CacheSize");
}
// Enable submergers, if required
if (aSubMg >= 0) {
proof->SetParameter("PROOF_UseMergers", aSubMg);
if (aSubMg > 0) {
Printf("runProof: %s: enabling merging via %d sub-mergers", act.Data(), aSubMg);
} else {
Printf("runProof: %s: enabling merging via sub-mergers (optimal number)", act.Data());
}
} else {
proof->DeleteParameters("PROOF_UseMergers");
}
// The performance tree
if (makePerfTree) {
proof->SetParameter("PROOF_StatsHist", "");
proof->SetParameter("PROOF_StatsTrace", "");
proof->SetParameter("PROOF_SlaveStatsTrace", "");
}
// Additional inputs from the argument 'ins'
if (ins && ins->GetSize() > 0) {
TObject *oin = 0;
TIter nxo(ins);
while ((oin = nxo())) { proof->AddInput(oin); }
}
// Full lits of inputs so far
proof->GetInputList()->Print();
// Action
if (act == "simple") {
// ProofSimple is an example of non-data driven analysis; it
// creates and fills with random numbers a given number of histos
if (first > 0)
// Meaningless for this tutorial
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
// Default 10000 events
nevt = (nevt < 0) ? 100000 : nevt;
// Find out the number of histograms
TString aNhist, aNhist3;
while (args.Tokenize(tok, from, " ")) {
// Number of histos
if (tok.BeginsWith("nhist=")) {
aNhist = tok;
aNhist.ReplaceAll("nhist=","");
if (!aNhist.IsDigit()) {
Printf("runProof: error parsing the 'nhist=' option (%s) - ignoring", tok.Data());
aNhist = "";
}
} else if (tok.BeginsWith("nhist3=")) {
aNhist3 = tok;
aNhist3.ReplaceAll("nhist3=","");
if (!aNhist3.IsDigit()) {
Printf("runProof: error parsing the 'nhist3=' option (%s) - ignoring", tok.Data());
aNhist3 = "";
}
}
}
Int_t nhist = (aNhist.IsNull()) ? 100 : aNhist.Atoi();
Int_t nhist3 = (aNhist3.IsNull()) ? -1 : aNhist3.Atoi();
Printf("\nrunProof: running \"simple\" with nhist= %d, nhist3=%d and nevt= %lld\n", nhist, nhist3, nevt);
// The number of histograms is added as parameter in the input list
proof->SetParameter("ProofSimple_NHist", (Long_t)nhist);
// The number of histograms is added as parameter in the input list
if (nhist3 > 0) proof->SetParameter("ProofSimple_NHist3", (Long_t)nhist3);
// The selector string
sel.Form("%s/proof/ProofSimple.C%s", tutorials.Data(), aMode.Data());
//
// Run it for nevt times
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
proof->Process(sel.Data(), nevt, xopt);
} else if (act == "h1") {
// This is the famous 'h1' example analysis run on Proof reading the
// data from the ROOT http server.
// Create the chain
TChain *chain = new TChain("h42");
chain->Add(TString::Format("%s/dstarmb.root", aH1Src.Data()));
chain->Add(TString::Format("%s/dstarp1a.root", aH1Src.Data()));
chain->Add(TString::Format("%s/dstarp1b.root", aH1Src.Data()));
chain->Add(TString::Format("%s/dstarp2.root", aH1Src.Data()));
chain->ls();
// We run on Proof
chain->SetProof();
// Set entrylist, if required
if (useList) {
TString eln("elist"), elfn("elist.root");
if (gSystem->AccessPathName(elfn)) {
Printf("\nrunProof: asked to use an entry list but '%s' not found or not readable", elfn.Data());
Printf("\nrunProof: did you forget to run with 'fillList=%s'?\n", elfn.Data());
} else {
TFile f(elfn);
if (!(f.IsZombie())) {
TEntryList *elist = (TEntryList *)f.Get(eln);
if (elist) {
elist->SetDirectory(0); //otherwise the file destructor will delete elist
chain->SetEntryList(elist);
} else {
Printf("\nrunProof: could not find entry-list '%s' in file '%s': ignoring",
eln.Data(), elfn.Data());
}
} else {
Printf("\nrunProof: requested entry-list file '%s' not existing (or not readable):"
" ignoring", elfn.Data());
}
}
}
// The selector
sel.Form("%s/tree/h1analysis.C%s", tutorials.Data(), aMode.Data());
// Run it
Printf("\nrunProof: running \"h1\"\n");
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
chain->Process(sel.Data(),xopt,nevt,first);
// Cleanup the input list
gProof->ClearInputData("elist.root");
TObject *o = 0;
while ((o = nxi())) {
if (!strncmp(o->GetName(), "elist", 5)) {
delete o;
}
}
} else if (act == "pythia8") {
if (first > 0)
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
TString path(Form("%s/Index.xml", pythia8data));
if (gSystem->AccessPathName(path)) {
Printf("runProof: pythia8: PYTHIA8DATA directory (%s) must"
" contain the Index.xml file !", pythia8data);
return;
}
TString pythia8par = TString::Format("%s/proof/pythia8.par", tutorials.Data());
if (gSystem->AccessPathName(pythia8par.Data())) {
Printf("runProof: pythia8: par file not found (tried %s)", pythia8par.Data());
return;
}
proof->UploadPackage(pythia8par);
proof->EnablePackage("pythia8");
// Show enabled packages
proof->ShowEnabledPackages();
Printf("runProof: pythia8: check settings:");
proof->Exec(".!echo hostname = `hostname`; echo \"ls pythia8:\"; ls pythia8");
// Loading libraries needed
if (gSystem->Load("libEG.so") < 0) {
Printf("runProof: pythia8: libEG not found \n");
return;
}
if (gSystem->Load("libEGPythia8.so") < 0) {
Printf("runProof: pythia8: libEGPythia8 not found \n");
return;
}
// Setting the default number of events, if needed
nevt = (nevt < 0) ? 100 : nevt;
Printf("\nrunProof: running \"Pythia01\" nevt= %lld\n", nevt);
// The selector string
sel.Form("%s/proof/ProofPythia.C%s", tutorials.Data(), aMode.Data());
// Run it for nevt times
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
proof->Process(sel.Data(), nevt, xopt);
} else if (act == "event") {
if (first > 0)
// Meaningless for this tutorial
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
TString eventpar = TString::Format("%s/proof/event.par", tutorials.Data());
if (gSystem->AccessPathName(eventpar.Data())) {
Printf("runProof: event: par file not found (tried %s)", eventpar.Data());
return;
}
proof->UploadPackage(eventpar);
proof->EnablePackage("event");
Printf("Enabled packages...\n");
proof->ShowEnabledPackages();
// Setting the default number of events, if needed
nevt = (nevt < 0) ? 100 : nevt;
Printf("\nrunProof: running \"event\" nevt= %lld\n", nevt);
// The selector string
sel.Form("%s/proof/ProofEvent.C%s", tutorials.Data(), aMode.Data());
// Run it for nevt times
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
proof->Process(sel.Data(), nevt, xopt);
} else if (act == "eventproc") {
TString eventpar = TString::Format("%s/proof/event.par", tutorials.Data());
gSystem->ExpandPathName(eventpar);
if (gSystem->AccessPathName(eventpar.Data())) {
Printf("runProof: eventproc: par file not found (tried %s)", eventpar.Data());
return;
}
proof->UploadPackage(eventpar);
proof->EnablePackage("event");
Printf("Enabled packages...\n");
proof->ShowEnabledPackages();
// Load ProcFileElements (to check processed ranges)
TString pfelem = TString::Format("%s/proof/ProcFileElements.C", tutorials.Data());
if (gSystem->AccessPathName(pfelem.Data())) {
Printf("runProof: eventproc: ProcFileElements.C not found (tried %s)", pfelem.Data());
return;
}
pfelem += aMode;
// Add include to test trasmission
pfelem += TString::Format(",%s/proof/EmptyInclude.h", tutorials.Data());
proof->Load(pfelem);
// Extract the number of files to process, data source and
// other parameters controlling the run ...
Bool_t uneven = kFALSE;
TString aFiles, aDataSrc("http://root.cern.ch/files/data"), aPartitions;
proof->SetParameter("ProofEventProc_Read", "optimized");
while (args.Tokenize(tok, from, " ")) {
// Number of events
if (tok.BeginsWith("files=")) {
aFiles = tok;
aFiles.ReplaceAll("files=","");
if (!aFiles.IsDigit()) {
Printf("runProof: error parsing the 'files=' option (%s) - ignoring", tok.Data());
aFiles = "";
}
} else if (tok.BeginsWith("datasrc=")) {
tok.ReplaceAll("datasrc=","");
if (tok.IsDigit()) {
Printf("runProof: error parsing the 'datasrc=' option (%s) - ignoring", tok.Data());
} else {
aDataSrc = tok;
Printf("runProof: reading files from: %s", aDataSrc.Data());
}
} else if (tok == "readall") {
proof->SetParameter("ProofEventProc_Read", "readall");
Printf("runProof: eventproc: reading the full event");
} else if (tok == "uneven") {
uneven = kTRUE;
} else if (tok.BeginsWith("partitions=")) {
tok.ReplaceAll("partitions=","");
if (tok.IsDigit()) {
Printf("runProof: error parsing the 'partitions=' option (%s) - ignoring", tok.Data());
} else {
aPartitions = tok;
Printf("runProof: partitions: %s included in packetizer operations", aPartitions.Data());
}
}
}
Int_t nFiles = (aFiles.IsNull()) ? 10 : aFiles.Atoi();
Printf("runProof: found aFiles: '%s', nFiles: %d", aFiles.Data(), nFiles);
if (nFiles > 50) {
Printf("runProof: max number of files is 50 - resizing request");
nFiles = 50;
}
// We create the chain now
TChain *c = new TChain("EventTree");
if (gSystem->GetPathInfo(aDataSrc, fst) == 0 && R_ISREG(fst.fMode) &&
// It is a local file, we get the TFileCollection and we inject it into the chain
TFileCollection *fc = new TFileCollection("", "", aDataSrc, nFiles);
delete fc;
} else {
// Tokenize the source: if more than 1 we rotate the assignment. More sources can be specified
// separating them by a '|'
TObjArray *dsrcs = aDataSrc.Tokenize("|");
Int_t nds = dsrcs->GetEntries();
// Fill the chain
Int_t i = 1, k = 0;
TString fn;
for (i = 1; i <= nFiles; i++) {
k = (i - 1) % nds;
TObjString *os = (TObjString *) (*dsrcs)[k];
if (os) {
fn.Form("%s/event_%d.root", os->GetName(), i);
if (uneven) {
if ((i - 1)%5 == 0)
c->AddFile(fn.Data(), 50000);
else
c->AddFile(fn.Data(), 5000);
} else {
c->AddFile(fn.Data());
}
}
}
dsrcs->SetOwner();
delete dsrcs;
}
// Show the chain
c->ls();
c->SetProof();
// Only validate the files really needed for the analysis
proof->SetParameter("PROOF_ValidateByFile", 1);
// Send over the partition information, if any
if (!aPartitions.IsNull()) {
aPartitions.ReplaceAll("|", ",");
proof->SetParameter("PROOF_PacketizerPartitions", aPartitions);
}
// The selector
sel.Form("%s/proof/ProofEventProc.C%s", tutorials.Data(), aMode.Data());
// Run it
Printf("\nrunProof: running \"eventproc\"\n");
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
c->Process(sel.Data(), xopt, nevt, first);
} else if (act == "ntuple") {
// ProofNtuple is an example of non-data driven analysis; it
// creates and fills a disk resident ntuple with automatic file merging
if (first > 0)
// Meaningless for this tutorial
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
// Set the default number of events, if needed
nevt = (nevt < 0) ? 1000 : nevt;
Printf("\nrunProof: running \"ntuple\" with nevt= %lld\n", nevt);
// Which randoms to use
Bool_t usentprndm = kFALSE;
while (args.Tokenize(tok, from, " ")) {
if (tok == "inputrndm") {
usentprndm = kTRUE;
break;
}
}
if (usentprndm) Printf("runProof: taking randoms from input ntuple\n");
// Output file
TString fout(aOutFile);
if (fout.IsNull()) {
fout.Form("%s/ProofNtuple.root", gSystem->WorkingDirectory());
// Cleanup any existing instance of the output file
gSystem->Unlink(fout);
if (!isProofLocal) {
// Setup a local basic xrootd to receive the file
Bool_t xrdok = kFALSE;
Int_t port = 9000;
while (port < 9010) {
if (checkXrootdAt(port) != 1) {
if (startXrootdAt(port, gSystem->WorkingDirectory(), kTRUE) == 0) {
xrdok = kTRUE;
break;
}
}
port++;
}
if (!xrdok) {
Printf("runProof: could not start basic xrootd on ports 9000-9009 - cannot continue");
return;
}
fout.Insert(0, TString::Format("root://%s:%d/", TUrl(gSystem->HostName()).GetHostFQDN(), port));
// Make a copy of the files on the master before merging
proof->AddInput(new TNamed("PROOF_OUTPUTFILE_LOCATION", "LOCAL"));
}
}
proof->AddInput(new TNamed("PROOF_OUTPUTFILE", fout.Data()));
// If using the 'NtpRndm' for a fixed values of randoms, send over the file
if (usentprndm) {
// The file with 'NtpRndm'
TString fnr = TString::Format("%s/proof/ntprndm.root", tutorials.Data());
// Set as input data
proof->SetInputDataFile(fnr);
// Set the related parameter
proof->SetParameter("PROOF_USE_NTP_RNDM","yes");
// Notify
Printf("runProof: taking randoms from '%s'", fnr.Data());
}
// The selector string
sel.Form("%s/proof/ProofNtuple.C%s", tutorials.Data(), aMode.Data());
// Run it for nevt times
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
Printf("runProof: selector file '%s', options: '%s'", sel.Data(), xopt.Data());
proof->Process(sel.Data(), nevt, xopt);
// Reset input variables
if (usentprndm) {
proof->DeleteParameters("PROOF_USE_NTP_RNDM");
proof->SetInputDataFile(0);
}
} else if (act == "dataset") {
// This is an example of analysis creating data files on each node which are
// automatically registered as dataset; the newly created dataset is used to create
// the final plots. The data are of the same type as for the 'ntuple' example.
// Selector used: ProofNtuple
if (first > 0)
// Meaningless for this tutorial
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
// Set the default number of events, if needed
nevt = (nevt < 0) ? 1000000 : nevt;
Printf("\nrunProof: running \"dataset\" with nevt= %lld\n", nevt);
// Ask for registration of the dataset (the default is the the TFileCollection is return
// without registration; the name of the TFileCollection is the name of the dataset
proof->SetParameter("SimpleNtuple.root","testNtuple");
// Do not plot the ntuple at this level
proof->SetParameter("PROOF_NTUPLE_DONT_PLOT", "");
// The selector string
sel.Form("%s/proof/ProofNtuple.C%s", tutorials.Data(), aMode.Data());
//
// Run it for nevt times
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
proof->Process(sel.Data(), nevt, xopt);
// The TFileCollection must be in the output
if (proof->GetOutputList()->FindObject("testNtuple")) {
// Plot the ntuple via PROOF (example of drawing PROOF actions)
plotNtuple(proof, "testNtuple", "proof ntuple from dataset");
} else {
Printf("runProof: dataset 'testNtuple' not found in the output list");
}
// Do not plot the ntuple at this level
proof->DeleteParameters("PROOF_NTUPLE_DONT_PLOT");
proof->DeleteParameters("SimpleNtuple.root");
} else if (act == "friends") {
// This is an example of analysis creating two data files on each node (the main tree
// and its friend) which are then processed as 'friends' to create the final plots.
// Selector used: ProofFriends, ProofAux
if (first > 0)
// Meaningless for this tutorial
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
// Find out whether to use the same file or separate files
Bool_t sameFile = kFALSE;
while (args.Tokenize(tok, from, " ")) {
// Number of histos
if (tok == "samefile") {
sameFile = kTRUE;
break;
}
}
// File generation: we use TPacketizerFile in here to create two files per node
TList *wrks = proof->GetListOfSlaveInfos();
if (!wrks) {
Printf("runProof: could not get the list of information about the workers");
return;
}
// Create the map
TString fntree;
TMap *files = new TMap;
files->SetName("PROOF_FilesToProcess");
TIter nxwi(wrks);
TSlaveInfo *wi = 0;
while ((wi = (TSlaveInfo *) nxwi())) {
fntree.Form("tree_%s.root", wi->GetOrdinal());
THashList *wrklist = (THashList *) files->GetValue(wi->GetName());
if (!wrklist) {
wrklist = new THashList;
wrklist->SetName(wi->GetName());
files->Add(new TObjString(wi->GetName()), wrklist);
}
wrklist->Add(new TObjString(fntree));
}
// Generate the files
proof->AddInput(files);
if (sameFile) {
Printf("runProof: friend tree stored in the same file as the main tree");
proof->SetParameter("ProofAux_Action", "GenerateTreesSameFile");
} else {
proof->SetParameter("ProofAux_Action", "GenerateTrees");
}
// Default 1000 events
nevt = (nevt < 0) ? 10000 : nevt;
proof->SetParameter("ProofAux_NEvents", (Long64_t)nevt);
// Special Packetizer
proof->SetParameter("PROOF_Packetizer", "TPacketizerFile");
// Now process
sel.Form("%s/proof/ProofAux.C%s", tutorials.Data(), aMode.Data());
proof->Process(sel.Data(), 1);
// Remove the packetizer specifications
proof->DeleteParameters("PROOF_Packetizer");
// Print the lists and create the TDSet objects
TDSet *dset = new TDSet("Tmain", "Tmain");
TDSet *dsetf = new TDSet("Tfrnd", "Tfrnd");
if (proof->GetOutputList()) {
TIter nxo(proof->GetOutputList());
TObject *o = 0;
TObjString *os = 0;
while ((o = nxo())) {
TList *l = dynamic_cast<TList *> (o);
if (l && !strncmp(l->GetName(), "MainList-", 9)) {
TIter nxf(l);
while ((os = (TObjString *) nxf()))
dset->Add(os->GetName());
}
}
nxo.Reset();
while ((o = nxo())) {
TList *l = dynamic_cast<TList *> (o);
if (l && !strncmp(l->GetName(), "FriendList-", 11)) {
TIter nxf(l);
while ((os = (TObjString *) nxf()))
dsetf->Add(os->GetName());
}
}
}
// Process with friends
dset->AddFriend(dsetf, "friend");
sel.Form("%s/proof/ProofFriends.C%s", tutorials.Data(), aMode.Data());
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
dset->Process(sel, xopt);
// Clear the files created by this run
} else if (act == "simplefile") {
// ProofSimpleFile is an example of non-data driven analysis with merging
// via file and objcets saved in different directories; it creates and
// fills with random numbers two sets of a given number of histos
if (first > 0)
// Meaningless for this tutorial
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
// Default 100000 events
nevt = (nevt < 0) ? 1000000 : nevt;
// Find out the number of histograms
TString aNhist;
while (args.Tokenize(tok, from, " ")) {
// Number of histos
if (tok.BeginsWith("nhist=")) {
aNhist = tok;
aNhist.ReplaceAll("nhist=","");
if (!aNhist.IsDigit()) {
Printf("runProof: error parsing the 'nhist=' option (%s) - ignoring", tok.Data());
aNhist = "";
}
}
}
Int_t nhist = (aNhist.IsNull()) ? 16 : aNhist.Atoi();
Printf("\nrunProof: running \"simplefile\" with nhist= %d and nevt= %lld\n", nhist, nevt);
// The number of histograms is added as parameter in the input list
proof->SetParameter("ProofSimple_NHist", (Long_t)nhist);
// Output file
TString fout(aOutFile);
if (fout.IsNull()) {
fout.Form("%s/SimpleFile.root", gSystem->WorkingDirectory());
// Cleanup any existing instance of the output file
gSystem->Unlink(fout);
if (!isProofLocal) {
// Setup a local basic xrootd to receive the file
Bool_t xrdok = kFALSE;
Int_t port = 9000;
while (port < 9010) {
if (checkXrootdAt(port) != 1) {
if (startXrootdAt(port, gSystem->WorkingDirectory(), kTRUE) == 0) {
xrdok = kTRUE;
break;
}
}
port++;
}
if (!xrdok) {
Printf("runProof: could not start basic xrootd on ports 9000-9009 - cannot continue");
return;
}
fout.Insert(0, TString::Format("root://%s:%d/", TUrl(gSystem->HostName()).GetHostFQDN(), port));
// Make a copy of the files on the master before merging
proof->AddInput(new TNamed("PROOF_OUTPUTFILE_LOCATION", "LOCAL"));
}
}
proof->AddInput(new TNamed("PROOF_OUTPUTFILE", fout.Data()));
// The selector string
sel.Form("%s/proof/ProofSimpleFile.C%s", tutorials.Data(), aMode.Data());
//
// Run it for nevt times
TString xopt = aFeedback; if (!opt.IsNull()) xopt += TString::Format(" %s", opt.Data());
proof->Process(sel.Data(), nevt, xopt);
} else if (act == "stdvec") {
// This is an example of runnign a TSelector using standard vectors
// Selector used: ProofStdVect
if (first > 0)
// Meaningless for this tutorial
Printf("runProof: %s: warning concept of 'first' meaningless for this tutorial"
" - ignored", act.Data());
// Set the default number of events, if needed
nevt = (nevt < 0) ? 50000 * proof->GetParallel() : nevt;
Printf("\nrunProof: running \"stdvec\" with nevt= %lld\n", nevt);
// The selector string
sel.Form("%s/proof/ProofStdVect.C%s", tutorials.Data(), aMode.Data());
TString xopt;
// Create the dataset 'TestStdVect' with 'nevt' events
xopt.Form("%s %s create", aFeedback.Data(), opt.Data());
proof->Process(sel.Data(), nevt, xopt);
// The dataset must have been registered
if (proof->ExistsDataSet("TestStdVect")) {
// Use dataset 'TestStdVect'
xopt.Form("%s %s", aFeedback.Data(), opt.Data());
proof->Process("TestStdVect", sel.Data(), xopt);
} else {
Printf("runProof: dataset 'TestStdVect' not available!");
}
} else {
// Do not know what to run
Printf("runProof: unknown tutorial: %s", what);
}
// Save the performance tree
if (makePerfTree) {
SavePerfTree(proof, aPerfTree.Data());
// Cleanup parameters
gProof->DeleteParameters("PROOF_StatsHist");
gProof->DeleteParameters("PROOF_StatsTrace");
gProof->DeleteParameters("PROOF_SlaveStatsTrace");
}
}
//_______________________________________________________________________________________
void plotNtuple(TProof *p, const char *ds, const char *ntptitle)
{
// Make some plots from the ntuple 'ntp' via PROOF
//
// Create a canvas, with 2 pads
//
TCanvas *c1 = new TCanvas(Form("cv-%s", ds), ntptitle,800,10,700,780);
c1->Divide(1,2);
TPad *pad1 = (TPad *) c1->GetPad(1);
TPad *pad2 = (TPad *) c1->GetPad(2);
//
// Display a function of one ntuple column imposing a condition
// on another column.
pad1->cd();
pad1->SetGrid();
pad1->SetLogy();
pad1->GetFrame()->SetFillColor(15);
p->SetParameter("PROOF_LineColor", (Int_t)1);
p->SetParameter("PROOF_FillStyle", (Int_t)1001);
p->SetParameter("PROOF_FillColor", (Int_t)45);
p->DrawSelect(ds, "3*px+2","px**2+py**2>1");
p->SetParameter("PROOF_FillColor", (Int_t)38);
p->DrawSelect(ds, "2*px+2","pz>2","same");
p->SetParameter("PROOF_FillColor", (Int_t)5);
p->DrawSelect(ds, "1.3*px+2","(px^2+py^2>4) && py>0","same");
pad1->RedrawAxis();
//
// Display a 3-D scatter plot of 3 columns. Superimpose a different selection.
pad2->cd();
p->DrawSelect(ds, "pz:py:px","(pz<10 && pz>6)+(pz<4 && pz>3)");
p->SetParameter("PROOF_MarkerColor", (Int_t)4);
p->DrawSelect(ds, "pz:py:px","pz<6 && pz>4","same");
p->SetParameter("PROOF_MarkerColor", (Int_t)5);
p->DrawSelect(ds, "pz:py:px","pz<4 && pz>3","same");
TPaveText *l2 = new TPaveText(0.,0.6,0.9,0.95);
l2->SetFillColor(42);
l2->SetTextAlign(12);
l2->AddText("You can interactively rotate this view in 2 ways:");
l2->AddText(" - With the RotateCube in clicking in this pad");
l2->AddText(" - Selecting View with x3d in the View menu");
l2->Draw();
// Final update
c1->cd();
c1->Update();
// Clear parameters used for the plots
p->DeleteParameters("PROOF_*Color");
p->DeleteParameters("PROOF_*Style");
}
//______________________________________________________________________________
void SavePerfTree(TProof *proof, const char *fn)
{
// Save PROOF timing information from TPerfStats to file 'fn'
if (!proof) {
Printf("PROOF must be run to save output performance information");;
return;
}
if (!proof->GetOutputList() || proof->GetOutputList()->GetSize() <= 0) {
Printf("PROOF outputlist undefined or empty");;
return;
}
TFile f(fn, "RECREATE");
if (f.IsZombie()) {
Printf("ERROR: could not open file '%s' for writing", fn);;
} else {
f.cd();
TIter nxo(proof->GetOutputList());
TObject* obj = 0;
while ((obj = nxo())) {
TString objname(obj->GetName());
if (objname.BeginsWith("PROOF_")) {
// Must list the objects since other PROOF_ objects exist
// besides timing objects
if (objname == "PROOF_PerfStats" ||
objname == "PROOF_PacketsHist" ||
objname == "PROOF_EventsHist" ||
objname == "PROOF_NodeHist" ||
objname == "PROOF_LatencyHist" ||
objname == "PROOF_ProcTimeHist" ||
objname == "PROOF_CpuTimeHist")
obj->Write();
}
}
f.Close();
}
}
Author
Gerardo Ganis

Definition in file runProof.C.