ROOT logo
//
// Macro to run examples of analysis on 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:
//
//   1. "simple"
//
//      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 entries and the number of histograms can be passed as 'arguments'
//      to 'simple': e.g. to fill 16 histos with 1000000 entries use
//
//      root[] runProof("simple(nevt=1000000,nhist=16)")
//
//   2. "h1"
//
//      root[] runProof("h1")
//
//      This runs the 'famous' H1 analysis from $ROOTSYS/tree/h1analysis.C,.h .
//      The data are read from the HTTP server at root.cern.ch .
//
//  3. "event"
//
//      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. "pythia8"
//
//      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")
//
//
//   In all cases, to run in non blocking mode the option 'asyn' is available, e.g.
//
//   root[] runProof("h1(asyn)")
//
//
//
//   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.domain")
//
//   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.
//


#include "TChain.h"
#include "TEnv.h"
#include "TProof.h"
#include "TString.h"
#include "TDrawFeedback.h"
#include "TList.h"

#include "getProof.C"

TDrawFeedback *fb = 0;

// 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 *url = "proof://localhost:11093",
              Int_t nwrks = -1)
{
   gEnv->SetValue("Proof.StatsHist",1);

   // Temp dir for PROOF tutorials
   TString tutdir = Form("%s/.proof-tutorial", gSystem->TempDirectory());
   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());
   }

   // Get the PROOF Session
   TProof *proof = getProof(url, nwrks, tutdir.Data(), "ask");
   if (!proof) {
      Printf("runProof: could not start/attach a PROOF session");
      return;
   }
   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;

   // Create feedback displayer
   if (!fb) {
      fb = new TDrawFeedback(proof);
   }
   if (!proof->GetFeedbackList() || !proof->GetFeedbackList()->FindObject("PROOF_EventsHist")) {
      // Number of events per worker
      proof->AddFeedback("PROOF_EventsHist");
   }

   // Have constant progress reporting based on estimated info
   proof->SetParameter("PROOF_RateEstimation", "average");

   // 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;
   }

   // 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
      TString aNevt, aNhist, opt;
      while (args.Tokenize(tok, from, " ")) {
         // Number of events
         if (tok.BeginsWith("nevt=")) {
            aNevt = tok;
            aNevt.ReplaceAll("nevt=","");
            if (!aNevt.IsDigit()) {
               Printf("runProof: error parsing the 'nevt=' option (%s) - ignoring", tok.Data());
               aNevt = "";
            }
         }
         // 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 = "";
            }
         }
         // Sync or async ?
         if (tok.BeginsWith("asyn"))
            opt = "ASYN";
      }
      Long64_t nevt = (aNevt.IsNull()) ? 100000 : aNevt.Atoi();
      Int_t nhist = (aNhist.IsNull()) ? 100 : aNhist.Atoi();
      Printf("\nrunProof: running \"simple\" with nhist= %d and nevt= %d\n", nhist, nevt);

      // The number of histograms is added as parameter in the input list
      proof->SetParameter("ProofSimple_NHist", (Long_t)nhist);
      // The selector string
      TString sel = Form("%s/proof/ProofSimple.C+", tutorials.Data());
      //
      // Run it for nevt times
      proof->Process(sel.Data(), nevt, opt);

   } else if (act == "h1") {
      // This is the famous 'h1' example analysis run on Proof reading the
      // data from the ROOT http server.
      TString opt;
      while (args.Tokenize(tok, from, " ")) {
         // Sync or async ?
         if (tok.BeginsWith("asyn"))
            opt = "ASYN";
      }

      // Create the chain
      TChain *chain = new TChain("h42");
      chain->Add("http://root.cern.ch/files/h1/dstarmb.root");
      chain->Add("http://root.cern.ch/files/h1/dstarp1a.root");
      chain->Add("http://root.cern.ch/files/h1/dstarp1b.root");
      chain->Add("http://root.cern.ch/files/h1/dstarp2.root");
      // We run on Proof
      chain->SetProof();
      // The selector
      TString sel = Form("%s/tree/h1analysis.C+", tutorials.Data());
      // Run it for 10000 times
      Printf("\nrunProof: running \"h1\"\n");
      chain->Process(sel.Data(),opt);

   } else if (act == "pythia8") {

      TString path(Form("%s/Index.xml", pythia8data));
      gSystem->ExpandPathName(path);
      if (gSystem->AccessPathName(path)) {
         Printf("runProof: pythia8: PYTHIA8DATA directory (%s) must"
                " contain the Index.xml file !", pythia8data);
         return;
      }
      TString pythia8par("proof/pythia8");
      if (gSystem->AccessPathName(Form("%s.par", pythia8par.Data()))) {
         pythia8par = "pythia8";
         if (gSystem->AccessPathName(Form("%s.par", pythia8par.Data()))) {
            Printf("runProof: pythia8: par file not found: tried 'proof/pythia8.par'"
                   " and 'pythia8.par'");
            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 number of events from arguments
      TString aNevt, opt;
      while (args.Tokenize(tok, from, " ")) {
         // Number of events
         if (tok.BeginsWith("nevt=")) {
            aNevt = tok;
            aNevt.ReplaceAll("nevt=","");
            if (!aNevt.IsDigit()) {
               Printf("runProof: pythia8: error parsing the 'nevt=' option (%s) - ignoring", tok.Data());
               aNevt = "";
            }
         }
         // Sync or async ?
         if (tok.BeginsWith("asyn"))
            opt = "ASYN";
      }
      Long64_t nevt = (aNevt.IsNull()) ? 100 : aNevt.Atoi();
      Printf("\nrunProof: running \"Pythia01\" nevt= %d\n", nevt);
      // The selector string
      TString sel = Form("%s/proof/ProofPythia.C+", tutorials.Data());
      // Run it for nevt times
      proof->Process(sel.Data(), nevt);

  } else if (act == "event") {

      TString eventpar("proof/event");
      if (gSystem->AccessPathName(Form("%s.par", eventpar.Data()))) {
         eventpar = "event";
         if (gSystem->AccessPathName(Form("%s.par", eventpar.Data()))) {
            Printf("runProof: event: par file not found: tried 'proof/event.par'"
                   " and 'event.par'");
            return;
         }
      }

      proof->UploadPackage(eventpar);
      proof->EnablePackage("event");
      Printf("Enabled packages...\n");
      proof->ShowEnabledPackages(); 

      // Setting number of events from arguments
      TString aNevt, opt;
      while (args.Tokenize(tok, from, " ")) {
         // Number of events
         if (tok.BeginsWith("nevt=")) {
            aNevt = tok;
            aNevt.ReplaceAll("nevt=","");
            if (!aNevt.IsDigit()) {
               Printf("runProof: event: error parsing the 'nevt=' option (%s) - ignoring", tok.Data());
               aNevt = "";
            }
         }
         // Sync or async ?
         if (tok.BeginsWith("asyn"))
            opt = "ASYN";
      }

      Long64_t nevt = (aNevt.IsNull()) ? 100 : aNevt.Atoi();
      Printf("\nrunProof: running \"event\" nevt= %d\n", nevt);
      // The selector string
      TString sel = Form("%s/proof/ProofEvent.C+", tutorials.Data());
      // Run it for nevt times
      proof->Process(sel.Data(), nevt);

   } else {
      // Do not know what to run
      Printf("runProof: unknown tutorial: %s", what);
   }
}
 runProof.C:1
 runProof.C:2
 runProof.C:3
 runProof.C:4
 runProof.C:5
 runProof.C:6
 runProof.C:7
 runProof.C:8
 runProof.C:9
 runProof.C:10
 runProof.C:11
 runProof.C:12
 runProof.C:13
 runProof.C:14
 runProof.C:15
 runProof.C:16
 runProof.C:17
 runProof.C:18
 runProof.C:19
 runProof.C:20
 runProof.C:21
 runProof.C:22
 runProof.C:23
 runProof.C:24
 runProof.C:25
 runProof.C:26
 runProof.C:27
 runProof.C:28
 runProof.C:29
 runProof.C:30
 runProof.C:31
 runProof.C:32
 runProof.C:33
 runProof.C:34
 runProof.C:35
 runProof.C:36
 runProof.C:37
 runProof.C:38
 runProof.C:39
 runProof.C:40
 runProof.C:41
 runProof.C:42
 runProof.C:43
 runProof.C:44
 runProof.C:45
 runProof.C:46
 runProof.C:47
 runProof.C:48
 runProof.C:49
 runProof.C:50
 runProof.C:51
 runProof.C:52
 runProof.C:53
 runProof.C:54
 runProof.C:55
 runProof.C:56
 runProof.C:57
 runProof.C:58
 runProof.C:59
 runProof.C:60
 runProof.C:61
 runProof.C:62
 runProof.C:63
 runProof.C:64
 runProof.C:65
 runProof.C:66
 runProof.C:67
 runProof.C:68
 runProof.C:69
 runProof.C:70
 runProof.C:71
 runProof.C:72
 runProof.C:73
 runProof.C:74
 runProof.C:75
 runProof.C:76
 runProof.C:77
 runProof.C:78
 runProof.C:79
 runProof.C:80
 runProof.C:81
 runProof.C:82
 runProof.C:83
 runProof.C:84
 runProof.C:85
 runProof.C:86
 runProof.C:87
 runProof.C:88
 runProof.C:89
 runProof.C:90
 runProof.C:91
 runProof.C:92
 runProof.C:93
 runProof.C:94
 runProof.C:95
 runProof.C:96
 runProof.C:97
 runProof.C:98
 runProof.C:99
 runProof.C:100
 runProof.C:101
 runProof.C:102
 runProof.C:103
 runProof.C:104
 runProof.C:105
 runProof.C:106
 runProof.C:107
 runProof.C:108
 runProof.C:109
 runProof.C:110
 runProof.C:111
 runProof.C:112
 runProof.C:113
 runProof.C:114
 runProof.C:115
 runProof.C:116
 runProof.C:117
 runProof.C:118
 runProof.C:119
 runProof.C:120
 runProof.C:121
 runProof.C:122
 runProof.C:123
 runProof.C:124
 runProof.C:125
 runProof.C:126
 runProof.C:127
 runProof.C:128
 runProof.C:129
 runProof.C:130
 runProof.C:131
 runProof.C:132
 runProof.C:133
 runProof.C:134
 runProof.C:135
 runProof.C:136
 runProof.C:137
 runProof.C:138
 runProof.C:139
 runProof.C:140
 runProof.C:141
 runProof.C:142
 runProof.C:143
 runProof.C:144
 runProof.C:145
 runProof.C:146
 runProof.C:147
 runProof.C:148
 runProof.C:149
 runProof.C:150
 runProof.C:151
 runProof.C:152
 runProof.C:153
 runProof.C:154
 runProof.C:155
 runProof.C:156
 runProof.C:157
 runProof.C:158
 runProof.C:159
 runProof.C:160
 runProof.C:161
 runProof.C:162
 runProof.C:163
 runProof.C:164
 runProof.C:165
 runProof.C:166
 runProof.C:167
 runProof.C:168
 runProof.C:169
 runProof.C:170
 runProof.C:171
 runProof.C:172
 runProof.C:173
 runProof.C:174
 runProof.C:175
 runProof.C:176
 runProof.C:177
 runProof.C:178
 runProof.C:179
 runProof.C:180
 runProof.C:181
 runProof.C:182
 runProof.C:183
 runProof.C:184
 runProof.C:185
 runProof.C:186
 runProof.C:187
 runProof.C:188
 runProof.C:189
 runProof.C:190
 runProof.C:191
 runProof.C:192
 runProof.C:193
 runProof.C:194
 runProof.C:195
 runProof.C:196
 runProof.C:197
 runProof.C:198
 runProof.C:199
 runProof.C:200
 runProof.C:201
 runProof.C:202
 runProof.C:203
 runProof.C:204
 runProof.C:205
 runProof.C:206
 runProof.C:207
 runProof.C:208
 runProof.C:209
 runProof.C:210
 runProof.C:211
 runProof.C:212
 runProof.C:213
 runProof.C:214
 runProof.C:215
 runProof.C:216
 runProof.C:217
 runProof.C:218
 runProof.C:219
 runProof.C:220
 runProof.C:221
 runProof.C:222
 runProof.C:223
 runProof.C:224
 runProof.C:225
 runProof.C:226
 runProof.C:227
 runProof.C:228
 runProof.C:229
 runProof.C:230
 runProof.C:231
 runProof.C:232
 runProof.C:233
 runProof.C:234
 runProof.C:235
 runProof.C:236
 runProof.C:237
 runProof.C:238
 runProof.C:239
 runProof.C:240
 runProof.C:241
 runProof.C:242
 runProof.C:243
 runProof.C:244
 runProof.C:245
 runProof.C:246
 runProof.C:247
 runProof.C:248
 runProof.C:249
 runProof.C:250
 runProof.C:251
 runProof.C:252
 runProof.C:253
 runProof.C:254
 runProof.C:255
 runProof.C:256
 runProof.C:257
 runProof.C:258
 runProof.C:259
 runProof.C:260
 runProof.C:261
 runProof.C:262
 runProof.C:263
 runProof.C:264
 runProof.C:265
 runProof.C:266
 runProof.C:267
 runProof.C:268
 runProof.C:269
 runProof.C:270
 runProof.C:271
 runProof.C:272
 runProof.C:273
 runProof.C:274
 runProof.C:275
 runProof.C:276
 runProof.C:277
 runProof.C:278
 runProof.C:279
 runProof.C:280
 runProof.C:281
 runProof.C:282
 runProof.C:283
 runProof.C:284
 runProof.C:285
 runProof.C:286
 runProof.C:287
 runProof.C:288
 runProof.C:289
 runProof.C:290
 runProof.C:291
 runProof.C:292
 runProof.C:293
 runProof.C:294
 runProof.C:295
 runProof.C:296
 runProof.C:297
 runProof.C:298
 runProof.C:299
 runProof.C:300
 runProof.C:301
 runProof.C:302
 runProof.C:303
 runProof.C:304
 runProof.C:305
 runProof.C:306
 runProof.C:307
 runProof.C:308
 runProof.C:309
 runProof.C:310
 runProof.C:311
 runProof.C:312
 runProof.C:313
 runProof.C:314
 runProof.C:315
 runProof.C:316
 runProof.C:317
 runProof.C:318
 runProof.C:319
 runProof.C:320
 runProof.C:321
 runProof.C:322
 runProof.C:323
 runProof.C:324
 runProof.C:325
 runProof.C:326
 runProof.C:327
 runProof.C:328
 runProof.C:329
 runProof.C:330
 runProof.C:331
 runProof.C:332
 runProof.C:333
 runProof.C:334
 runProof.C:335
 runProof.C:336
 runProof.C:337
 runProof.C:338
 runProof.C:339
 runProof.C:340
 runProof.C:341
 runProof.C:342
 runProof.C:343
 runProof.C:344
 runProof.C:345
 runProof.C:346
 runProof.C:347
 runProof.C:348
 runProof.C:349
 runProof.C:350
 runProof.C:351
 runProof.C:352
 runProof.C:353
 runProof.C:354
 runProof.C:355
 runProof.C:356
 runProof.C:357
 runProof.C:358
 runProof.C:359
 runProof.C:360
 runProof.C:361
 runProof.C:362
 runProof.C:363
 runProof.C:364
 runProof.C:365
 runProof.C:366
 runProof.C:367
 runProof.C:368
 runProof.C:369
 runProof.C:370
 runProof.C:371
 runProof.C:372