runProof.C

Go to the documentation of this file.
00001 //
00002 // Macro to run examples of analysis on PROOF, corresponding to the TSelector
00003 // implementations found under <ROOTSYS>/tutorials/proof .
00004 // This macro uses an existing PROOF session or starts one at the indicated URL.
00005 // In the case non existing PROOF session is found and no URL is given, the
00006 // macro tries to start a local PROOF session.
00007 //
00008 // To run the macro:
00009 //
00010 //   root[] .L proof/runProof.C+
00011 //   root[] runProof("<analysis>")
00012 //
00013 //   Currently available analysis are (to see how all this really works check
00014 //   the scope for the specified option inside the macro):
00015 //
00016 //   1. "simple"
00017 //
00018 //      Selector: ProofSimple.h.C
00019 //
00020 //      root[] runProof("simple")
00021 //
00022 //      This will create a local PROOF session and run an analysis filling
00023 //      100 histos with 100000 gaussian random numbers, and displaying them
00024 //      in a canvas with 100 pads (10x10).
00025 //      The number of histograms can be passed as 'arguments' to 'simple',
00026 //      e.g. to fill 16 histos with 1000000 entries use
00027 //
00028 //      root[] runProof("simple(nevt=1000000,nhist=16)")
00029 //
00030 //   2. "h1"
00031 //
00032 //      Selector: tutorials/tree/h1analysis.h.C
00033 //
00034 //      root[] runProof("h1")
00035 //
00036 //      This runs the 'famous' H1 analysis from $ROOTSYS/tree/h1analysis.C.h.
00037 //      By default the data are read from the HTTP server at root.cern.ch,
00038 //      the data source can be changed via the argument 'h1src', e.g.
00039 //
00040 //      root[] runProof("h1,h1src=/data/h1")
00041 //
00042 //      (the directory specified must contain the 4 H1 files).
00043 //
00044 //      The 'h1' example is also used to show how to use entry-lists in PROOF.
00045 //      To fill the list for the events used for the final plots add the option
00046 //      'fillList':
00047 //
00048 //      root[] runProof("h1,fillList")
00049 //
00050 //      To use the list previously created for the events used for the 
00051 //      final plots add the option 'useList':
00052 //
00053 //      root[] runProof("h1,useList")
00054 //
00055 //  3. "event"
00056 //
00057 //      Selector: ProofEvent.h,.C
00058 //
00059 //      This is an example of using PROOF par files.
00060 //      It runs event generation and simple analysis based on the 'Event'
00061 //      class found under test.
00062 //
00063 //      root[] runProof("event")
00064 //
00065 //  4. "eventproc"
00066 //
00067 //      Selector: ProofEventProc.h.C
00068 //
00069 //      This is an example of using PROOF par files and process 'event'
00070 //      data from the ROOT HTTP server. It runs the ProofEventProc selector
00071 //      which is derived from the EventTree_Proc one found under
00072 //      test/ProofBench. The following specific arguments are available:
00073 //      - 'readall'  to read the whole event, by default only the branches
00074 //                   needed by the analysis are read (read 25% more bytes)
00075 //      - 'datasrc=<dir-with-files>' to read the files from another server,
00076 //                   the files must be named 'event_<num>.root' where <num>=1,2,...
00077 //        or
00078 //      - 'datasrc=<file-with-files>' to take the file content from a text file,
00079 //                   specified one file per line; usefull when testing differences
00080 //                   between several sources and distributions
00081 //      - 'files=N'  to change the number of files to be analysed (default
00082 //                   is 10, max is 50 for the HTTP server).
00083 //      - 'uneven'   to process uneven entries from files following the scheme
00084 //                   {50000,5000,5000,5000,5000} and so on
00085 //
00086 //      root[] runProof("eventproc")
00087 //
00088 //  5. "pythia8"
00089 //
00090 //      Selector: ProofPythia.h.C
00091 //
00092 //      This runs Pythia8 generation based on main03.cc example in Pythia 8.1 
00093 //
00094 //      To run this analysis ROOT must be configured with pythia8.
00095 //
00096 //      Note that before executing this analysis, the env variable PYTHIA8
00097 //      must point to the pythia8100 (or newer) directory, in particular,
00098 //      $PYTHIA8/xmldoc must contain the file Index.xml. The tutorial assumes
00099 //      that the Pythia8 directory is the same on all machines, i.e. local
00100 //      and worker ones.
00101 //
00102 //      root[] runProof("pythia8")
00103 //
00104 //  6. "ntuple"
00105 //
00106 //      Selector: ProofNtuple.h.C
00107 //
00108 //      This is an example of final merging via files created on the workers,
00109 //      using TProofOutputFile. The final file is called ProofNtuple.root
00110 //      and it is created in the directory where the tutorial is run. If
00111 //      the PROOF cluster is remote, the file is received by a local xrootd
00112 //      daemon started for the purpose. Because of this, this example can be
00113 //      run only on unix clients.
00114 //
00115 //      root[] runProof("ntuple")
00116 //
00117 //  7. "dataset"
00118 //
00119 //      Selector: ProofNtuple.h.C
00120 //
00121 //      This is an example of automatic creation of a dataset from files
00122 //      created on the workers, using TProofOutputFile. The dataset is
00123 //      called testNtuple and it is automatically registered and verified.
00124 //      The files contain the same ntuple as in previous example/tutorial 6
00125 //      (the same selector ProofNTuple is used with a slightly different
00126 //      configuration). The dataset is then used to produce the same plot
00127 //      as in 5 but using the DrawSelect methods of PROOF, which also show
00128 //      how to set style, color and other drawing attributes in PROOF.
00129 //      Depending on the relative worker perforance, some of the produced
00130 //      files may result in having no entries. If this happens, the file
00131 //      will be added to the missing (skipped) file list. Increasing the
00132 //      number of events (via nevt=...) typically solves this issue.
00133 //
00134 //      root[] runProof("dataset")
00135 //
00136 //  8. "friends"
00137 //
00138 //      Selectors: ProofFriends.h(.C), ProofAux.h(.C)
00139 //
00140 //      This is an example of TTree friend processing in PROOF. It also shows
00141 //      how to use the TPacketizerFile to steer creation of files.
00142 //
00143 //      root[] runProof("friends")
00144 //
00145 //   General arguments
00146 //   -----------------
00147 //
00148 //   The following arguments are valid for all examples (the ones specific
00149 //   to each tutorial have been explained above)
00150 //
00151 //   0. ACLiC mode
00152 //      By default all processing is done with ACLiC mode '+', i.e. compile
00153 //      if changed. However, this may lead to problems if the available
00154 //      selector libs were compiled in previous sessions with a different
00155 //      set of loaded libraries (this is a general problem in ROOT). When
00156 //      this happens the best solution is to force recompilation (ACLiC
00157 //      mode '++'). To do this just add one or more '+' to the name of the
00158 //      tutorial, e.g. runProof("simple++")
00159 //
00160 //   1. debug=[what:]level
00161 //
00162 //      Controls verbosity; 'level' is an integer number and the optional string
00163 //      'what' one or more of the enum names in TProofDebug.h .
00164 //      e.g. runProof("eventproc(debug=kPacketizer|kCollect:2)") runs 'eventproc' enabling
00165 //           all printouts matching TProofDebug::kPacketizer and having level
00166 //           equal or larger than 2 .
00167 //
00168 //   2. nevt=N
00169 //
00170 //      Set the number of entries to N
00171 //      e.g. runProof("simple(nevt=1000000000)") runs simple with 1000000000
00172 //
00173 //   3. asyn
00174 //
00175 //      Run in non blocking mode
00176 //      e.g. root[] runProof("h1(asyn)")
00177 //
00178 //   4. nwrk=N
00179 //
00180 //      Set the number of active workers to N, usefull to test performance
00181 //      on a remote cluster where control about the number of workers is
00182 //      not possible, e.g. runProof("event(nwrk=2)") runs 'event' with
00183 //      2 workers.
00184 //
00185 //   5. punzip
00186 //
00187 //      Use parallel unzipping in reading files where relevant
00188 //      e.g. root[] runProof("eventproc(punzip)")
00189 //
00190 //   6. cache=<bytes> (or <kbytes>K or <mbytes>M) 
00191 //
00192 //      Change the size of the tree cache; 0 or <0 disables the cache,
00193 //      value cane be in bytes (no suffix), kilobytes (suffix 'K') or
00194 //      megabytes (suffix 'M'), e.g. root[] runProof("eventproc(cache=0)") 
00195 //
00196 //   7. submergers[=S]
00197 //
00198 //      Enabling merging via S submergers or the optimal number if S is
00199 //      not specified, e.g. root[] runProof("simple(hist=1000,submergers)") 
00200 //
00201 //   8. rateest=average
00202 //
00203 //      Enable processed entries estimation for constant progress reporting based on
00204 //      the measured average. This may screw up the progress bar in some cases, which
00205 //      is the reason why it is not on by default .
00206 //      e.g. root[] runProof("eventproc(rateest=average)")
00207 //
00208 //   In all cases, to run on a remote PROOF cluster, the master URL must
00209 //   be passed as second argument; e.g.
00210 //
00211 //      root[] runProof("simple","master.do.main")
00212 //
00213 //   In the case of local running it is possible to specify the number of
00214 //   workers to start as third argument (the default is the number of cores
00215 //   of the machine), e.g.
00216 //
00217 //      root[] runProof("simple",0,4)
00218 //
00219 //   will start 4 workers. Note that the real number of workers is changed
00220 //   only the first time you call runProof into a ROOT session. Following
00221 //   calls can reduce the number of active workers, but not increase it.
00222 //   For example, in the same session of the call above starting 4 workers,
00223 //   this
00224 //
00225 //   root[] runProof("simple",0,8)
00226 //
00227 //   will still use 4 workers, while this
00228 //
00229 //   root[] runProof("simple",0,2)
00230 //
00231 //   will disable 2 workers and use the other 2.
00232 //
00233 
00234 
00235 #include "TCanvas.h"
00236 #include "TChain.h"
00237 #include "TDrawFeedback.h"
00238 #include "TDSet.h"
00239 #include "TEnv.h"
00240 #include "TEntryList.h"
00241 #include "TFile.h"
00242 #include "TFileCollection.h"
00243 #include "TFrame.h"
00244 #include "THashList.h"
00245 #include "TList.h"
00246 #include "TPad.h"
00247 #include "TPaveText.h"
00248 #include "TProof.h"
00249 #include "TProofDebug.h"
00250 #include "TString.h"
00251 
00252 #include "getProof.C"
00253 void plotNtuple(TProof *p, const char *ds, const char *ntptitle);
00254 int getDebugEnum(const char *what);
00255 
00256 TDrawFeedback *fb = 0;
00257 
00258 // Variable used to locate the Pythia8 directory for the Pythia8 example
00259 const char *pythia8dir = 0;
00260 const char *pythia8data = 0;
00261 
00262 void runProof(const char *what = "simple",
00263               const char *url = "proof://localhost:11093",
00264               Int_t nwrks = -1)
00265 {
00266 #ifdef __CINT__
00267    Printf("runProof: this script can only be executed via ACliC:");
00268    Printf("runProof:      root [] .x <path>/runProof.C+");
00269    Printf("runProof: or   root [] .L <path>/runProof.C+");
00270    Printf("runProof:      root [] runProof(...)");
00271    return;
00272 #endif
00273    gEnv->SetValue("Proof.StatsHist",1);
00274 
00275    // Temp dir for PROOF tutorials
00276    // Force "/tmp/<user>" whenever possible to avoid length problems on MacOsX
00277    TString tmpdir("/tmp");
00278    if (gSystem->AccessPathName(tmpdir, kWritePermission)) tmpdir = gSystem->TempDirectory();
00279    TString us;
00280    UserGroup_t *ug = gSystem->GetUserInfo(gSystem->GetUid());
00281    if (!ug) {
00282       Printf("runProof: could not get user info");
00283       return;
00284    }
00285    us.Form("/%s", ug->fUser.Data());
00286    if (!tmpdir.EndsWith(us.Data())) tmpdir += us;
00287    gSystem->mkdir(tmpdir.Data(), kTRUE);
00288    if (gSystem->AccessPathName(tmpdir, kWritePermission)) {
00289       Printf("runProof: unable to get a writable tutorial directory (tried: %s)"
00290              " - cannot continue", tmpdir.Data());
00291       return;
00292    }
00293    TString tutdir = Form("%s/.proof-tutorial", tmpdir.Data());
00294    if (gSystem->AccessPathName(tutdir)) {
00295       Printf("runProof: creating the temporary directory"
00296                 " for the tutorial (%s) ... ", tutdir.Data());
00297       if (gSystem->mkdir(tutdir, kTRUE) != 0) {
00298          Printf("runProof: could not assert / create the temporary directory"
00299                 " for the tutorial (%s)", tutdir.Data());
00300          return;
00301       }
00302    }
00303 
00304    // For the Pythia8 example we need to set some environment variable;
00305    // This must be done BEFORE starting the PROOF session
00306    if (what && !strncmp(what, "pythia8", 7)) {
00307       // We assume that the remote location of Pythia8 is the same as the local one
00308       pythia8dir = gSystem->Getenv("PYTHIA8");
00309       if (!pythia8dir || strlen(pythia8dir) <= 0) {
00310          Printf("runProof: pythia8: environment variable PYTHIA8 undefined:"
00311                   " it must contain the path to pythia81xx root directory (local and remote) !");
00312          return;
00313       }
00314       pythia8data = gSystem->Getenv("PYTHIA8DATA");
00315       if (!pythia8data || strlen(pythia8data) <= 0) {
00316          gSystem->Setenv("PYTHIA8DATA", Form("%s/xmldoc", pythia8dir));
00317          pythia8data = gSystem->Getenv("PYTHIA8DATA");
00318          if (!pythia8data || strlen(pythia8data) <= 0) {
00319             Printf("runProof: pythia8: environment variable PYTHIA8DATA undefined:"
00320                    " it one must contain the path to pythia81xx/xmldoc"
00321                    " subdirectory (local and remote) !");
00322             return;
00323          }
00324       }
00325       TString env = Form("echo export PYTHIA8=%s; export PYTHIA8DATA=%s",
00326                          pythia8dir, pythia8data);
00327       TProof::AddEnvVar("PROOF_INITCMD", env.Data());
00328    }
00329 
00330    // Get the PROOF Session
00331    TProof *proof = getProof(url, nwrks, tutdir.Data(), "ask");
00332    if (!proof) {
00333       Printf("runProof: could not start/attach a PROOF session");
00334       return;
00335    }
00336 
00337    // Determine locality of this session
00338    Bool_t isProofLocal = kFALSE;
00339    TUrl uu(url);
00340    if (!strcmp(uu.GetHost(), "localhost") || proof->IsLite() ||
00341        !strcmp(uu.GetHostFQDN(), TUrl(gSystem->HostName()).GetHostFQDN())) {
00342       isProofLocal = kTRUE;
00343    }
00344 #ifdef WIN32
00345    if (isProofLocal && what && !strcmp(what, "ntuple", 6)) {
00346       // Not support on windows
00347       Printf("runProof: the 'ntuple' example needs to run xrootd to receive the output file, \n"
00348              "          but xrootd is not supported on Windows - cannot continue");
00349       return;
00350    }
00351 #endif
00352 
00353    TString proofsessions(Form("%s/sessions",tutdir.Data()));
00354    // Save tag of the used session
00355    FILE *fs = fopen(proofsessions.Data(), "a");
00356    if (!fs) {
00357       Printf("runProof: could not create files for sessions tags");
00358    } else {
00359       fprintf(fs,"session-%s\n", proof->GetSessionTag());
00360       fclose(fs);
00361    }
00362    if (!proof) {
00363       Printf("runProof: could not start/attach a PROOF session");
00364       return;
00365    }
00366 
00367    // Set the number of workers (may only reduce the number of active workers
00368    // in the session)
00369    if (nwrks > 0)
00370       proof->SetParallel(nwrks);
00371 
00372    // Where is the code to run
00373    char *rootbin = gSystem->Which(gSystem->Getenv("PATH"), "root.exe", kExecutePermission);
00374    if (!rootbin) {
00375       Printf("runProof: root.exe not found: please check the environment!");
00376       return;
00377    }
00378    TString rootsys(gSystem->DirName(rootbin));
00379    rootsys = gSystem->DirName(rootsys);
00380    TString tutorials(Form("%s/tutorials", rootsys.Data()));
00381    delete[] rootbin;
00382 
00383    // Create feedback displayer
00384    if (!fb) {
00385       new TCanvas("PROOF_EventsHist_canvas", "Events per Worker", 100, 600, 600, 400);
00386       fb = new TDrawFeedback(proof);
00387    }
00388    if (!proof->GetFeedbackList() || !proof->GetFeedbackList()->FindObject("PROOF_EventsHist")) {
00389       // Number of events per worker
00390       proof->AddFeedback("PROOF_EventsHist");
00391    }
00392 
00393    // Parse 'what'; it is in the form 'analysis(arg1,arg2,...)'
00394    TString args(what);
00395    args.ReplaceAll("("," "); 
00396    args.ReplaceAll(")"," "); 
00397    args.ReplaceAll(","," "); 
00398    Ssiz_t from = 0;
00399    TString act, tok;
00400    if (!args.Tokenize(act, from, " ")) {
00401       // Cannot continue
00402       Printf("runProof: action not found: check your arguments (%s)", what);
00403       return;
00404    }
00405    // Extract ACLiC mode
00406    TString aMode = "+";
00407    if (act.EndsWith("+")) {
00408       aMode += "+";
00409       while (act.EndsWith("+")) { act.Remove(TString::kTrailing,'+'); }
00410    }
00411    Printf("runProof: %s: ACLiC mode: '%s'", act.Data(), aMode.Data());
00412 
00413    // Parse out number of events and  'asyn' option, used almost by every test
00414    TString aNevt, aNwrk, opt, sel, punzip("off"), aCache, aH1Src("http://root.cern.ch/files/h1"),
00415            aDebug, aDebugEnum, aRateEst;
00416    Long64_t suf = 1;
00417    Int_t aSubMg = -1;
00418    Bool_t fillList = kFALSE, useList = kFALSE;
00419    while (args.Tokenize(tok, from, " ")) {
00420       // Debug controllers
00421       if (tok.BeginsWith("debug=")) {
00422          aDebug = tok;
00423          aDebug.ReplaceAll("debug=","");
00424          Int_t icol = kNPOS;
00425          if ((icol = aDebug.Index(":")) != kNPOS) {
00426             aDebugEnum = aDebug(0, icol);
00427             aDebug.Remove(0, icol+1);
00428          }
00429          if (!aDebug.IsDigit()) {
00430             Printf("runProof: %s: error parsing the 'debug=' option (%s) - ignoring", act.Data(), tok.Data());
00431             aDebug = "";
00432             aDebugEnum = "";
00433          }
00434       }
00435       // Number of events
00436       if (tok.BeginsWith("nevt=")) {
00437          aNevt = tok;
00438          aNevt.ReplaceAll("nevt=","");
00439          if (!aNevt.IsDigit()) {
00440             Printf("runProof: %s: error parsing the 'nevt=' option (%s) - ignoring", act.Data(), tok.Data());
00441             aNevt = "";
00442          }
00443       }
00444       // Sync or async ?
00445       if (tok.BeginsWith("asyn"))
00446          opt = "ASYN";
00447       // Number of workers
00448       if (tok.BeginsWith("nwrk=")) {
00449          aNwrk = tok;
00450          aNwrk.ReplaceAll("nwrk=","");
00451          if (!aNwrk.IsDigit()) {
00452             Printf("runProof: %s: error parsing the 'nwrk=' option (%s) - ignoring", act.Data(), tok.Data());
00453             aNwrk = "";
00454          }
00455       }
00456       // Parallel unzipping ?
00457       if (tok.BeginsWith("punzip"))
00458          punzip = "on";
00459       // Number of workers
00460       if (tok.BeginsWith("cache=")) {
00461          aCache = tok;
00462          aCache.ReplaceAll("cache=","");
00463          if (aCache.EndsWith("k")) { aCache.Remove(TString::kTrailing, 'k'); suf = 1024; }
00464          if (aCache.EndsWith("K")) { aCache.Remove(TString::kTrailing, 'K'); suf = 1024; }
00465          if (aCache.EndsWith("M")) { aCache.Remove(TString::kTrailing, 'M'); suf = 1024*1024; }
00466          if (!aCache.IsDigit()) {
00467             Printf("runProof: %s: error parsing the 'cache=' option (%s) - ignoring", act.Data(), tok.Data());
00468             aCache = "";
00469          }
00470       }
00471       // Use submergers?
00472       if (tok.BeginsWith("submergers")) {
00473          tok.ReplaceAll("submergers","");
00474          aSubMg = 0;
00475          if (tok.BeginsWith("=")) {
00476             tok.ReplaceAll("=","");
00477             if (tok.IsDigit()) aSubMg = tok.Atoi();
00478          }
00479       }
00480       // H1: use entry-lists ?
00481       if (tok.BeginsWith("useList")) {
00482          useList = kTRUE;
00483       }
00484       if (tok.BeginsWith("fillList")) {
00485          fillList = kTRUE;
00486          opt += "fillList";
00487       }
00488       // H1: change location of files?
00489       if (tok.BeginsWith("h1src=")) {
00490          tok.ReplaceAll("h1src=","");
00491          if (!(tok.IsNull())) aH1Src = tok;
00492          Printf("runProof: %s: reading data files from '%s'", act.Data(), aH1Src.Data());
00493       }
00494       // Rate estimation technique
00495       if (tok.BeginsWith("rateest=")) {
00496          tok.ReplaceAll("rateest=","");
00497          if (!(tok.IsNull())) aRateEst = tok;
00498          Printf("runProof: %s: progress-bar rate estimation option: '%s'", act.Data(), aRateEst.Data());
00499       }
00500    }
00501    Long64_t nevt = (aNevt.IsNull()) ? -1 : aNevt.Atoi();
00502    Long64_t nwrk = (aNwrk.IsNull()) ? -1 : aNwrk.Atoi();
00503    from = 0;
00504 
00505    // Set number workers
00506    if (nwrk > 0) {
00507       if (proof->GetParallel() < nwrk) {
00508          Printf("runProof: %s: request for a number of workers larger then available - ignored", act.Data());
00509       } else {
00510          proof->SetParallel(nwrk);
00511       }
00512    }
00513 
00514    // Debug controllers
00515    if (!aDebug.IsNull()) {
00516       Int_t dbg = aDebug.Atoi();
00517       Int_t scope = TProofDebug::kAll;
00518       if (!aDebugEnum.IsNull()) scope = getDebugEnum(aDebugEnum.Data());
00519       proof->SetLogLevel(dbg, scope);
00520       Printf("runProof: %s: verbose mode for '%s'; level: %d", act.Data(), aDebugEnum.Data(), dbg);
00521    }
00522 
00523    // Have constant progress reporting based on estimated info
00524    // (NB: may screw up the progress bar in some cases)
00525    if (aRateEst == "average")
00526       proof->SetParameter("PROOF_RateEstimation", aRateEst);
00527 
00528    // Parallel unzip
00529    if (punzip == "on") {
00530       proof->SetParameter("PROOF_UseParallelUnzip", (Int_t)1);
00531       Printf("runProof: %s: parallel unzip enabled", act.Data());
00532    } else {
00533       proof->SetParameter("PROOF_UseParallelUnzip", (Int_t)0);
00534    }
00535 
00536    // Tree cache
00537    if (!aCache.IsNull()) {
00538       Long64_t cachesz = aCache.Atoi() * suf;
00539       if (cachesz <= 0) {
00540          proof->SetParameter("PROOF_UseTreeCache", (Int_t)0);
00541          Printf("runProof: %s: disabling tree cache", act.Data());
00542       } else {
00543          proof->SetParameter("PROOF_UseTreeCache", (Int_t)1);
00544          proof->SetParameter("PROOF_CacheSize", cachesz);
00545          Printf("runProof: %s: setting cache size to %lld", act.Data(), cachesz);
00546       }
00547    } else {
00548       // Use defaults
00549       proof->DeleteParameters("PROOF_UseTreeCache");
00550       proof->DeleteParameters("PROOF_CacheSize");
00551    }
00552 
00553    // Enable submergers, if required
00554    if (aSubMg >= 0) {
00555       gProof->SetParameter("PROOF_UseMergers", aSubMg);
00556       if (aSubMg > 0) {
00557          Printf("runProof: %s: enabling merging via %d sub-mergers", act.Data(), aSubMg);
00558       } else {
00559          Printf("runProof: %s: enabling merging via sub-mergers (optimal number)", act.Data());
00560       }
00561    } else {
00562       gProof->DeleteParameters("PROOF_UseMergers");
00563    }
00564 
00565    // Action
00566    if (act == "simple") {
00567       // ProofSimple is an example of non-data driven analysis; it
00568       // creates and fills with random numbers a given number of histos
00569 
00570       // Default 10000 events
00571       nevt = (nevt < 0) ? 100000 : nevt;
00572       // Find out the number of histograms
00573       TString aNhist;
00574       while (args.Tokenize(tok, from, " ")) {
00575          // Number of histos
00576          if (tok.BeginsWith("nhist=")) {
00577             aNhist = tok;
00578             aNhist.ReplaceAll("nhist=","");
00579             if (!aNhist.IsDigit()) {
00580                Printf("runProof: error parsing the 'nhist=' option (%s) - ignoring", tok.Data());
00581                aNhist = "";
00582             }
00583          }
00584       }
00585       Int_t nhist = (aNhist.IsNull()) ? 100 : aNhist.Atoi();
00586       Printf("\nrunProof: running \"simple\" with nhist= %d and nevt= %lld\n", nhist, nevt);
00587 
00588       // The number of histograms is added as parameter in the input list
00589       proof->SetParameter("ProofSimple_NHist", (Long_t)nhist);
00590       // The selector string
00591       sel.Form("%s/proof/ProofSimple.C%s", tutorials.Data(), aMode.Data());
00592       //
00593       // Run it for nevt times
00594       proof->Process(sel.Data(), nevt, opt);
00595 
00596    } else if (act == "h1") {
00597       // This is the famous 'h1' example analysis run on Proof reading the
00598       // data from the ROOT http server.
00599 
00600       // Create the chain
00601       TChain *chain = new TChain("h42");
00602       chain->Add(TString::Format("%s/dstarmb.root", aH1Src.Data()));
00603       chain->Add(TString::Format("%s/dstarp1a.root", aH1Src.Data()));
00604       chain->Add(TString::Format("%s/dstarp1b.root", aH1Src.Data()));
00605       chain->Add(TString::Format("%s/dstarp2.root", aH1Src.Data()));
00606       chain->ls();
00607       // We run on Proof
00608       chain->SetProof();
00609       // Set entrylist, if required
00610       if (useList) {
00611          TString eln("elist"), elfn("elist.root");
00612          if (gSystem->AccessPathName(elfn)) {
00613             Printf("\nrunProof: asked to use an entry list but '%s' not found or not readable", elfn.Data());
00614             Printf("\nrunProof: did you forget to run with 'fillList=%s'?\n", elfn.Data());
00615          } else {
00616             TFile f(elfn);
00617             if (!(f.IsZombie())) {
00618                TEntryList *elist = (TEntryList *)f.Get(eln);
00619                if (elist) {
00620                   elist->SetDirectory(0); //otherwise the file destructor will delete elist
00621                   chain->SetEntryList(elist);
00622                } else {
00623                   Printf("\nrunProof: could not find entry-list '%s' in file '%s': ignoring",
00624                          eln.Data(), elfn.Data());
00625                }
00626             } else {
00627                Printf("\nrunProof: requested entry-list file '%s' not existing (or not readable):"
00628                       " ignoring", elfn.Data());
00629             }
00630          }
00631       }
00632       // The selector
00633       sel.Form("%s/tree/h1analysis.C%s", tutorials.Data(), aMode.Data());
00634       // Run it 
00635       Printf("\nrunProof: running \"h1\"\n");
00636       chain->Process(sel.Data(),opt);
00637       // Cleanup the input list
00638       gProof->ClearInputData("elist");
00639       gProof->ClearInputData("elist.root");
00640       TIter nxi(gProof->GetInputList());
00641       TObject *o = 0;
00642       while ((o = nxi())) {
00643          if (!strncmp(o->GetName(), "elist", 5)) {
00644             gProof->GetInputList()->Remove(o);
00645             delete o;
00646          }
00647       }
00648 
00649    } else if (act == "pythia8") {
00650 
00651       TString path(Form("%s/Index.xml", pythia8data));
00652       gSystem->ExpandPathName(path);
00653       if (gSystem->AccessPathName(path)) {
00654          Printf("runProof: pythia8: PYTHIA8DATA directory (%s) must"
00655                 " contain the Index.xml file !", pythia8data);
00656          return;
00657       }
00658       TString pythia8par = TString::Format("%s/proof/pythia8.par", tutorials.Data());
00659       if (gSystem->AccessPathName(pythia8par.Data())) {
00660          Printf("runProof: pythia8: par file not found (tried %s)", pythia8par.Data());
00661          return;
00662       }
00663       proof->UploadPackage(pythia8par);
00664       proof->EnablePackage("pythia8");
00665       // Show enabled packages
00666       proof->ShowEnabledPackages();
00667       Printf("runProof: pythia8: check settings:");
00668       proof->Exec(".!echo hostname = `hostname`; echo \"ls pythia8:\"; ls pythia8");
00669       // Loading libraries needed
00670       if (gSystem->Load("libEG.so") < 0) {
00671          Printf("runProof: pythia8: libEG not found \n");
00672          return;
00673       }
00674       if (gSystem->Load("libEGPythia8.so") < 0) {
00675          Printf("runProof: pythia8: libEGPythia8 not found \n");
00676          return;
00677       }
00678       // Setting the default number of events, if needed
00679       nevt = (nevt < 0) ? 100 : nevt;
00680       Printf("\nrunProof: running \"Pythia01\" nevt= %lld\n", nevt);
00681       // The selector string
00682       sel.Form("%s/proof/ProofPythia.C%s", tutorials.Data(), aMode.Data());
00683       // Run it for nevt times
00684       proof->Process(sel.Data(), nevt);
00685 
00686   } else if (act == "event") {
00687 
00688       TString eventpar = TString::Format("%s/proof/event.par", tutorials.Data());
00689       if (gSystem->AccessPathName(eventpar.Data())) {
00690          Printf("runProof: event: par file not found (tried %s)", eventpar.Data());
00691          return;
00692       }
00693 
00694       proof->UploadPackage(eventpar);
00695       proof->EnablePackage("event");
00696       Printf("Enabled packages...\n");
00697       proof->ShowEnabledPackages(); 
00698 
00699       // Setting the default number of events, if needed
00700       nevt = (nevt < 0) ? 100 : nevt;
00701       Printf("\nrunProof: running \"event\" nevt= %lld\n", nevt);
00702       // The selector string
00703       sel.Form("%s/proof/ProofEvent.C%s", tutorials.Data(), aMode.Data());
00704       // Run it for nevt times
00705       proof->Process(sel.Data(), nevt);
00706 
00707   } else if (act == "eventproc") {
00708 
00709       TString eventpar = TString::Format("%s/proof/event.par", tutorials.Data());
00710       gSystem->ExpandPathName(eventpar);
00711       if (gSystem->AccessPathName(eventpar.Data())) {
00712          Printf("runProof: event: par file not found (tried %s)", eventpar.Data());
00713          return;
00714       }
00715 
00716       proof->UploadPackage(eventpar);
00717       proof->EnablePackage("event");
00718       Printf("Enabled packages...\n");
00719       proof->ShowEnabledPackages(); 
00720 
00721       // Extract the number of files to process, data source and
00722       // other parameters controlling the run ...
00723       Bool_t uneven = kFALSE;
00724       TString aFiles, aDataSrc("http://root.cern.ch/files/data"), aPartitions;
00725       proof->SetParameter("ProofEventProc_Read", "optimized");
00726       while (args.Tokenize(tok, from, " ")) {
00727          // Number of events
00728          if (tok.BeginsWith("files=")) {
00729             aFiles = tok;
00730             aFiles.ReplaceAll("files=","");
00731             if (!aFiles.IsDigit()) {
00732                Printf("runProof: error parsing the 'files=' option (%s) - ignoring", tok.Data());
00733                aFiles = "";
00734             }
00735          } else if (tok.BeginsWith("datasrc=")) {
00736             tok.ReplaceAll("datasrc=","");
00737             if (tok.IsDigit()) {
00738                Printf("runProof: error parsing the 'datasrc=' option (%s) - ignoring", tok.Data());
00739             } else {
00740                aDataSrc = tok;
00741                Printf("runProof: reading files from: %s", aDataSrc.Data());
00742             }
00743          } else if (tok == "readall") {
00744             proof->SetParameter("ProofEventProc_Read", "readall");
00745             Printf("runProof: eventproc: reading the full event");
00746          } else if (tok == "uneven") {
00747             uneven = kTRUE;
00748          } else if (tok.BeginsWith("partitions=")) {
00749             tok.ReplaceAll("partitions=","");
00750             if (tok.IsDigit()) {
00751                Printf("runProof: error parsing the 'partitions=' option (%s) - ignoring", tok.Data());
00752             } else {
00753                aPartitions = tok;
00754                Printf("runProof: partitions: %s included in packetizer operations", aPartitions.Data());
00755             }
00756          }
00757       }
00758       Int_t nFiles = (aFiles.IsNull()) ? 10 : aFiles.Atoi();
00759          Printf("runProof: found aFiles: '%s', nFiles: %d", aFiles.Data(), nFiles);
00760       if (nFiles > 50) {
00761          Printf("runProof: max number of files is 50 - resizing request");
00762          nFiles = 50;
00763       }
00764 
00765       // We create the chain now
00766       TChain *c = new TChain("EventTree");
00767 
00768       FileStat_t fst;
00769       if (gSystem->GetPathInfo(aDataSrc, fst) == 0 && R_ISREG(fst.fMode) &&
00770          !gSystem->AccessPathName(aDataSrc, kReadPermission)) {
00771          // It is a local file, we get the TFileCollection and we inject it into the chain
00772          TFileCollection *fc = new TFileCollection("", "", aDataSrc, nFiles);
00773          c->AddFileInfoList(fc->GetList());
00774          delete fc;
00775 
00776       } else {
00777 
00778          // Tokenize the source: if more than 1 we rotate the assignment. More sources can be specified
00779          // separating them by a '|'
00780          TObjArray *dsrcs = aDataSrc.Tokenize("|");
00781          Int_t nds = dsrcs->GetEntries();
00782 
00783          // Fill the chain
00784          Int_t i = 1, k = 0;
00785          TString fn;
00786          for (i = 1; i <= nFiles; i++) {
00787             k = (i - 1) % nds;
00788             TObjString *os = (TObjString *) (*dsrcs)[k];
00789             if (os) {
00790                fn.Form("%s/event_%d.root", os->GetName(), i);
00791                if (uneven) {
00792                   if ((i - 1)%5 == 0)
00793                      c->AddFile(fn.Data(), 50000);
00794                   else
00795                      c->AddFile(fn.Data(), 5000);
00796                } else {
00797                   c->AddFile(fn.Data());
00798                }
00799             }
00800          }
00801          dsrcs->SetOwner();
00802          delete dsrcs;
00803       }
00804       // Show the chain
00805       c->ls();
00806       c->SetProof();
00807 
00808       // Only validate the files really needed for the analysis
00809       proof->SetParameter("PROOF_ValidateByFile", 1);
00810 
00811       // Send over the  partition information, if any
00812       if (!aPartitions.IsNull()) {
00813          aPartitions.ReplaceAll("|", ",");
00814          proof->SetParameter("PROOF_PacketizerPartitions", aPartitions);
00815       }
00816 
00817       // The selector
00818       sel.Form("%s/proof/ProofEventProc.C%s", tutorials.Data(), aMode.Data());
00819       // Run it
00820       Printf("\nrunProof: running \"eventproc\"\n");
00821       c->Process(sel.Data(), opt, nevt);
00822 
00823    } else if (act == "ntuple") {
00824 
00825       // ProofNtuple is an example of non-data driven analysis; it
00826       // creates and fills a disk resident ntuple with automatic file merging 
00827 
00828       // Set the default number of events, if needed
00829       nevt = (nevt < 0) ? 1000 : nevt;
00830       Printf("\nrunProof: running \"ntuple\" with nevt= %lld\n", nevt);
00831 
00832       // Output file
00833       TString fout = TString::Format("%s/ProofNtuple.root", gSystem->WorkingDirectory());
00834       // Cleanup any existing instance of the output file
00835       gSystem->Unlink(fout);
00836 
00837       if (!isProofLocal) {
00838          // Setup a local basic xrootd to receive the file
00839          Bool_t xrdok = kFALSE;
00840          Int_t port = 9000;
00841          while (port < 9010) {
00842             if (checkXrootdAt(port) != 1) {
00843                if (startXrootdAt(port, gSystem->WorkingDirectory(), kTRUE) == 0) {
00844                   xrdok = kTRUE;
00845                   break;
00846                }
00847             }
00848             port++;
00849          }
00850          if (!xrdok) {
00851             Printf("runProof: could not start basic xrootd on ports 9000-9009 - cannot continue");
00852             return;
00853          }
00854          fout.Insert(0, TString::Format("root://%s:%d/", TUrl(gSystem->HostName()).GetHostFQDN(), port));
00855          // Make a copy of the files on the master before merging
00856          proof->AddInput(new TNamed("PROOF_OUTPUTFILE_LOCATION", "LOCAL"));
00857       }
00858       proof->AddInput(new TNamed("PROOF_OUTPUTFILE", fout.Data()));
00859 
00860       // The selector string
00861       sel.Form("%s/proof/ProofNtuple.C%s", tutorials.Data(), aMode.Data());
00862 
00863       // Run it for nevt times
00864       proof->Process(sel.Data(), nevt, opt);
00865 
00866    } else if (act == "dataset") {
00867 
00868       // This is an example of analysis creating data files on each node which are
00869       // automatically registered as dataset; the newly created dataset is used to create
00870       // the final plots. The data are of the same type as for the 'ntuple' example.
00871       // Selector used: ProofNtuple
00872 
00873       // Set the default number of events, if needed
00874       nevt = (nevt < 0) ? 1000000 : nevt;
00875       Printf("\nrunProof: running \"dataset\" with nevt= %lld\n", nevt);
00876 
00877       // Ask for registration of the dataset (the default is the the TFileCollection is return
00878       // without registration; the name of the TFileCollection is the name of the dataset
00879       proof->SetParameter("SimpleNtuple.root","testNtuple");
00880 
00881       // Do not plot the ntuple at this level
00882       proof->SetParameter("PROOF_NTUPLE_DONT_PLOT", "");
00883 
00884       // The selector string
00885       sel.Form("%s/proof/ProofNtuple.C%s", tutorials.Data(), aMode.Data());
00886       //
00887       // Run it for nevt times
00888       proof->Process(sel.Data(), nevt, opt);
00889 
00890       // The TFileCollection must be in the output
00891       if (proof->GetOutputList()->FindObject("testNtuple")) {
00892 
00893          // Plot the ntuple via PROOF (example of drawing PROOF actions)
00894          plotNtuple(proof, "testNtuple", "proof ntuple from dataset");
00895 
00896       } else {
00897          Printf("runProof: dataset 'testNtuple' not found in the output list");
00898       }
00899       // Do not plot the ntuple at this level
00900       proof->DeleteParameters("PROOF_NTUPLE_DONT_PLOT");
00901       proof->DeleteParameters("SimpleNtuple.root");
00902 
00903    } else if (act == "friends") {
00904 
00905       // This is an example of analysis creating two data files on each node (the main tree
00906       // and its friend) which are then processed as 'friends' to create the final plots.
00907       // Selector used: ProofFriends, ProofAux
00908 
00909       // File generation: we use TPacketizerFile in here to create two files per node
00910       TList *wrks = proof->GetListOfSlaveInfos();
00911       if (!wrks) {
00912          Printf("runProof: could not get the list of information about the workers");
00913          return;
00914       }
00915       // Create the map
00916       TString fntree;
00917       TMap *files = new TMap;
00918       files->SetName("PROOF_FilesToProcess");
00919       TIter nxwi(wrks);
00920       TSlaveInfo *wi = 0;
00921       while ((wi = (TSlaveInfo *) nxwi())) {
00922          fntree.Form("tree_%s.root", wi->GetOrdinal());
00923          TList *wrklist = (TList *) files->GetValue(wi->GetName());
00924          if (!wrklist) {
00925             wrklist = new TList;
00926             wrklist->SetName(wi->GetName());
00927             files->Add(new TObjString(wi->GetName()), wrklist);
00928          }
00929          wrklist->Add(new TObjString(fntree));
00930       }
00931 
00932       // Generate the files
00933       proof->AddInput(files);
00934       proof->SetParameter("ProofAux_Action", "GenerateTrees");
00935       // Default 1000 events
00936       nevt = (nevt < 0) ? 10000 : nevt;
00937       proof->SetParameter("ProofAux_NEvents", (Long64_t)nevt);
00938       // Special Packetizer
00939       proof->SetParameter("PROOF_Packetizer", "TPacketizerFile");
00940       // Now process
00941       sel.Form("%s/proof/ProofAux.C%s", tutorials.Data(), aMode.Data());
00942       proof->Process(sel.Data(), 1);
00943       // Remove the packetizer specifications
00944       proof->DeleteParameters("PROOF_Packetizer");
00945 
00946       // Print the lists and create the TDSet objects
00947       TDSet *dset = new TDSet("Tmain");
00948       TDSet *dsetf = new TDSet("Tfrnd");
00949       if (proof->GetOutputList()) {
00950          TIter nxo(proof->GetOutputList());
00951          TObject *o = 0;
00952          TObjString *os = 0;
00953          while ((o = nxo())) {
00954             TList *l = dynamic_cast<TList *> (o);
00955             if (l && !strncmp(l->GetName(), "MainList-", 9)) {
00956                TIter nxf(l);
00957                while ((os = (TObjString *) nxf()))
00958                   dset->Add(os->GetName());
00959             }
00960          }
00961          nxo.Reset();
00962          while ((o = nxo())) {
00963             TList *l = dynamic_cast<TList *> (o);
00964             if (l && !strncmp(l->GetName(), "FriendList-", 11)) {
00965                TIter nxf(l);
00966                while ((os = (TObjString *) nxf()))
00967                   dsetf->Add(os->GetName());
00968             }
00969          }
00970       }
00971       // Process with friends
00972       dset->AddFriend(dsetf, "friend");
00973       sel.Form("%s/proof/ProofFriends.C%s", tutorials.Data(), aMode.Data());
00974       dset->Process(sel);
00975       // Clear the files created by this run
00976       proof->ClearData(TProof::kUnregistered | TProof::kForceClear);
00977 
00978    } else {
00979       // Do not know what to run
00980       Printf("runProof: unknown tutorial: %s", what);
00981    }
00982 }
00983 
00984 //_______________________________________________________________________________________
00985 void plotNtuple(TProof *p, const char *ds, const char *ntptitle)
00986 {
00987    // Make some plots from the ntuple 'ntp' via PROOF
00988 
00989    //
00990    // Create a canvas, with 2 pads
00991    //
00992    TCanvas *c1 = new TCanvas(Form("cv-%s", ds), ntptitle,800,10,700,780);
00993    c1->Divide(1,2);
00994    TPad *pad1 = (TPad *) c1->GetPad(1);
00995    TPad *pad2 = (TPad *) c1->GetPad(2);
00996    //
00997    // Display a function of one ntuple column imposing a condition
00998    // on another column.
00999    pad1->cd();
01000    pad1->SetGrid();
01001    pad1->SetLogy();
01002    pad1->GetFrame()->SetFillColor(15);
01003 
01004    p->SetParameter("PROOF_LineColor", (Int_t)1);
01005    p->SetParameter("PROOF_FillStyle", (Int_t)1001);
01006    p->SetParameter("PROOF_FillColor", (Int_t)45);
01007    p->DrawSelect(ds, "3*px+2","px**2+py**2>1");
01008    p->SetParameter("PROOF_FillColor", (Int_t)38);
01009    p->DrawSelect(ds, "2*px+2","pz>2","same");
01010    p->SetParameter("PROOF_FillColor", (Int_t)5);
01011    p->DrawSelect(ds, "1.3*px+2","(px^2+py^2>4) && py>0","same");
01012    pad1->RedrawAxis();
01013 
01014    //
01015    // Display a 3-D scatter plot of 3 columns. Superimpose a different selection.
01016    pad2->cd();
01017    p->DrawSelect(ds, "pz:py:px","(pz<10 && pz>6)+(pz<4 && pz>3)");
01018    p->SetParameter("PROOF_MarkerColor", (Int_t)4);
01019    p->DrawSelect(ds, "pz:py:px","pz<6 && pz>4","same");
01020    p->SetParameter("PROOF_MarkerColor", (Int_t)5);
01021    p->DrawSelect(ds, "pz:py:px","pz<4 && pz>3","same");
01022    TPaveText *l2 = new TPaveText(0.,0.6,0.9,0.95);
01023    l2->SetFillColor(42);
01024    l2->SetTextAlign(12);
01025    l2->AddText("You can interactively rotate this view in 2 ways:");
01026    l2->AddText("  - With the RotateCube in clicking in this pad");
01027    l2->AddText("  - Selecting View with x3d in the View menu");
01028    l2->Draw();
01029 
01030    // Final update
01031    c1->cd();
01032    c1->Update();
01033 
01034    // Clear parameters used for the plots
01035    p->DeleteParameters("PROOF_*Color");
01036    p->DeleteParameters("PROOF_*Style");
01037 }
01038 
01039 int getDebugEnum(const char *what)
01040 {
01041    // Check if 'what' matches one of the TProofDebug enum and return the corresponding
01042    // integer. Relies on a perfect synchronization with the content of TProofDebug.h .
01043 
01044    TString sws(what), sw;
01045    int rcmask = 0;
01046    int from = 0;
01047    while (sws.Tokenize(sw, from , "|")) {
01048       if (sw.BeginsWith("k")) sw.Remove(0,1);
01049 
01050       if (sw == "None") {
01051          rcmask |= TProofDebug::kNone;
01052       } else if (sw == "Packetizer") {
01053          rcmask |= TProofDebug::kPacketizer;
01054       } else if (sw == "Loop") {
01055          rcmask |= TProofDebug::kLoop;
01056       } else if (sw == "Selector") {
01057          rcmask |= TProofDebug::kSelector;
01058       } else if (sw == "Output") {
01059          rcmask |= TProofDebug::kOutput;
01060       } else if (sw == "Input") {
01061          rcmask |= TProofDebug::kInput;
01062       } else if (sw == "Global") {
01063          rcmask |= TProofDebug::kGlobal;
01064       } else if (sw == "Package") {
01065          rcmask |= TProofDebug::kPackage;
01066       } else if (sw == "Feedback") {
01067          rcmask |= TProofDebug::kFeedback;
01068       } else if (sw == "Condor") {
01069          rcmask |= TProofDebug::kCondor;
01070       } else if (sw == "Draw") {
01071          rcmask |= TProofDebug::kDraw;
01072       } else if (sw == "Asyn") {
01073          rcmask |= TProofDebug::kAsyn;
01074       } else if (sw == "Cache") {
01075          rcmask |= TProofDebug::kCache;
01076       } else if (sw == "Collect") {
01077          rcmask |= TProofDebug::kCollect;
01078       } else if (sw == "Dataset") {
01079          rcmask |= TProofDebug::kDataset;
01080       } else if (sw == "Submerger") {
01081          rcmask |= TProofDebug::kSubmerger;
01082       } else if (sw == "All") {
01083          rcmask |= TProofDebug::kAll;
01084       } else if (!sw.IsNull()) {
01085          Printf("WARNING: requested debug enum name '%s' does not exist: assuming 'All'", sw.Data());
01086          rcmask |= TProofDebug::kAll;
01087       }
01088    }
01089    // Done
01090    return rcmask;
01091 }

Generated on Tue Jul 5 15:44:53 2011 for ROOT_528-00b_version by  doxygen 1.5.1