KaliVeda  1.13/01
Heavy-Ion Analysis Toolkit
KVDataAnalyser.cpp
Go to the documentation of this file.
1 /*
2 $Id: KVDataAnalyser.cpp,v 1.40 2009/01/14 16:15:46 franklan Exp $
3 $Revision: 1.40 $
4 $Date: 2009/01/14 16:15:46 $
5 $Author: franklan $
6 */
7 
8 #include "KVBase.h"
9 #include "KVDataAnalyser.h"
10 #include "KVDataAnalysisTask.h"
11 #include "KVDataSetManager.h"
12 #include "KVString.h"
13 #include "TObjString.h"
14 #include "TObjArray.h"
15 #include "Riostream.h"
16 #include "KVBatchSystemManager.h"
17 #include "TPluginManager.h"
18 #include "TSystemDirectory.h"
19 #include "TROOT.h"
20 #include "TClass.h"
21 #include "THashList.h"
22 #include "KVError.h"
23 
24 using namespace std;
26 
28 
30 
31 
34 
36 {
37  //Default constructor.
38  fParent = nullptr;
39  fBatch = kFALSE;
40  fTask = nullptr;
41  fQuit = kFALSE;
42  fSubmit = kFALSE;
43  nbEventToRead = -1;
44  fUserClassIsOK = kFALSE;
45  fUserClass = "";
46  fBatchEnv = new TEnv(".KVBatchrc");
48  fBatchSystem = 0;
49  fChoseRunMode = kFALSE;
50  fWorkDirInit = fWorkDirEnd = 0;
51  fMenus = kFALSE;
52 #ifdef WITH_CPP11
53  fProofMode = EProofMode::None;
54 #else
55  fProofMode = None;
56 #endif
57  fUseBaseClassSubmitTask = kFALSE;
58 }
59 
60 
61 
64 
65 KVDataAnalyser::~KVDataAnalyser()
66 {
67  //Default destructor.
68  delete fBatchEnv;
69  SafeDelete(fWorkDirInit);
70  SafeDelete(fWorkDirEnd);
71  if (gDataAnalyser == this)gDataAnalyser = nullptr;
72 }
73 
74 
75 
77 
79 {
80  fDataType = "";
81  fTask = nullptr;
82  fQuit = kFALSE;
83  fSubmit = kFALSE;
84  fUserClassIsOK = kFALSE;
85  fUserClass = "";
86  fUserClassOptions = "";
87  nbEventToRead = -1;
88  fBatchSystem = nullptr;
89  fChoseRunMode = kFALSE;
90 #ifdef WITH_CPP11
91  fProofMode = EProofMode::None;
92 #else
93  fProofMode = None;
94 #endif
95 }
96 
97 
98 
99 
102 
104 {
105  //Check all task variables, then run analyser
106 
107  fSubmit = kFALSE;
108  //print welcome message for main (parent) analyser
109  if (!fParent && !fMenus) KVBase::PrintSplashScreen();
110 
111  if (CheckTaskVariables()) {
112  if (fBatchSystem && !BatchMode()) {
113  //if batch mode is requested, the job is submitted to the chosen batch system
114  fBatchSystem->SubmitTask(this);
115  }
116  else {
117  if (BatchMode() && fBatchSystem && !fParent) fBatchSystem->Print("log");
118  if (!RunningInLaunchDirectory() && fParent) {
119  //when batch job runs in directory different to launch directory,
120  //we scan the list of files present in the current working directory
121  //just prior to running the analysis task
122  ScanWorkingDirectory(&fWorkDirInit);
123  }
124  if (!PreSubmitCheck()) return;
125 
126  // The following horrific kludge is supposed to solve the following problem:
127  // when running in batch mode (GridEngine) the data analyser created in
128  // KaliVedaAnalysis.cpp has to be of the right type (KVSimDirAnalyser or KVDataSetAnalyser)
129  // in order for it to read all necessary informations from the batch env file
130  // by calling the appropriate ReadBatchEnvFile override.
131  // However, when Run() is called for this object from KaliVedaAnalysis.cpp,
132  // we have to call the KVDataAnalyser::SubmitTask method, not the override in the
133  // derived class.
134  if (fUseBaseClassSubmitTask)
136  else
137  SubmitTask();
138 
139  if (!RunningInLaunchDirectory() && fParent) {
140  //when batch job runs in directory different to launch directory,
141  //we scan the list of files present in the current working directory
142  //just after running the analysis task
143  ScanWorkingDirectory(&fWorkDirEnd);
144  //any files which are present in the second list which were not present
145  //in the first list will be copied back to the launch directory
146  CopyAnalysisResultsToLaunchDirectory();
147  }
148  if (BatchMode() && fBatchSystem && !fParent) {
149  // at end of batch jobs,
150  // remove .[jobname] and [jobname].status files from $HOME directory
151  // remove .[jobname].bak and [jobname].status.bak files from $HOME directory
152  TString ff;
153  AssignAndDelete(ff, gSystem->ConcatFileName(gSystem->Getenv("HOME"), Form(".%s", GetBatchName())));
154  gSystem->Unlink(ff);
155  AssignAndDelete(ff, gSystem->ConcatFileName(gSystem->Getenv("HOME"), Form(".%s.bak", GetBatchName())));
156  gSystem->Unlink(ff);
157  AssignAndDelete(ff, gSystem->ConcatFileName(gSystem->Getenv("HOME"), Form("%s.status", GetBatchName())));
158  gSystem->Unlink(ff);
159  AssignAndDelete(ff, gSystem->ConcatFileName(gSystem->Getenv("HOME"), Form("%s.status.bak", GetBatchName())));
160  gSystem->Unlink(ff);
161  }
162  }
163  }
164  PostRunReset();
165 }
166 
167 
168 
169 
172 
174 {
175  //Run data analyser in menu-driven mode
176 
177  fMenus = kTRUE;
178  Reset();
180 
181  while (!fQuit) {
182  if (NeedToChooseWhatToDo())
183  ChooseWhatToDo();
184  else if (NeedToChooseWhatToAnalyse())
185  ChooseWhatToAnalyse();
186  else if (fSubmit) {
187  Run();
188  Reset();
190  }
191  }
192 }
193 
194 
195 
196 
201 
203 {
204  //Checks the task variables
205  //In batch mode, we first set the task variables by reading the
206  //batch env file associated with the name set for the batch job
207 
208  if (BatchMode()) ReadBatchEnvFile(Form(".%s", GetBatchName()));
209 
210  //if (!CheckWhatToAnalyseAndHow()) return kFALSE;
211 
212  if (fTask->WithUserClass() && fUserClass != ClassName()) {
213  //task requires user analysis class
214  if (fUserClass == "") {
215  ChooseUserClass();
216  }
217 
218  if (!CheckIfUserClassIsValid(fUserClassAlternativeBaseClass)) {
219  cout << "============> Warning <=============" << endl;
220  cout << GetUserClass() << " is not a valid " << fTask->GetUserBaseClass() << endl;
221  cout << "Analysis aborted." << endl;
222  cout << "====================================" << endl;
223  /*if (BatchMode())*/ return kFALSE; // avoid infinite loop in batch mode
224  //ChooseUserClass();
225  }
226  }
227 
228  if (nbEventToRead < 0) {
229  ChooseNbEventToRead();
230  }
231 
232  return kTRUE;
233 }
234 
235 
236 
238 
240 {
241  if (NeedToChooseWhatToDo()) {
242  return kFALSE;
243  }
244 
245  if (NeedToChooseWhatToAnalyse()) {
246  return kFALSE;
247  }
248  return kTRUE;
249 }
250 
251 
252 
253 
254 
255 
260 
262 {
263  //Set analysis task and data type
264  //For ways of obtaining pointers to data analysis tasks for any given dataset,
265  //see method KVDataSet::GetAnalysisTask(const Char_t* keywords) const.
266  fTask = at;
267  if (at)
268  fDataType = at->GetPrereq();
269  else
270  fDataType = "";
271 }
272 
273 
274 
275 
279 
281 {
282 // Add to the includes paths the user's includes paths
283 // the includes paths have to be separated by a white space
284 
285  fIncludes = "";
286  if (!incDirs) {
287  return;
288  }
289  TString tmp = incDirs;
290  TString curIncDir = gSystem->GetIncludePath();
291  TObjArray* oa = tmp.Tokenize(" ");
292  oa->SetOwner(kTRUE);
293  TIter next(oa);
294  TObjString* st = 0;
295  while ((st = (TObjString*)next())) {
296  TString id = st->GetString();
297  if (id.Length()) {
298  fIncludes += id.Data();
299  fIncludes += " ";
300  if (!curIncDir.Contains(id.Data())) {
301  cout << "Include path \"" << id.Data() << "\" added." << endl;
302  id.Prepend("-I");
303  gSystem->AddIncludePath(id.Data());
304  }
305  }
306  }
307  delete oa;
308 }
309 
310 
311 
312 
316 
318 {
319 // Load the user's libraries
320 // the libraries have to be separated by a white space
321 
322  fLibraries = "";
323  if (!libs) {
324  return;
325  }
326  KVString tmp = libs;
327  KVString slib = gSystem->GetLibraries("", "D");
328 
329  tmp.Begin(" ");
330  while (!tmp.End()) {
331 
332  KVString id = tmp.Next();
333 
334  Bool_t loaded = kFALSE;
335  slib.Begin(" ");
336  while (!slib.End() && !loaded) {
337  KVString ss = slib.Next();
338  if (ss == id) {
339  Info("SetUserLibraries", "%s already load", id.Data());
340  loaded = kTRUE;
341  }
342  else {
343  }
344  }
345  if (!loaded) {
346  Info("SetUserLibraries", "Library \"%s\"added.", id.Data());
347  gSystem->Load(id.Data());
348  }
349  fLibraries += id.Data();
350  fLibraries += " ";
351  }
352 
353 }
354 
355 
356 
357 
360 
362 {
363  // Ask user to set number of events to read
364 
365  SetNbEventToRead(-1);
366  while (nbEventToRead < 0) {
367  cout << "Give the number of events to read [<RET>=all]:" << endl;
368  KVString ntr;
369  ntr.ReadToDelim(cin);
370  if (ntr.IsDigit() || !ntr.Length()) {
371  if (ntr.Length()) {
372  nbEventToRead = (Long64_t) ntr.Atoi();
373  }
374  else {
375  nbEventToRead = 0;
376  }
377  }
378  else {
379  cout << "\"" << ntr.
380  Data() << "\" is not a number. Please retry." << endl;
381  }
382  }
383 }
384 
385 
386 
387 
391 
393 {
394  //Creates an instance of a class derived from KVDataAnalyser defined as a plugin
395 
396  //check and load plugin library
397  TPluginHandler* ph;
398  if (!(ph = KVBase::LoadPlugin("KVDataAnalyser", plugin)))
399  return 0;
400 
401  //execute constructor
402  KVDataAnalyser* da = (KVDataAnalyser*) ph->ExecPlugin(0);
403 
404  return da;
405 }
406 
407 
408 
409 
412 
414 {
415  //Choose the user's analysis class
416  fUserClass = "";
417  while (!fUserClass.Length()) {
418  cout << "Give the name of the analysis class derived from " << fTask->GetUserBaseClass() << ":" << endl;
419  fUserClass.ReadLine(cin);
420  fUserClassIsOK = kFALSE;
421  }
422 }
423 
424 
425 
426 
430 
432 {
433  //Check if files containing user's class are present in the working directory.
434  //The names of the implementation and header files are stored in fUserClassImp and fUserClassDec.
435 
436  return KVBase::FindClassSourceFiles(fUserClass.Data(), fUserClassImp, fUserClassDec);
437 }
438 
439 
440 
441 
458 
460 {
461  //Return kTRUE if the name of the class given by the user (fUserClass) is valid
462  //for the analysis task. This is so if one of the following is true:
463  // - the class library has already been loaded. In this case the class will exist
464  // in the dictionary (gROOT->GetClass()); we check if it derived from the
465  // base class defined for the analysis task
466  // - a plugin exists defining this class as an extension of the base class defined
467  // for the analysis task (gROOT->GetPluginManager()->FindHandler(...): the URI for
468  // the plugin must be the same as the name of the class)
469  // - source files for the class are present in the working directory. In this case
470  // we can add a plugin handler for the class.
471  //In the latter two cases, the class is valid if compilation succeeds.
472  //
473  //If the user's class may in fact be derived from an alternative base class, rather
474  //than the base class defined for this analysis task (see KVDataAnalysisTask::SetUserBaseClass)
475  //you can supply the name of this class (or a comma-separated list of base classes).
476 
477  TObject* o = GetInstanceOfUserClass(alternative_base_class);
478  if (o) {
479  delete o;
480  return kTRUE;
481  }
482  return kFALSE;
483 }
484 
485 
486 
487 
498 
500 {
501  // Returns string to be appended to name of user class for compilation with ACliC in
502  // GetInstanceOfUserClass. This depends on the boolean resources:
503  //
504  // KVDataAnalyser.UserClass.Debug: ( "yes" => "g" )
505  // KVDataAnalyser.UserClass.Optimise: ( "yes" => "O" )
506  // KVDataAnalyser.UserClass.ForceRecompile: ( "no" => "+"; "yes" => "++" )
507  //
508  // Note that if both Debug and Optimise are set to "yes/true", we use Debug mode.
509  // (can't have BOTH debug & optimisation).
510 
511  static TString aclic;
512  if (gEnv->GetValue("KVDataAnalyser.UserClass.ForceRecompile", kFALSE)) aclic = "++";
513  else aclic = "+";
514  if (gEnv->GetValue("KVDataAnalyser.UserClass.Debug", kFALSE)) aclic += "g";
515  else if (gEnv->GetValue("KVDataAnalyser.UserClass.Optimise", kFALSE)) aclic += "O";
516  return aclic.Data();
517 }
518 
519 
520 
522 
524 {
525  fBatchSystem = nullptr;
526 }
527 
528 
529 
530 
546 
548 {
549  //Return an instance of the class given by the user (fUserClass), if it is valid.
550  //If the user class is given in the form of source code, it will be (re)compiled
551  //if it has not already been loaded and/or the source has changed since the last
552  //build, using ACliC. If the resource
553  //
554  // KVDataAnalyser.UserClass.Debug: yes
555  //
556  //is set, the user's class will be compiled with extra debugging information
557  //
558  //Once compiled, we check that the user's class is indeed derived from the base
559  //class defined for this analysis task (see KVDataAnalysisTask::SetUserBaseClass).
560  //If the user's class may in fact be derived from an alternative base class, you
561  //can supply the name of this class (or comma-separated list of base classes).
562 
563  // make sure any required plugin library defining base class for user's analysis class is loaded
564  if (!fTask->CheckUserBaseClassIsLoaded()) return 0x0;
565 
566  //do we have a plugin ?
567  TPluginHandler* ph = gROOT->GetPluginManager()->FindHandler(fTask->GetUserBaseClass(), fUserClass.Data());
568  if (!ph) {//no plugin defined
569 
570  //if it is a precompiled class (i.e. already part of KaliVeda),
571  //it will be in the dictionary already
572  TClass* cl = gROOT->GetClass(fUserClass.Data());
573 
574  //do we have source files ?
575  if (DoUserClassFilesExist()) {
576  //compile & load user's source files using ACLIC. ACliC options read by GetACliCMode() from .kvrootrc
577  TString cmd;
578  cmd.Form(".L %s%s", fUserClassImp.Data(), GetACliCMode());
579  gROOT->ProcessLine(cmd.Data());
580  //class will be in dictionary if compilation successful
581  cl = gROOT->GetClass(fUserClass.Data());
582  }
583  else if (!cl) {
584  //class not in dictionary and no source files. help!
585  Info("GetInstanceOfUserClass", "Class %s is unknown and no source files available",
586  fUserClass.Data());
587  return 0;
588  }
589  if (!cl) {
590  //compilation of user class has failed
591  Info("GetInstanceOfUserClass", "Compilation of class %s failed. Correct the mistakes and try again",
592  fUserClass.Data());
593  return 0;
594  }
595  if (!cl->GetBaseClass(fTask->GetUserBaseClass())) {
596  // class does not inherit from base class defined by analysis task
597  if (alternative_base_class == "") { // no alternative base classes provided
598  Info("GetInstanceOfUserClass", "Class %s does not inherit from correct base class (%s), or compilation of class %s failed. Correct the mistakes and try again",
599  fUserClass.Data(), fTask->GetUserBaseClass(), fUserClass.Data());
600  return nullptr;
601  }
602  else {
603  // check alternative base class(es) - it may still be good!
604  bool got_good_base = false;
605  TString good_base = "";
606  alternative_base_class.Begin(",");
607  while (!alternative_base_class.End()) {
608  good_base = alternative_base_class.Next(kTRUE);
609  if (cl->GetBaseClass(good_base)) {
610  got_good_base = true;
611  break;
612  }
613  }
614  if (got_good_base) {
615  Info("GetInstanceOfUserClass", "Class %s inherits from alternative base class %s: OK!",
616  fUserClass.Data(), good_base.Data());
617  }
618  else {
619  Info("GetInstanceOfUserClass", "Class %s does not inherit from task-defined base class (%s) or any provided alternative base classes (%s), or compilation of class %s failed. Correct the mistakes and try again",
620  fUserClass.Data(), fTask->GetUserBaseClass(), alternative_base_class.Data(), fUserClass.Data());
621  return nullptr;
622  }
623  }
624  }
625  //EVERYTHING OK!! now instanciate an object of the new class
626  return (TObject*)cl->New();
627  }
628  else {
629  Info("GetInstanceOfUserClass", "Found plugin handler for class %s",
630  fUserClass.Data());
631  //load class from plugin
632  ph = KVBase::LoadPlugin(fTask->GetUserBaseClass(), fUserClass.Data());
633  if (!ph) {
634  Info("GetInstanceOfUserClass", "KVBase::LoadPlugin failed for %s", fUserClass.Data());
635  return 0;
636  }
637  TObject* obj = (TObject*)ph->ExecPlugin(0);
638  if (obj) {
639  //Info("GetInstanceOfUserClass", "constructor OK for %s", fUserClass.Data());
640  if (obj->InheritsFrom(fTask->GetUserBaseClass())) return obj;
641  Info("GetInstanceOfUserClass", "%s does not inherit from %s", fUserClass.Data(), fTask->GetUserBaseClass());
642  return 0;
643  }
644  else {
645  Info("GetInstanceOfUserClass", "constructor not OK for %s", fUserClass.Data());
646  return 0;
647  }
648  }
649  return 0;
650 }
651 
652 
653 
654 
659 
661 {
662  //Set name of user analysis class.
663  //If check=kTRUE (default), we check the validity of the class
664  //if check=kFALSE we do not check and assume that the class is valid
665 
666  fUserClass = kvs;
667  if (check) {
668  fUserClassIsOK = CheckIfUserClassIsValid();
669  }
670  else {
671  fUserClassIsOK = kTRUE;
672  }
673 }
674 
675 
676 
677 
683 
685 {
686  //Save (in the TEnv fBatchEnv) all necessary information on analysis task which can be used to execute it later
687  //(i.e. when batch processing system executes the job).
688  //If save=kTRUE (default), write the information in a file whose name is given by ".jobname"
689  //where 'jobname' is the name of the job as given to the batch system.
690 
691  delete fBatchEnv;
692  fBatchEnv = new TEnv(Form(".%s", jobname));
693  if (fBatchSystem) {
694  fBatchEnv->SetValue("BatchSystem", fBatchSystem->GetName());
695  fBatchSystem->WriteBatchEnvFile(fBatchEnv);
696  }
697  fBatchEnv->SetValue("AnalysisTask", fTask->GetType());
698 
699  if (fTask->WithUserClass()) {
700  fBatchEnv->SetValue("UserClass", GetUserClass());
701  if (fUserClassImp == "" || fUserClassDec == "") {
702  if (!DoUserClassFilesExist()) {
703  Warning("WriteBatchEnvFile", "Source files for user class %s do not exist. Job will not work.",
704  GetUserClass());
705  }
706  }
707  fBatchEnv->SetValue("UserClassOptions", fUserClassOptions);
708  fBatchEnv->SetValue("UserClassImp", fUserClassImp);
709  fBatchEnv->SetValue("UserClassDec", fUserClassDec);
710  }
711  else {
712  // a task without a user class may still need to pass options to the predefined analysis class
713  if (fUserClassOptions != "") fBatchEnv->SetValue("UserClassOptions", fUserClassOptions);
714  }
715  fBatchEnv->SetValue("NbToRead", (Double_t)nbEventToRead);
716  fBatchEnv->SetValue("LaunchDirectory", gSystem->WorkingDirectory());
717  if (fIncludes.Length()) {
718  fBatchEnv->SetValue("UserIncludes", fIncludes.Data());
719  }
720  if (fLibraries.Length()) {
721  fBatchEnv->SetValue("UserLibraries", fLibraries.Data());
722  }
723 
724  if (save) fBatchEnv->SaveLevel(kEnvUser);
725 }
726 
727 
728 
729 
734 
736 {
737  //Read the batch env file "filename" and initialise the analysis task using the
738  //informations in the file
739  //Returns kTRUE if all goes well
740 
741  Bool_t ok = kFALSE;
742 
743  delete fBatchEnv;
744  fBatchEnv = new TEnv(filename);
745  KVString val = fBatchEnv->GetValue("AnalysisTask", "");
746  fTask = 0;
747  if (val != "") {
748  if (!gDataSetManager) {
751  }
752  SetAnalysisTask(gDataSetManager->GetAnalysisTaskAny(val.Data()));
753  }
754  else {
755  Error("ReadBatchEnvFile", "Name of analysis task not given");
756  return ok;
757  }
758  if (!fTask) {
759  Error("ReadBatchEnvFile", "Analysis task \"%s\"not found for dataset %s",
760  val.Data(), gDataSet->GetName());
761  return ok;
762  }
763 
764  nbEventToRead = (Long64_t)fBatchEnv->GetValue("NbToRead", -1);
765  SetUserIncludes(fBatchEnv->GetValue("UserIncludes", ""));
766  SetUserLibraries(fBatchEnv->GetValue("UserLibraries", ""));
767 
768  //batch system
769  if (strcmp(fBatchEnv->GetValue("BatchSystem", ""), "")) {
770  fBatchSystem = gBatchSystemManager->GetBatchSystem(fBatchEnv->GetValue("BatchSystem", ""));
771  fBatchSystem->ReadBatchEnvFile(fBatchEnv);
772  fBatchSystem->cd(); // make gBatchSystem point to it
773  fBatchSystem->SetAnalyser(this);
774  }
775 
776  //User files
777  if (fTask->WithUserClass()) {
778  fUserClass = fBatchEnv->GetValue("UserClass", "");
779  if (fUserClass == "") {
780  Error("ReadBatchEnvFile", "Name of user class not given");
781  return ok;
782  }
783  fUserClassOptions = fBatchEnv->GetValue("UserClassOptions", "");
784  fUserClassImp = fBatchEnv->GetValue("UserClassImp", "");
785  if (fUserClassImp == "") {
786  Error("ReadBatchEnvFile", "Name of user class implementation file not given");
787  return ok;
788  }
789  fUserClassDec = fBatchEnv->GetValue("UserClassDec", "");
790  if (fUserClass == "") {
791  Error("ReadBatchEnvFile", "Name of user class header file not given");
792  return ok;
793  }
794  fUserClassAlternativeBaseClass = fBatchEnv->GetValue("UserClassAlternativeBaseClass", "");
795 
796  //If current working directory is not the same as the launch directory,
797  //we have to copy the user's files here
798  if (!RunningInLaunchDirectory()) {
799  TString launchDir = fBatchEnv->GetValue("LaunchDirectory", gSystem->WorkingDirectory());
800  TString path_src, path_trg;
801  //copy user's implementation file
802  AssignAndDelete(path_src, gSystem->ConcatFileName(launchDir.Data(), fUserClassImp.Data()));
803  AssignAndDelete(path_trg, gSystem->ConcatFileName(gSystem->WorkingDirectory(), fUserClassImp.Data()));
804  gSystem->CopyFile(path_src.Data(), path_trg.Data());
805  //copy user's header file
806  AssignAndDelete(path_src, gSystem->ConcatFileName(launchDir.Data(), fUserClassDec.Data()));
807  AssignAndDelete(path_trg, gSystem->ConcatFileName(gSystem->WorkingDirectory(), fUserClassDec.Data()));
808  gSystem->CopyFile(path_src.Data(), path_trg.Data());
809  }
810  }
811  else {
812  // a task without a user class may still need to pass options to the predefined analysis class
813  fUserClassOptions = fBatchEnv->GetValue("UserClassOptions", "");
814  }
815 
816  ok = kTRUE;
817 
818  return ok;
819 }
820 
821 
822 
823 
827 
829 {
830  //Returns kTRUE if current working directory is same as launch directory for batch job
831  //When not in batch mode, always returns kTRUE.
832  if (!BatchMode() || !fBatchEnv) return kTRUE;
833  TString launchDir = fBatchEnv->GetValue("LaunchDirectory", gSystem->WorkingDirectory());
834  return (launchDir == gSystem->WorkingDirectory());
835 }
836 
837 
838 
839 
841 
843 {
844  the_analyser->SetParent(this);
845  the_analyser->SetAnalysisTask(fTask);
846  the_analyser->SetNbEventToRead(GetNbEventToRead());
847  the_analyser->SetUserIncludes(fIncludes.Data());
848  the_analyser->SetUserLibraries(fLibraries.Data());
849 }
850 
851 
852 
858 
860 {
861  //In interactive mode, the data analysis task is performed by
862  //instanciating and initialising the KVDataAnalyser child class specified by the task,
863  //and then calling its Run() method.
864  //In batch mode, the job is submitted to the chosen batch system.
865 
866  KVString task_data_analyser = fTask->GetDataAnalyser();
867  Info("SubmitTask", "fTask->GetDataAnalyser()=%s", task_data_analyser.Data());
868  unique_ptr<KVDataAnalyser> the_analyser;
869  if (task_data_analyser == "UserClass") {
870  //the user-provided class is to be used as analyser
871  the_analyser.reset((KVDataAnalyser*)GetInstanceOfUserClass());
872  }
873  else {
874  the_analyser.reset(GetAnalyser(fTask->GetDataAnalyser()));
875  }
876  if (!the_analyser.get())
877  Fatal("SubmitTask", "the_analyser is 0x0, go to crash");
878 
879  set_up_analyser_for_task(the_analyser.get());
880 
881  if (fTask->WithUserClass()) {
882  the_analyser->SetUserClass(GetUserClass(), kFALSE);
883  the_analyser->SetUserClassOptions(fUserClassOptions);
884  }
885  else if (strcmp(fTask->GetUserBaseClass(), "")) the_analyser->SetUserClass(fTask->GetUserBaseClass(), kFALSE);
886  if (!BatchMode()) {
887  //when not in batch mode i.e. when submitting a task, we ask the user to supply
888  //any further information required by the task, and then ask whether to run in
889  //interactive or batch mode
890  the_analyser->CheckTaskVariables();
891  if (!fChoseRunMode) ChooseRunningMode();
892  }
893  the_analyser->SetBatchMode(BatchMode());
894  the_analyser->SetBatchName(GetBatchName());
895  the_analyser->SetBatchSystem(fBatchSystem);
896  the_analyser->SetProofMode(GetProofMode());
897  //set global pointer to analyser object which performs the analysis
898  //this allows e.g. user class to obtain information on the analysis task
899  gDataAnalyser = the_analyser.get();
900  the_analyser->Run();
901 }
902 
903 
904 
905 
912 
914 {
915  //Replace any 'special' symbols in "format" with their current values
916  //
917  // $Date : current date and time
918  // $User : name of user
919  // $UserClass : name of user's analysis class
920 
921  KVString tmp = format;
922  TDatime now;
923  KVString stDate = now.AsSQLString();
924  stDate.ReplaceAll(" ", "-");
925  tmp.ReplaceAll("$Date", stDate.Data());
926  if (fUserClass.Length()) tmp.ReplaceAll("$UserClass", fUserClass.Data());
927  else if (fTask) tmp.ReplaceAll("$UserClass", fTask->GetDataAnalyser());
928  tmp.ReplaceAll("$User", gSystem->GetUserInfo()->fUser.Data());
929  return tmp;
930 }
931 
932 
933 
935 
937 {
938  static TString keywords = "Will be expanded: $Date, $User, $UserClass";
939  return keywords;
940 }
941 
942 
943 
944 
945 
946 
950 
952 {
953  // Returns full path to job submission directory for batch jobs.
954  // Returns current working directory for non-batch jobs.
955 
956  if (!BatchMode() || !fBatchEnv) return gSystem->WorkingDirectory();
957  return fBatchEnv->GetValue("LaunchDirectory", gSystem->WorkingDirectory());
958 }
959 
960 
961 
968 
970 {
971  // Use this method to get the full path to a file in the directory where the job was launched.
972  //
973  // When not using a batch system, this will just be the current working directory.
974  //
975  // If the job is actually running elsewhere, use this method to access a file in the launch directory.
976 
977  TString fullpath;
978  AssignAndDelete(fullpath, gSystem->ConcatFileName(GetLaunchDirectory(), f.Data()));
979  return fullpath;
980 }
981 
982 
983 
986 
988 {
989  // Returns full path to file used to store status of running batch jobs
990 
991  if (!BatchMode() || !fBatchEnv) return "";
992 
993  static TString filename = "";
994  TString statfile;
995  statfile.Form("%s.status", gBatchSystem->GetJobName());
996 
997  TString launchDir = GetLaunchDirectory();
998  AssignAndDelete(filename, gSystem->ConcatFileName(launchDir.Data(), statfile.Data()));
999  return filename;
1000 }
1001 
1002 
1003 
1006 
1008 {
1009  // Update infos in batch status file
1010 
1011  if (!BatchMode() || !fBatchEnv) return;
1012 
1013  TEnv stats(GetBatchStatusFileName());
1014  stats.SetValue("TotalEvents", totev);
1015  stats.SetValue("EventsRead", evread);
1016  disk.Remove(TString::kTrailing, '\t');
1017  disk.Remove(TString::kTrailing, ' ');
1018  disk.Remove(TString::kTrailing, '\t');
1019  stats.SetValue("DiskUsed", disk.Data());
1020  stats.SaveLevel(kEnvLocal);
1021 }
1022 
1023 
1024 
1027 
1029 {
1030  // Delete batch status file (and backup - '.bak') for batch job
1031 
1032  if (!BatchMode() || !fBatchEnv) return;
1033  TString stats = GetBatchStatusFileName();
1034  gSystem->Unlink(stats);
1035  stats += ".bak";
1036  gSystem->Unlink(stats);
1037 }
1038 
1039 
1040 
1044 
1046 {
1047  // Returns kTRUE if the number of events coincides with the interval
1048  // set for status updates for the current data analysis task
1049  return (!(nevents % fTask->GetStatusUpdateInterval()) && nevents);
1050 }
1051 
1052 
1053 
1056 
1058 {
1059  // Print infos on events treated, disk usage, memory usage
1060 
1061  cout << " +++ " << nevents << " events processed +++ " << endl;
1062  ProcInfo_t pid;
1063  if (gSystem->GetProcInfo(&pid) == 0) {
1064  cout << " ------------- Process infos -------------" << endl;
1065  printf(" CpuSys = %f s. CpuUser = %f s. ResMem = %f MB VirtMem = %f MB\n",
1066  pid.fCpuSys, pid.fCpuUser, pid.fMemResident / 1024.,
1067  pid.fMemVirtual / 1024.);
1068  }
1069 }
1070 
1071 
1072 
1073 
1078 
1080 {
1081  //Ask user to choose between immediate or batch execution
1082  //If the choice is batch, we ask to choose a batch system and whether or not
1083  //to use the "multijobs" mode
1084 
1085  fChoseRunMode = kTRUE;
1086  KVString tmp;
1087  do {
1088  cout << endl << "Run in Interactive or Batch mode (I or B) ? : ";
1089  tmp.ReadLine(cin);
1090  }
1091  while (tmp != "i" && tmp != "I" && tmp != "b" && tmp != "B");
1092  tmp.ToUpper();
1093  //interactive mode - no more to do
1094  if (tmp == "I") {
1095  fBatchSystem = 0;
1096  return;
1097  }
1098  cout << endl << "Choose the batch system to use : " << endl;
1100  do {
1101  cout << "(enter a number) : " << endl;
1102  tmp.ReadLine(cin);
1103  }
1104  while (!tmp.IsDigit());
1105  fBatchSystem = gBatchSystemManager->GetBatchSystem(tmp.Atoi());
1106  fBatchSystem->Clear();
1107 }
1108 
1109 
1110 
1111 
1115 
1117 {
1118  //Fill TList with list of files in current working directory.
1119  //If ls!=0 it is deleted beforehand
1120  if (*ls) delete (*ls);
1121  TSystemDirectory dir("LocDir", gSystem->WorkingDirectory());
1122  (*ls) = dir.GetListOfFiles();
1123 }
1124 
1125 
1126 
1127 
1132 
1134 {
1135  //Compare the two lists of files in the current working directory, before and after analysis;
1136  //and copy any files which were created during the analysis to the launch directory.
1137  //Files with the same names in the launch directory will be overwritten if they exist.
1138 
1139  if (!fWorkDirInit || !fWorkDirEnd) return;
1140  TString launchDir = fBatchEnv->GetValue("LaunchDirectory", gSystem->WorkingDirectory());
1141  TIter next_new_file(fWorkDirEnd);
1142  TObject* file;
1143  while ((file = next_new_file())) {
1144  if (!fWorkDirInit->FindObject(file->GetName())) {
1145  TString fname;
1146  fname.Form("%s", file->GetName());
1147  //ajout d une condition pour eviter le transfert des file*.so generes par les KVParticleCondition
1148  //et aussi les .d generes par les KVParticleCondition
1149  if (!(fname.BeginsWith("KVParticleCondition_") || fname.EndsWith(".so") || fname.EndsWith(".d") || fname.EndsWith(".pcm") || fname.EndsWith(".bak"))) {
1150  TString path_src, path_trg;
1151  AssignAndDelete(path_trg, gSystem->ConcatFileName(launchDir.Data(), file->GetName()));
1153  file->GetName()));
1154  Info("CopyAnalysisResultsToLaunchDirectory", "Copying analysis results file :\n%s ---> %s",
1155  path_src.Data(), path_trg.Data());
1156  //copy & overwrite any existing file in launch directory
1157  if (gSystem->CopyFile(path_src.Data(), path_trg.Data(), kTRUE) == 0) {
1158  Info("CopyAnalysisResultsToLaunchDirectory", "File copied correctly");
1159  }
1160  else {
1161  Info("CopyAnalysisResultsToLaunchDirectory", " **** ERROR copying file !!! ");
1162  }
1163  }
1164  }
1165  }
1166 }
1167 
1168 
1169 
1170 
1175 
1177 {
1178  // Store lots of useful information about the current version of KaliVeda,
1179  // ROOT, etc. etc. in a TEnv object which will be added to the TTree's
1180  // list of user infos (TTree::GetUserInfo).
1181 
1182  tt->GetUserInfo()->Add(new TEnv());
1183  TEnv* kvenv = (TEnv*)tt->GetUserInfo()->FindObject("TEnv");
1184 
1185 //----
1186  THashList* hh = gEnv->GetTable();
1187  KVString tamp;
1188  for (Int_t kk = 0; kk < hh->GetEntries(); kk += 1) {
1189  tamp.Form("%s", hh->At(kk)->GetName());
1190  if (tamp.BeginsWith("Plugin.")) {}
1191  else kvenv->SetValue(hh->At(kk)->GetName(), ((TEnvRec*)hh->At(kk))->GetValue(), kEnvUser);
1192  }
1193 
1194  kvenv->SetValue("KVBase::GetKVVersion()", KVBase::GetKVVersion(), kEnvUser);
1195  kvenv->SetValue("KVBase::GetKVBuildDate()", KVBase::GetKVBuildDate(), kEnvUser);
1196  kvenv->SetValue("KVBase::GetKVBuildUser()", KVBase::GetKVBuildUser(), kEnvUser);
1197  kvenv->SetValue("KVBase::GetKVSourceDir()", KVBase::GetKVSourceDir(), kEnvUser);
1198 
1199 #ifdef WITH_BZR_INFOS
1200  kvenv->SetValue("KVBase::bzrRevisionId()", KVBase::bzrRevisionId(), kEnvUser);
1201  kvenv->SetValue("KVBase::bzrRevisionDate()", KVBase::bzrRevisionDate(), kEnvUser);
1202  kvenv->SetValue("KVBase::bzrBranchNick()", KVBase::bzrBranchNick(), kEnvUser);
1203  kvenv->SetValue("KVBase::bzrRevisionNumber()", KVBase::bzrRevisionNumber());
1204  kvenv->SetValue("KVBase::bzrIsBranchClean()", KVBase::bzrIsBranchClean());
1205 #endif
1206 #ifdef WITH_GIT_INFOS
1207  kvenv->SetValue("KVBase::gitBranch()", KVBase::gitBranch(), kEnvUser);
1208  kvenv->SetValue("KVBase::gitCommit()", KVBase::gitCommit(), kEnvUser);
1209 #endif
1210 
1211  kvenv->SetValue("gROOT->GetVersion()", gROOT->GetVersion(), kEnvUser);
1212 
1213  kvenv->SetValue("gSystem->GetBuildArch()", gSystem->GetBuildArch(), kEnvUser);
1214  kvenv->SetValue("gSystem->GetBuildCompiler()", gSystem->GetBuildCompiler(), kEnvUser);
1215  kvenv->SetValue("gSystem->GetBuildCompilerVersion()", gSystem->GetBuildCompilerVersion(), kEnvUser);
1216  kvenv->SetValue("gSystem->GetBuildNode()", gSystem->GetBuildNode(), kEnvUser);
1217  kvenv->SetValue("gSystem->GetBuildDir()", gSystem->GetBuildDir(), kEnvUser);
1218 
1219  kvenv->SetValue("gSystem->GetUserInfo()->fUser", gSystem->GetUserInfo()->fUser, kEnvUser);
1220  kvenv->SetValue("gSystem->HostName()", gSystem->HostName(), kEnvUser);
1221 
1222  if (fBatchEnv) {
1223  THashList* hh = fBatchEnv->GetTable();
1224  for (Int_t kk = 0; kk < hh->GetEntries(); kk += 1) {
1225  tamp.Form("%s", hh->At(kk)->GetName());
1226  if (!strcmp(kvenv->GetValue(hh->At(kk)->GetName(), "rien"), "rien"))
1227  kvenv->SetValue(hh->At(kk)->GetName(), ((TEnvRec*)hh->At(kk))->GetValue(), kEnvUser);
1228  }
1229  }
1230 
1231 
1232 }
1233 
1234 
1235 
1241 
1243 {
1244  //Set up and run data analysis task.
1245  //This allows to choose a dataset and a data analysis task and then execute the task or submit a batch job.
1246  //The behaviour of the data analyser object (base class KVDataAnalyser) can be modified by choosing
1247  //a plugin class corresponding to one of the plugins defined in $KVROOT/KVFiles/.kvrootrc.
1248 
1249  KVDataAnalyser* datan = 0;
1250  TString tmp(uri);
1251  if (tmp != "") {
1252  //got plugin ?
1253  TPluginHandler* ph = KVBase::LoadPlugin("KVDataAnalyser", uri);
1254  if (!ph)
1255  ::Warning("KVDataAnalyser::RunAnalyser", "No plugin %s found for KVDataAnalyser",
1256  uri);
1257  else
1258  datan = (KVDataAnalyser*) ph->ExecPlugin(0);
1259  }
1260  if (datan == 0)
1261  datan = new KVDataAnalyser;
1262  datan->RunMenus();
1263  delete datan;
1264 }
1265 
1266 
1267 
1272 
1274 {
1275  // Static method KVDataAnalyser::IsRunningBatchAnalysis()
1276  // Returns kTRUE if an analysis task is being performed in batch mode
1277  // Returns kFALSE if no analysis task is in interactive mode, or no analysis task running
1278 
1280  return kFALSE;
1281 }
1282 
1283 
1284 
1290 
1292 {
1293  // Create a KVNameValueList called "JobDescriptionList" and add it to
1294  // the TList. The parameters in the list describe the properties of the
1295  // current job. The TList pointer could be, for example, the address of
1296  // the TSelector::fInput list used by PROOF.
1297 
1298  KVNameValueList* jdl = new KVNameValueList("JobDescriptionList", "Job parameters");
1299 
1300  jdl->SetValue("AnalysisTask", fTask->GetType());
1301  jdl->SetValue("PROOFMode", GetProofMode());
1302 
1303  l->Add(jdl);
1304 }
1305 
1306 
1307 
1310 
1312 {
1313  // TO IMPLEMENT ?
1314 }
1315 
1316 
1317 
1320 
1322 {
1323  // TO IMPLEMENT ?
1324 }
1325 
1326 
int Int_t
void AssignAndDelete(TString &target, char *tobedeleted)
KVBatchSystemManager * gBatchSystemManager
KVBatchSystem * gBatchSystem
KVDataAnalyser * gDataAnalyser
KVDataSetManager * gDataSetManager
KVDataSet * gDataSet
Definition: KVDataSet.cpp:29
Defines macros for standard error messages.
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
KVString GetValue(KVString &l, char c)
Definition: KVTGID.cpp:800
#define SafeDelete(p)
#define f(i)
char Char_t
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
R__EXTERN TEnv * gEnv
kEnvUser
kEnvLocal
#define gROOT
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
static Bool_t FindClassSourceFiles(const Char_t *class_name, KVString &imp_file, KVString &dec_file, const Char_t *dir_name=".")
Definition: KVBase.cpp:1102
static const Char_t * GetKVBuildDate()
Returns KaliVeda build date.
Definition: KVBase.cpp:900
static const Char_t * gitCommit()
Returns last git commit of sources.
Definition: KVBase.cpp:976
static const Char_t * GetKVBuildUser()
Returns username of person who performed build.
Definition: KVBase.cpp:887
static const Char_t * gitBranch()
Returns git branch of sources.
Definition: KVBase.cpp:964
static const Char_t * GetKVSourceDir()
Returns top-level directory of source tree used for build.
Definition: KVBase.cpp:938
static void PrintSplashScreen()
Prints welcome message and infos on version etc.
Definition: KVBase.cpp:1593
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:793
static const Char_t * GetKVVersion()
Returns KaliVeda version string.
Definition: KVBase.cpp:874
Handles list of all available batch systems for processing non-interactive data analysis tasks.
void Print(Option_t *opt="") const
KVBatchSystem * GetBatchSystem(const Char_t *name)
Get batch system by name.
virtual const Char_t * GetJobName() const
virtual void ReadBatchEnvFile(TEnv *)
virtual void Clear(Option_t *opt="")
Manager class which sets up and runs data analysis tasks.
const Char_t * GetACliCMode()
void DoStatusUpdate(Long64_t nevents) const
Print infos on events treated, disk usage, memory usage.
virtual TString ExpandAutoBatchName(const Char_t *format) const
void SetParent(KVDataAnalyser *da)
virtual void PostRunReset()
virtual void Run()
Check all task variables, then run analyser.
virtual void Reset()
virtual void AddJobDescriptionList(TList *)
void ChooseNbEventToRead()
Ask user to set number of events to read.
Bool_t RunningInLaunchDirectory()
void SetUserLibraries(const Char_t *libs=0)
void SetUserClass(const Char_t *kvs, Bool_t check=kTRUE)
virtual Bool_t CheckIfUserClassIsValid(const KVString &alternative_base_class="")
TString GetPathToFileInLaunchDirectory(const TString &) const
void WriteBatchInfo(TTree *)
virtual void RunMenus()
Run data analyser in menu-driven mode.
virtual Bool_t CheckTaskVariables()
Bool_t DoUserClassFilesExist()
const Char_t * GetLaunchDirectory() const
void SetAnalysisTask(KVDataAnalysisTask *at)
virtual const Char_t * GetRecognisedAutoBatchNameKeywords() const
virtual void set_up_analyser_for_task(KVDataAnalyser *the_analyser)
virtual void WriteBatchEnvFile(const Char_t *, Bool_t sav=kTRUE)
virtual Bool_t CheckStatusUpdateInterval(Long64_t nevents) const
virtual Bool_t CheckWhatToAnalyseAndHow()
virtual void SubmitTask()
const Char_t * GetBatchStatusFileName() const
Returns full path to file used to store status of running batch jobs.
virtual void ChooseWhatToAnalyse()
TO IMPLEMENT ?
static Bool_t fCleanAbort
flag to force abort of processing
static KVDataAnalyser * GetAnalyser(const Char_t *plugin)
static Bool_t IsRunningBatchAnalysis()
static void RunAnalyser(const Char_t *plugin="")
void ScanWorkingDirectory(TList **)
void ChooseUserClass()
Choose the user's analysis class.
void CopyAnalysisResultsToLaunchDirectory()
void DeleteBatchStatusFile() const
Delete batch status file (and backup - '.bak') for batch job.
virtual Bool_t ReadBatchEnvFile(const Char_t *)
void SetUserIncludes(const Char_t *incDirs=0)
virtual void ChooseWhatToDo()
TO IMPLEMENT ?
Bool_t BatchMode() const
void UpdateBatchStatusFile(Int_t totev, Int_t evread, TString disk) const
Update infos in batch status file.
KVBatchSystem * fBatchSystem
batch system to use for submission of job
TObject * GetInstanceOfUserClass(const KVString &alternative_base_class="")
void SetNbEventToRead(Long64_t nb=0)
Define and manage data analysis tasks.
virtual const Char_t * GetPrereq() const
Manage all datasets contained in a given data repository.
virtual Bool_t Init(KVDataRepository *=0)
KVDataAnalysisTask * GetAnalysisTaskAny(const Char_t *keywords) const
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
void SetValue(const Char_t *name, value_type value)
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:72
void Begin(TString delim) const
Definition: KVString.cpp:565
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
virtual Int_t GetEntries() const
virtual void SetOwner(Bool_t enable=kTRUE)
const char * AsSQLString() const
virtual const char * GetValue(const char *name, const char *dflt) const
virtual void SetValue(const char *name, const char *value, EEnvLevel level=kEnvChange, const char *type=nullptr)
THashList * GetTable() const
virtual void SaveLevel(EEnvLevel level)
virtual TObject * At(Int_t idx) const
virtual const char * GetName() const
const TString & GetString() const
virtual const char * GetName() const
virtual Bool_t InheritsFrom(const char *classname) const
Longptr_t ExecPlugin(int nargs, const T &... params)
Ssiz_t Length() const
Int_t Atoi() const
std::istream & ReadToDelim(std::istream &str, char delim='\n')
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Bool_t IsDigit() const
void ToUpper()
TObjArray * Tokenize(const TString &delim) const
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
const char * Data() const
void Form(const char *fmt,...)
TString & Remove(EStripType s, char c)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
TString & ReplaceAll(const char *s1, const char *s2)
std::istream & ReadLine(std::istream &str, Bool_t skipWhite=kTRUE)
virtual TList * GetListOfFiles() const
virtual const char * GetBuildNode() const
virtual const char * GetBuildCompilerVersion() const
virtual const char * GetBuildDir() const
virtual void AddIncludePath(const char *includePath)
virtual int CopyFile(const char *from, const char *to, Bool_t overwrite=kFALSE)
virtual const char * Getenv(const char *env)
virtual const char * GetIncludePath()
virtual char * ConcatFileName(const char *dir, const char *name)
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
virtual UserGroup_t * GetUserInfo(const char *user=nullptr)
virtual int GetProcInfo(ProcInfo_t *info) const
virtual const char * HostName()
virtual const char * WorkingDirectory()
virtual const char * GetBuildCompiler() const
virtual const char * GetLibraries(const char *regexp="", const char *option="", Bool_t isRegexp=kTRUE)
virtual const char * GetBuildArch() const
virtual int Unlink(const char *name)
long long Long64_t
RooCmdArg ClassName(const char *name)
RooCmdArg BatchMode(bool flag=true)
const long double cl
Definition: KVUnits.h:85
void Info(const char *location, const char *va_(fmt),...)
void Error(const char *location, const char *va_(fmt),...)
void Fatal(const char *location, const char *va_(fmt),...)
void Warning(const char *location, const char *va_(fmt),...)
Long_t fMemVirtual
Float_t fCpuSys
Long_t fMemResident
Float_t fCpuUser
TString fUser
auto * tt
auto * l