KaliVeda
Toolkit for HIC analysis
KVDataSet.cpp
1 /*
2 $Id: KVDataSet.cpp,v 1.41 2009/03/11 14:22:41 franklan Exp $
3 $Revision: 1.41 $
4 $Date: 2009/03/11 14:22:41 $
5 $Author: franklan $
6 */
7 
8 #include "TMethodCall.h"
9 #include "KVDataSet.h"
10 #include "KVDataRepository.h"
11 #include "KVDataRepositoryManager.h"
12 #include "KVDataSetManager.h"
13 #include "TSystem.h"
14 #include "TObjArray.h"
15 #include "TObjString.h"
16 #include "KVDBSystem.h"
17 #include "KVDBRun.h"
18 #include "TEnv.h"
19 #include "KVAvailableRunsFile.h"
20 #include "KVNumberList.h"
21 #include "TPluginManager.h"
22 #include "TClass.h"
23 #include "KVRunFile.h"
24 
25 using namespace std;
26 
28 
29 KVDataSet* gDataSet;
30 
31 
34 
36 {
37  //Default constructor
38  fRepository = nullptr;
39  fDataBase = nullptr;
40  fAllTasks.SetOwner(kTRUE);
41  fTasks.SetOwner(kFALSE);
42 }
43 
44 
45 
49 
51 {
52  //Returns available runs file object for given data 'type' (="raw", "recon", "ident", "root")
53  //Object will be created and added to internal list if it does not exist
54 
55  if (!fRepository) return nullptr;
56  KVAvailableRunsFile* avrf =
57  (KVAvailableRunsFile*) fAvailableRuns.FindObjectByName(type);
58  if (!avrf) {
59  avrf = fRepository->NewAvailableRunsFile(type, this);
60  fAvailableRuns.Add(avrf);
61  }
62  return avrf;
63 }
64 
65 
66 
81 
83 {
84  //Returns name of file containing database for dataset.
85  //
86  //This is fixed as `DataBase.root.M.mm` where
87  // - `M` is the current major version number
88  // - `m` is the current minor version number
89  //
90  //(fixed to be consistent with CMake function INSTALL_KALIVEDA_DATASETS which sets up
91  //the Makefile for each dataset which automatically triggers rebuilding of the ROOT file
92  //when source files change: thus we must have the right file name!)
93  //
94  //This in order to avoid problems if several different versions of KaliVeda
95  //use the same working directory (in user's `$HOME/.kaliveda`) to write the
96  //database files, which are often incompatible between versions
97 
98  TString n = "DataBase.root";
99  n.Append(Form(".%d.%d", GetKVMajorVersion(),
100  GetKVMinorVersion()));
101  return n;
102 }
103 
104 
105 
109 
111 {
112  //Returns name of database object in database file.
113  //If this is not set explicitly with SetDBName(), we use the name of the dataset by default
114 
115  return (fDBName != "" ? fDBName.Data() : GetName());
116 }
117 
118 
119 
120 
123 
124 void KVDataSet::OpenDBFile(const Char_t* full_path_to_dbfile) const
125 {
126  //Open the database from a file on disk.
127 
128  TDirectory* work_dir = gDirectory; //keep pointer to current directory
129  fDBase.reset(new TFile(full_path_to_dbfile, "READ"));
130 
131  if (fDBase->IsOpen()) {
132  fDataBase = dynamic_cast<KVExpDB*>(fDBase->Get(GetDBName()));
133  if (!fDataBase) {
134  Error("OpenDBFile", "%s not found in file %s", GetDBName().Data(),
135  GetDBFileName().Data());
136  }
137  else {
138  fDataBase->ReadObjects(fDBase.get()); // read any associated objects
139  }
140  work_dir->cd(); //back to initial working directory
141  }
142 }
143 
144 
145 
146 
149 
151 {
152  // Returns full path to file where database is written on disk
153 
154  TString dbfile = GetDBFileName();
155  TString dbfile_fullpath;
156  TString tmp;
157 
158  // If this dataset is just an alias for another dataset i.e. if DataSet.Directory
159  // is set with just the name of another dataset (not a full path to dataset files)
160  // then the database file should be written/found under the name of the alias.
161  TString dataset_alias = GetDataSetEnv("DataSet.Directory", GetName());
162  TString db_alias = GetName();
163  if (!gSystem->IsAbsoluteFileName(dataset_alias)) db_alias = dataset_alias;
164 
165  AssignAndDelete(tmp, gSystem->ConcatFileName(GetDATABASEFilePath(), db_alias.Data()));
166  AssignAndDelete(dbfile_fullpath, gSystem->ConcatFileName(tmp.Data(), dbfile.Data()));
167  return dbfile_fullpath;
168 }
169 
170 
171 
177 
179 {
180  //PROTECTED METHOD
181  //Called by KVDataSet::SetAnalysisTasks
182  //Check environment variables (i.e. .kvrootrc) to see if the task parameters
183  //have been "tweaked" for the dataset.
184 
185  KVString envar = GetDataSetEnv(Form("%s.DataAnalysisTask.Title", t->GetName()));
186  if (envar != "") t->SetTitle(envar);
187  envar = GetDataSetEnv(Form("%s.DataAnalysisTask.Analyser", t->GetName()));
188  if (envar != "") t->SetDataAnalyser(envar);
189  envar = GetDataSetEnv(Form("%s.DataAnalysisTask.UserClass.Base", t->GetName()));
190  if (envar != "") t->SetUserBaseClass(envar);
191  envar = GetDataSetEnv(Form("%s.DataAnalysisTask.Prereq", t->GetName()));
192  if (envar != "") t->SetPrereq(envar);
193  envar = GetDataSetEnv(Form("%s.DataAnalysisTask.UserClass.ExtraACliCIncludes", t->GetName()));
194  if (envar != "") t->SetExtraAClicIncludes(envar);
195  Int_t nev = (Int_t)GetDataSetEnv(Form("%s.DataAnalysisTask.StatusUpdateInterval", t->GetName()), 0.0);
196  if (nev > 0) t->SetStatusUpdateInterval(nev);
197 }
198 
199 
200 
201 
212 
214 {
215  // Write the database to disk (ROOT file).
216  // It will be written in the directory
217  // $KVROOT/db/[dataset name]
218  // If the directory does not exist, it will be created. Permissions are set to 775 (rwxrwxr-x).
219  //
220  // # Default name of database file containing informations on runs, systems, calibration parameters etc.
221  // DataSet.DatabaseFile: DataBase.root
222  // # Default name of database object in file
223  // DataSet.DatabaseName: DataBase
224 
225  TString dbfile_fullpath = GetFullPathToDB();
226  TString tmp = gSystem->DirName(dbfile_fullpath.Data()); //full path to directory $KVROOT/db/[dataset name]
227 
228  if (gSystem->AccessPathName(tmp.Data())) { // directory $KVROOT/db/[dataset name] does not exist
229 
230  if (gSystem->mkdir(tmp.Data()) == -1) { // problem creating $KVROOT/db/[dataset name]
231 
232  TString tmp2 = gSystem->DirName(tmp.Data());// full path to directory $KVROOT/db
233 
234  if (gSystem->AccessPathName(tmp2.Data())) { // directory $KVROOT/db does not exist
235 
236  if (gSystem->mkdir(tmp2.Data()) == -1) { // problem creating $KVROOT/db
237  Error("SaveDataBase", "Cannot create directory %s required to save database",
238  tmp2.Data());
239  return;
240  }
241  gSystem->Chmod(tmp2.Data(), 0775);
242  }
243  else {
244  Error("SaveDataBase", "Cannot create directory %s required to save database, even though %s exists: check disk space ?",
245  tmp.Data(), tmp2.Data());
246  return;
247  }
248  //try again
249  if (gSystem->mkdir(tmp.Data()) == -1) {
250  Error("SaveDataBase", "Cannot create directory %s required to save database",
251  tmp.Data());
252  return;
253  }
254  else {
255  gSystem->Chmod(tmp.Data(), 0775);
256  }
257  }
258  else {
259  gSystem->Chmod(tmp.Data(), 0775);
260  }
261  }
262 
263  WriteDBFile(dbfile_fullpath.Data());
264 }
265 
266 
267 
268 
273 
274 void KVDataSet::WriteDBFile(const Char_t* full_path_to_dbfile) const
275 {
276  //PRIVATE METHOD
277  //Write the database to disk.
278  //Set permissions to rw for user & group
279 
280  TDirectory* work_dir = gDirectory; //keep pointer to current directory
281  if (!fDataBase) {
282  Error("WriteDBFile", "Database has not been built");
283  return;
284  }
285  fDBase.reset(new TFile(full_path_to_dbfile, "recreate"));
286  fDBase->cd(); //set as current directory (maybe not necessary)
287  fDataBase->Write(GetDBName()); //write database to file with given name
288  fDataBase->WriteObjects(fDBase.get()); //write any associated objects
289  fDBase->Write(); // write file header etc.
290  fDBase->Close(); // close file
291  gSystem->Chmod(full_path_to_dbfile, 0664); // set permissions to rw-rw-r--
292  work_dir->cd(); //back to initial working directory
293 }
294 
295 
296 
307 
309 {
310  //Returns pointer to database associated with this dataset.
311  //Opens, updates or creates database file if necessary
312  //(the database is automatically rebuilt if the source files are
313  //more recent than the last database file).
314  //
315  //If opt="update":
316  // close and delete database if already open
317  // regenerate database from source files
318  //Use this option to force the regeneration of the database.
319 
320  TString _opt(opt);
321  _opt.ToUpper();
322  if (_opt == "UPDATE") {
323  OpenDataBase(_opt.Data());
324  }
325  else {
326  OpenDataBase();
327  }
328  return fDataBase;
329 }
330 
331 
332 
353 
355 {
356  //Open the database for this dataset.
357  //If the database does not exist or is older than the source files
358  //the database is automatically rebuilt
359  //(see DataBaseNeedUpdate()).
360  //Use opt="UPDATE" to force rebuilding of the database.
361  //
362  //First, we look in to see if the database file exists
363  //(if no database file name given, use default name for database file defined in
364  //.rootrc config files).
365  //If so, we open the database contained in the file, after first loading the required plugin
366  //library if needed.
367  //
368  //The name of the dataset must correspond to the name of one of the Plugin.KVDataBase
369  //plugins defined in the .rootrc configuration files
370  //
371  //WARNING: if the database needs to be (re)built, we set gDataSet to
372  //point to this dataset in case it was not already done,
373  //as in order to (re)build the database it may be necessary for
374  //gDataSet to point to the current dataset.
375 
376  Bool_t is_glob_db = kFALSE;
377  //if option="update" or database out of date or does not exist, (re)build the database
378  if ((!strcmp(opt, "UPDATE")) || DataBaseNeedsUpdate()) {
379  //check if it is the currently active database (gDataBase),
380  //in which case we must 'cd()' to it after rebuilding
381  Info("OpenDataBase", "Updating database file");
382  fDataBaseUpdateInProgress = true;
383  is_glob_db = (fDataBase == gExpDB);
384  if (fDataBase) {
385  delete fDataBase;
386  fDataBase = 0;
387  }
388  // make sure gDataSet is set & points to us
389  gDataSet = const_cast<KVDataSet*>(this);
390  fDataBase = KVExpDB::MakeDataBase(GetDBName(), GetDataSetDir());
391  if (!fDataBase) {
392  // no database defined for dataset
393  Info("OpenDataBase", "No database defined for dataset");
394  return;
395  }
396  SaveDataBase();
397  if (fDataBase && is_glob_db) fDataBase->cd();
398  fDataBaseUpdateInProgress = false;
399  }
400  else if (!fDataBase) {
401  // if database is not in memory at this point, we need to
402  // open the database file and read in the database
403 
404  //load plugin for database
405  if (!LoadPlugin("KVExpDB", GetDBName())) {
406  Error("GetDataBase", "Cannot load required plugin library");
407  return;
408  }
409  //look for database file in dataset subdirectory
410  TString dbfile_fullpath = GetFullPathToDB();
411  //open database file
412  OpenDBFile(dbfile_fullpath.Data());
413  }
414 }
415 
416 
417 
418 
421 
423 {
424  //Print dataset information
425  cout << "Dataset name=" << GetName() << " (" << GetTitle() << ")";
426  if (IsAvailable()) {
427  cout << " [ AVAILABLE: ";
428  cout << fDatatypes.Data();
429  cout << "]";
430  }
431  else
432  cout << " [UNAVAILABLE]";
433  cout << endl;
434 }
435 
436 
437 
442 
443 void KVDataSet::Print(Option_t* opt) const
444 {
445  //Print dataset information
446  //If option string contains "tasks", print numbered list of tasks that can be performed
447  //If option string contains "data", print list of available data types
448 
449  TString Sopt(opt);
450  Sopt.ToUpper();
451  if (Sopt.Contains("TASK")) {
452  if (!GetNtasks()) {
453  cout << " *** No available analysis tasks ***"
454  << endl;
455  return;
456  }
457  else {
458  for (int i = 1; i <= GetNtasks(); i++) {
459  KVDataAnalysisTask* dat = GetAnalysisTask(i);
460  cout << "\t" << i << ". " << dat->GetTitle() << endl;
461  }
462  }
463  cout << endl;
464  }
465  else if (Sopt.Contains("DATA")) {
466  cout << "Available data types: " << fDatatypes.Data() << endl;
467  }
468  else {
469  ls(opt);
470  }
471 }
472 
473 
474 
493 
495 {
496  //Check if this data set is physically present and available for analysis.
497  //In other words we check if the value of GetDatapathSubdir() is a subdirectory
498  //of the given data repository
499  //If so, we proceed to check for the existence of any of the datatypes defined in
500  //
501  //KVDataSet.DataTypes:
502  //
503  //by checking for the associated sudirectories defined in the corresponding variables:
504  //
505  //KVDataSet.DataType.Subdir.[type]:
506  //
507  //If none of them exists, the dataset will be reset to 'unavailable'
508  //Otherwise the corresponding flags are set.
509  //
510  //Note that if SetUserGroups has been called with a list of groups allowed to read this data,
511  //the current user's name (gSystem->GetUserInfo()->fUser) will be used to check if the
512  //dataset is available. The user name must appear in the group defined by SetUserGroups.
513 
514  if (!fRepository) // for a stand-alone KVDataSetManager not linked to a KVDataRepository,
515  SetAvailable(); // all known datasets are 'available'
516  else
517  SetAvailable(fRepository->CheckSubdirExists(GetDataPathSubdir()));
518  if (!IsAvailable())
519  return;
520  //check subdirectories
521  KVString data_types = GetDataSetEnv("KVDataSet.DataTypes", "");
522  if (data_types == "") {
523  Warning("CheckAvailable", "No datatypes defined for this dataset: %s\nCheck value of KVDataSet.DataTypes or %s.KVDataSet.DataTypes",
524  GetName(), GetName());
525  SetAvailable(kFALSE);
526  }
527  fDatatypes = "";
528  // loop over data types
529  data_types.Begin(" ");
530  while (!data_types.End()) {
531  KVString type = data_types.Next(kTRUE);
532  if (!fRepository ||
533  (fRepository && fRepository->CheckSubdirExists(GetDataPathSubdir(), GetDataTypeSubdir(type.Data())))
534  ) {
535  AddAvailableDataType(type.Data());
536  }
537  }
538  //check at least one datatype exists
539  SetAvailable(fDatatypes != "");
540  //check user name against allowed groups
541  if (!CheckUserCanAccess()) {
542  SetAvailable(kFALSE);
543  return;
544  }
545 }
546 
547 
548 
550 
552 {
553  if (fDatatypes != "") fDatatypes += " ";
554  KVString _type = type;
555  _type.Remove(TString::kBoth, ' '); //strip whitespace
556  fDatatypes += _type;
557 }
558 
559 
560 
567 
569 {
570  // Add to fAllTasks list any data analysis task in list 'task_list'
571  //
572  // Add to fTasks list any data analysis task in list 'task_list' whose pre-requisite datatype is present for this dataset.
573  //
574  // Any dataset-specific "tweaking" of the task (including the prerequisite datatype) is done here.
575 
576  TString availables = gEnv->GetValue(Form("%s.DataAnalysisTask", GetName()), "");
577  fAllTasks.Clear();
578  fTasks.Clear();
579  TIter nxt(task_list);
580  KVDataAnalysisTask* dat;
581  while ((dat = (KVDataAnalysisTask*) nxt())) {
582  //make new copy of default analysis task
583  if (availables == "" || availables.Contains(dat->GetName())) {
584  KVDataAnalysisTask* new_task = new KVDataAnalysisTask(*dat);
585  //check if any dataset-specific parameters need to be changed
586  SetDataSetSpecificTaskParameters(new_task);
587  fAllTasks.Add(new_task);
588  // add tasks with available prerequisite data to fTasks
589  if (HasDataType(new_task->GetPrereq())) {
590  fTasks.Add(new_task);
591  }
592  }
593  }
594 }
595 
596 
597 
601 
603 {
604  //Returns the number of tasks associated to dataset which are compatible
605  //with the available data
606 
607  return fTasks.GetSize();
608 }
609 
610 
611 
616 
618 {
619  //Return kth analysis task in list of available tasks.
620  //k=[1, GetNtasks()] and corresponds to the number shown next to the title of the task when
621  //KVDataSet::Print("tasks") is called
622  return (KVDataAnalysisTask*) fTasks.At(k - 1);
623 }
624 
625 
626 
640 
641 std::unique_ptr<TList> KVDataSet::GetListOfAvailableSystems(const Char_t* datatype, KVDBSystem* systol)
642 {
643  //Create and fill a list of available systems for this dataset and the given datatype
644  //
645  //This uses the database associated to the dataset.
646  //
647  //For each system in the list we set the number of available runs : this number
648  //can be retrieved with KVDBSystem::GetNumberRuns()
649  //
650  //If systol!=0 then in fact the list contains a list of runs for the given system which are available.
651  //
652  //If no systems are defined for the dataset then we return a list of available runs
653  //for the given datatype
654 
655  //open the available runs file for the data type
656  if (!GetAvailableRunsFile(datatype)) {
657  Error("GetListOfAvailableSystems(const Char_t*)",
658  "No available runs file for type %s", datatype);
659  return 0;
660  }
661  return GetAvailableRunsFile(datatype)->GetListOfAvailableSystems(systol);
662 }
663 
664 
665 
679 
681 {
682  //Create and fill a list of available systems for this dataset and the prerequisite
683  //datatype for the given data analysis task.
684  //This uses the database associated to the dataset.
685  //USER MUST DELETE THE LIST AFTER USE.
686  //
687  //For each system in the list we set the number of available runs : this number
688  //can be retrieved with KVDBSystem::GetNumberRuns()
689  //
690  //If systol!=0 then in fact the list contains a list of runs for the given system which are available.
691  //
692  //If no systems are defined for the dataset then we return a list of available runs
693  //for the given datatype
694 
695  return GetListOfAvailableSystems(datan->GetPrereq(), systol);
696 }
697 
698 
699 
713 
714 void KVDataSet::SetName(const char* name)
715 {
716  // Set name of dataset.
717  // Also sets path to directory containing database informations
718  // for this dataset, i.e. list of runs, systems, calibration files etc.
719  // By default, just the name of the dataset is used, i.e.
720  // [DATADIR]/name
721  // (where DATADIR = path given by KVBase::GetDATADIRFilePath())
722  // However, if the variable
723  // [name].DataSet.Directory: [path]
724  // has been set, the value of [path] will be used.
725  // If [path] is an absolute path name, it will be used as such.
726  // If [path] is an incomplete or relative path, it will be prepended
727  // with [DATADIR]/
729  TString path = GetDataSetEnv("DataSet.Directory", name);
730  if (gSystem->IsAbsoluteFileName(path)) fCalibDir = path;
731  else {
732  // in this case (not an absolute path but just the name of another dataset)
733  // this dataset is an alias for another dataset.
734  fCalibDir = GetDATADIRFilePath(path);
735  // the name of the database object is the name of the "true" dataset
736  SetDBName(path);
737  }
738 }
739 
740 
741 
745 
747 {
748  //Returns full path to directory containing database and calibration/identification parameters etc.
749  //for this dataset.
750  return fCalibDir.Data();
751 }
752 
753 
754 
761 
762 void KVDataSet::cd() const
763 {
764  //Data analysis can only be performed if the data set in question
765  //is "activated" or "selected" using this method.
766  //At the same time, the data repository, dataset manager and database associated with
767  //this dataset also become the "active" ones (pointed to by the respective global
768  //pointers, gDataRepository, gDataBase, etc. etc.)
769 
770  gDataSet = const_cast<KVDataSet*>(this);
771  if (fRepository) fRepository->cd();
772  KVExpDB* db = GetDataBase();
773  if (db) db->cd();
774 }
775 
776 
777 
778 
783 
784 KVString KVDataSet::GetDataSetEnv(const Char_t* type, const Char_t* defval) const
785 {
786  //Will look for gEnv->GetValue "name_of_dataset.type"
787  //then simply "type" if no dataset-specific value is found.
788  //If neither resource is defined, return the "defval" default value (="" by default)
789 
790  return KVBase::GetDataSetEnv(GetName(), type, KVString(defval));
791 }
792 
793 
794 
795 
800 
802 {
803  //Will look for gEnv->GetValue "name_of_dataset.type"
804  //then simply "type" if no dataset-specific value is found.
805  //If neither resource is defined, return the "defval" default value
806 
807  return KVBase::GetDataSetEnv(GetName(), type, defval);
808 }
809 
810 
811 
812 
817 
818 Int_t KVDataSet::GetDataSetEnv(const Char_t* type, Int_t defval) const
819 {
820  //Will look for gEnv->GetValue "name_of_dataset.type"
821  //then simply "type" if no dataset-specific value is found.
822  //If neither resource is defined, return the "defval" default value
823 
824  return KVBase::GetDataSetEnv(GetName(), type, defval);
825 }
826 
827 
828 
829 
834 
835 Bool_t KVDataSet::GetDataSetEnv(const Char_t* type, Bool_t defval) const
836 {
837  //Will look for gEnv->GetValue "name_of_dataset.type"
838  //then simply "type" if no dataset-specific value is found.
839  //If neither resource is defined, return the "defval" default value
840 
841  return KVBase::GetDataSetEnv(GetName(), type, defval);
842 }
843 
844 
845 
846 
847 
875 
877 {
878  // Open file containing data of given datatype for given run number of this dataset.
879  //
880  // Returns a pointer to the opened file; if the file is not available, we return nullptr.
881  //
882  // The user must cast the returned pointer to the correct class, which will
883  // depend on the data type and the dataset (see `$KVROOT/KVFiles/.kvrootrc`)
884  //
885  // **SPECIAL CASE: MFM data with EBYEDAT frames**
886  //
887  // If the variable
888  //
889  //~~~~~~~~~~~~~~~~~~~~~~~~~
890  // [dataset].MFM.WithEbyedat: yes
891  //~~~~~~~~~~~~~~~~~~~~~~~~~
892  //
893  // is set, then we expect to find the necessary `ACTIONS_*` files in the dataset directory
894  // in subdirectory `ebyedat` (they should have the same names as the data files prefixed by
895  // `ACTIONS_[expname].CHC_PAR.`).
896  //
897  // If in addition the variable
898  //
899  //~~~~~~~~~~~~~~~~~~~~~~~~~
900  // [dataset].MFM.EbyedatActionsExpName: [expname]
901  //~~~~~~~~~~~~~~~~~~~~~~~~~
902  //
903  // is set, then we use the same `ACTIONS` file for all runs, with name `ACTIONS_[expname].CHC_PAR`
904 
905 
906  if (!strcmp(type, "raw") && !strcmp(GetDataSetEnv("MFM.WithEbyedat", ""), "yes")) {
907  TString ebydir = GetDataSetDir();
908  ebydir += "/ebyedat";
909  gEnv->SetValue("KVMFMDataFileReader.ActionsDirectory", ebydir);
910  if (strcmp(GetDataSetEnv("MFM.EbyedatActionsExpName", ""), ""))
911  gEnv->SetValue("KVMFMDataFileReader.ActionsExpName", GetDataSetEnv("MFM.EbyedatActionsExpName", ""));
912  TObject* f = GetRepository()->OpenDataSetRunFile(this, type, run, GetName());
913  // reset in case another dataset opens a raw MFM file without EBYEDAT data
914  gEnv->SetValue("KVMFMDataFileReader.ActionsDirectory", "");
915  gEnv->SetValue("KVMFMDataFileReader.ActionsExpName", "");
916  return f;
917  }
918  return GetRepository()->OpenDataSetRunFile(this, type, run, GetName());
919 }
920 
921 
922 
923 
930 
932  const run_index_t& run) const
933 {
934  //Return full path to file containing data of given datatype for given run number
935  //of this dataset. NB. only works for available run files, if their is no file in the repository for this run,
936  //the returned path will be empty.
937  //This path should be used with e.g. TChain::Add.
938 
939  //get name of file from available runs file
940  TString file("");
941  if (fRepository) file = GetRunfileName(type, run);
942  if (file == "")
943  return file.Data();
944  return fRepository->GetFullPathToOpenFile(this, type, file.Data());
945 }
946 
947 
948 
949 
956 
958 {
959  //Return name of file containing data of given datatype
960  //for given run number of this dataset.
961  //NB. only works for available run files, if there is no file in the repository for this run,
962  //the returned path will be empty.
963 
964  //check data type is available
965  if (!HasDataType(type)) {
966  Error("GetRunfileName",
967  "No data of type \"%s\" available for dataset %s", (const char*)type,
968  GetName());
969  return 0;
970  }
971  //get name of file from available runs file
972  return GetAvailableRunsFile(type)->GetFileName(run);
973 }
974 
975 
976 
977 
984 
986 {
987  //Return date of file containing data of given datatype
988  //for given run number of this dataset.
989  //NB. only works for available run files, if there is no file in the repository for this run,
990  //an error will be printed and the returned data is set to "Sun Jan 1 00:00:00 1995"
991  //(earliest possible date for TDatime class).
992 
993  static TDatime date;
994  date.Set(1995, 1, 1, 0, 0, 0);
995  //check data type is available
996  if (!HasDataType(type)) {
997  Error("GetRunfileDate",
998  "No data of type \"%s\" available for dataset %s", (const char*)type,
999  GetName());
1000  return date;
1001  }
1002  //get date of file from available runs file
1003  TString filename;
1004  if (!GetAvailableRunsFile(type)->GetRunInfo(run, date, filename)) {
1005  Error("GetRunfileDate",
1006  "Runfile not found for run %d index %d (data type: %s)", run.run(), run.index(), (const char*)type);
1007  }
1008  return date;
1009 }
1010 
1011 
1012 
1013 
1018 
1020 {
1021  //We check the availability of the run by looking in the available runs file associated
1022  //with the given datatype.
1023 
1024  //check data type is available
1025  if (!HasDataType(type)) {
1026  Error("CheckRunfileAvailable",
1027  "No data of type \"%s\" available for dataset %s", (const char*)type,
1028  GetName());
1029  return 0;
1030  }
1031  return GetAvailableRunsFile(type)->CheckAvailable(run);
1032 }
1033 
1034 
1035 
1036 
1051 
1052 const Char_t* KVDataSet::GetBaseFileName(const Char_t* type, const run_index_t& run) const
1053 {
1054  //PRIVATE METHOD: Returns base name of data file containing data for the run of given datatype.
1055  //The filename corresponds to one of the formats defined in $KVROOT/KVFiles/.kvrootrc
1056  //by variables like:
1057  //
1058  //~~~
1059  //[dataset].DataSet.RunFileName.[type]: run%R.dat
1060  //~~~
1061  //
1062  //%R will be replaced with the run number
1063  //
1064  //IF the format contains '%D' it will be replaced with the current date and time
1065  //
1066  // Any index will be appended at the end: ".index"
1067 
1068  static TString tmp;
1069  //get format string
1070  TString fmt = GetDataSetEnv(Form("DataSet.RunFileName.%s", type));
1071  TString run_num(Form("%d", run.run()));
1072  KVDatime now;
1073  TString date(now.AsSQLString());
1074  tmp = fmt;
1075  tmp.ReplaceAll("%R", run_num);
1076  if (fmt.Contains("%D")) {
1077  tmp.ReplaceAll("%D", date);
1078  }
1079  if (run.has_index()) tmp += Form(".%d", run.index());
1080  return tmp.Data();
1081 }
1082 
1083 
1084 
1085 
1089 
1091 {
1092  //Update list of available runs for given data 'type'
1093 
1094  //check data type is available
1095  if (!HasDataType(type)) {
1096  Error("UpdateAvailableRuns",
1097  "No data of type \"%s\" available for dataset %s", (const char*)type,
1098  GetName());
1099  }
1100  KVAvailableRunsFile* a = GetAvailableRunsFile(type);
1101  a->Update();
1102 }
1103 
1104 
1105 
1106 
1111 
1113 {
1114  // Create a new runfile for the dataset of given datatype.
1115  // (only if this dataset is associated with a data repository)
1116  // Once the file has been filled, use CommitRunfile to submit it to the repository.
1117 
1118  if (!fRepository) return nullptr;
1119  TString tmp = GetBaseFileName(type, run);
1120  //turn any spaces into "_"
1121  tmp.ReplaceAll(" ", "_");
1122  return fRepository->CreateNewFile(this, type, tmp.Data());
1123 }
1124 
1125 
1126 
1127 
1136 
1137 void KVDataSet::DeleteRunfile(const KVString& type, const run_index_t& run, Bool_t confirm)
1138 {
1139  // Delete the file for the given run/index of data type "type" from the repository.
1140  // By default, confirm=kTRUE, which means that the user will be asked to confirm
1141  // that the file should be deleted. If confirm=kFALSE, no confirmation will be asked
1142  // for and the file will be deleted straight away.
1143  //
1144  // WARNING: this really does DELETE files in the repository, they cannot be
1145  // retrieved once they have been deleted.
1146 
1147  if (!fRepository) return;
1148 
1149  //get name of file to delete
1150  TString filename = GetAvailableRunsFile(type)->GetFileName(run);
1151  if (filename == "") {
1152  Error("DeleteRunfile", "Run %s of type %s does not exist.",
1153  run.as_string().Data(), (const char*)type);
1154  return;
1155  }
1156  //delete file
1157  //prevent accidental deletion of certain types of runfiles
1158  KVString doNotDelete = GetDataSetEnv("DataSet.RunFile.DoNotDelete", "all");
1159  if (doNotDelete == "all" || doNotDelete.Contains(type)) {
1160  Error("DeleteRunFile", "%s files cannot be deleted", (const char*)type);
1161  return;
1162  }
1163  fRepository->DeleteFile(this, type, filename.Data(), confirm);
1164  //was file deleted ? if so, remove entry from available runs file
1165  if (!fRepository->CheckFileStatus(this, type, filename.Data()))
1166  GetAvailableRunsFile(type)->Remove(run);
1167 }
1168 
1169 
1170 
1171 
1183 
1184 void KVDataSet::DeleteRunfiles(const Char_t* type, const run_index_list& nl, Bool_t confirm)
1185 {
1186  // Delete files corresponding to a list of runs/index of data type "type" from the repository.
1187  //
1188  // By default, confirm=kTRUE, which means that the user will be asked to confirm
1189  // that each file should be deleted.
1190  //
1191  // If confirm=kFALSE, no confirmation will be asked for and the file will be deleted straight away.
1192  //
1193  // if "nl" is empty (default value) all runs of the dataset corresponding to the given type will be deleted
1194  //
1195  // WARNING: this really does DELETE files in the repository, they cannot be retrieved once they have been deleted.
1196 
1197  auto NL = nl;
1198  if (NL.IsEmpty()) NL = GetRunList(type);
1199  if (NL.IsEmpty()) return;
1200  for (auto& r : NL)
1201  DeleteRunfile(type, r, confirm);
1202 }
1203 
1204 
1205 
1206 
1214 
1215 run_index_list KVDataSet::GetRunList_DateSelection(const Char_t* type, TDatime* min, TDatime* max)
1216 {
1217  // Prints out and returns list of runs after date / time selection
1218  //
1219  // Runs generated between ]min;max[ are selected
1220  // - if min=NULL runs with date <max are selected
1221  // - if max=NULL runs with date >min are selected
1222  // - if max and min are NULL returns empty list
1223 
1224  if (!min && !max) return {};
1225 
1226  if (min) printf("date minimum %s\n", min->AsString());
1227  if (max) printf("date maximum %s\n", max->AsString());
1228 
1229  run_index_list numb;
1230 
1231  auto ll = GetListOfAvailableSystems(type);
1232  KVDBSystem* sys = 0;
1233  KVRunFile* run = 0;
1234  for (Int_t nl = 0; nl < ll->GetEntries(); nl += 1) {
1235  sys = (KVDBSystem*)ll->At(nl);
1236  auto lrun = GetListOfAvailableSystems(type, sys);
1237  auto oldList = numb;
1238  for (Int_t nr = 0; nr < lrun->GetEntries(); nr += 1) {
1239  run = (KVRunFile*)lrun->At(nr);
1240 
1241  if (min && max) {
1242  if (*min < run->GetFileWrittenDatime() && run->GetFileWrittenDatime() < *max) {
1243  numb.Add(run->GetRunIndex());
1244  }
1245  }
1246  else if (min) {
1247  if (*min < run->GetFileWrittenDatime()) {
1248  numb.Add(run->GetRunIndex());
1249  }
1250  }
1251  else if (max) {
1252  if (run->GetFileWrittenDatime() < *max) {
1253  numb.Add(run->GetRunIndex());
1254  }
1255  }
1256  }
1257  // print runs for system if any
1258  if (numb.GetEntries() > oldList.GetEntries())
1259  printf("%s : %s\n", sys->GetName(), (numb - oldList).AsString().Data());
1260  }
1261  return numb;
1262 
1263 }
1264 
1265 
1266 
1267 
1276 
1277 run_index_list KVDataSet::GetRunList_StageSelection(const Char_t* type, const Char_t* ref_type, KVDBSystem* system, Bool_t OnlyCol)
1278 {
1279  // Returns list of runs which are present for data type "base_type" but not for "other_type"
1280  //
1281  // if type is NULL or ="" returns empty KVNumberList
1282  //
1283  // If pointer to system is given, only runs for the system are considered.
1284  //
1285  // If OnlyCol=kTRUE (kFALSE default) only systems with KVDBSystem::IsCollision()=kTRUE are considered
1286 
1287  run_index_list manquant;
1288  auto ll = GetListOfAvailableSystems(ref_type);
1289  if (!ll || !ll->GetEntries()) {
1290  //numb.Clear();
1291  Info("GetRunList_StageSelection", "No data available of type \"%s\"", ref_type);
1292  return manquant;
1293  }
1294  if (system && !ll->FindObject(system)) {
1295  Info("GetRunList_StageSelection", "No data available of type \"%s\" for system %s", ref_type, system->GetName());
1296  return manquant;
1297  }
1298 
1299  Info("GetRunList_StageSelection", "Liste des runs presents dans \"%s\" mais absent dans \"%s\"", ref_type, type);
1300 
1301  KVDBSystem* sys = 0;
1302 
1303  for (Int_t nl = 0; nl < ll->GetEntries(); nl += 1) {
1304 
1305  sys = (KVDBSystem*)ll->At(nl);
1306  if (system && sys != system) continue;
1307  if (OnlyCol && !sys->IsCollision()) continue;
1308  auto nsys = GetRunList(type, sys);
1309  auto nsys_ref = GetRunList(ref_type, sys);
1310  Int_t nref = nsys_ref.GetNValues();
1311 
1312  nsys_ref.Remove(nsys);
1313 
1314  Info("GetRunList_StageSelection", "\nKVDBSystem : %s --> %d runs manquants sur %d : %s",
1315  sys->GetName(),
1316  nsys_ref.GetNValues(),
1317  nref,
1318  nsys_ref.AsString().Data()
1319  );
1320  manquant.Add(nsys_ref);
1321  }
1322  return manquant;
1323 }
1324 
1325 
1326 
1330 
1331 run_index_list KVDataSet::GetRunList_VersionSelection(const Char_t* type, const Char_t* version, KVDBSystem* sys)
1332 {
1333  // Returns list of runs of given type that were created with the given version of KaliVeda.
1334  // If system!="" then only runs for the given system are considered
1335 
1336  run_index_list runs;
1337  if (sys) {
1338  unique_ptr<TList> lrun(GetListOfAvailableSystems(type, sys));
1339  TIter next(lrun.get());
1340  KVRunFile* run;
1341  while ((run = (KVRunFile*)next())) {
1342  if (!strcmp(run->GetVersion(), version)) runs.Add(run->GetRunIndex());
1343  }
1344  return runs;
1345  }
1346  unique_ptr<TList> ll(GetListOfAvailableSystems(type));
1347  if (!ll.get() || !ll->GetEntries()) {
1348  //numb.Clear();
1349  Info("GetRunList_VersionSelection", "No data available of type \"%s\"", type);
1350  return runs;
1351  }
1352  Int_t nsys = ll->GetEntries();
1353  for (Int_t nl = 0; nl < nsys; nl += 1) {
1354  sys = (KVDBSystem*)ll->At(nl);
1355  unique_ptr<TList> lrun(GetListOfAvailableSystems(type, sys));
1356  TIter next(lrun.get());
1357  KVRunFile* run;
1358  while ((run = (KVRunFile*)next())) {
1359  if (!strcmp(run->GetVersion(), version)) runs.Add(run->GetRunIndex());
1360  }
1361  }
1362  return runs;
1363 }
1364 
1365 
1366 
1371 
1372 void KVDataSet::CommitRunfile(const KVString& type, const run_index_t& run, TFile* file)
1373 {
1374  // Commit a runfile previously created with NewRunfile() to the repository.
1375  // Any previous version of the runfile will be deleted.
1376  // The available runs list for this data 'type' is updated.
1377 
1378  if (!fRepository) return;
1379 
1380  //keep name of file for updating available runs list
1381  TString newfile = gSystem->BaseName(file->GetName());
1382 
1383  fRepository->CommitFile(file, type, this);
1384  //update list of available datatypes of dataset,
1385  //in case this addition has created a new subdirectory
1386  CheckAvailable();
1387  //check if previous version of file exists
1388  //get name of file from available runs file
1389  //note that when the file is the first of a new subdirectory, GetAvailableRunsFile->GetFileName
1390  //will cause the available runs file to be created, and it will contain one entry:
1391  //the new file!
1392  TString oldfile = GetAvailableRunsFile(type)->GetFileName(run);
1393  if (oldfile != "" && oldfile != newfile) {
1394  //delete previous version - no confirmation
1395  fRepository->DeleteFile(this, type, oldfile.Data(),
1396  kFALSE);
1397  //was file deleted ? if so, remove entry from available runs file
1398  if (!fRepository->CheckFileStatus(this, type, oldfile.Data()))
1399  GetAvailableRunsFile(type)->Remove(run);
1400  }
1401  if (oldfile != newfile) {
1402  //add entry for new run in available runs file
1403  GetAvailableRunsFile(type)->Add(run, newfile.Data());
1404  }
1405 }
1406 
1407 
1408 
1409 
1415 
1417 {
1418  //if fUserGroups has been set with SetUserGroups(), we check that the current user's name
1419  //(gSystem->GetUserInfo()->fUser) appears in at least one of the groups in the list.
1420  //Returns kFALSE if user's name is not found in any of the groups.
1421  //if fUserGroups="" (default), we return kTRUE for all users.
1422 
1423  if (fUserGroups == "")
1424  return kTRUE; /* no groups set, all users have access */
1425 
1426  //split into array of group names
1427  unique_ptr<TObjArray> toks(fUserGroups.Tokenize(' '));
1428  TObjString* group_name;
1429  TIter next_name(toks.get());
1430  while ((group_name = (TObjString*) next_name())) {
1431  //for each group_name, we check if the user's name appears in the group
1432  if (!fRepository || (fRepository && fRepository->GetDataSetManager()->
1433  CheckUser(group_name->String().Data()))
1434  ) {
1435  return kTRUE;
1436  }
1437  }
1438  return kFALSE;
1439 }
1440 
1441 
1442 
1443 
1446 
1448 {
1449  //Set pointer to data repository in which dataset is stored
1450  fRepository = dr;
1451 }
1452 
1453 
1454 
1455 
1458 
1460 {
1461  //Get pointer to data repository in which dataset is stored
1462  return fRepository;
1463 }
1464 
1465 
1466 
1467 
1472 
1474 {
1475  //Check all runs for a given datatype and make sure that only one version
1476  //exists for each runfile. If not, we print a report on the runfiles which occur
1477  //multiple times, with the associated date and file name.
1478 
1479  auto doubles = GetAvailableRunsFile(data_type)->CheckMultiRunfiles();
1480  if (doubles.empty()) {
1481  cout << "OK. No runs appear more than once." << endl;
1482  }
1483  else {
1484  cout << "Runs which appear more than once: " << endl << endl;
1485  //print dates and filenames for each run
1486 
1487  for (auto& rr : doubles) {
1488  KVList filenames, dates;
1489 
1490  //get infos for current run
1491  GetAvailableRunsFile(data_type)->GetRunInfos(rr, &dates, &filenames);
1492 
1493  cout << "Run " << rr << " : " << dates.GetEntries() << " files >>>>>>" << endl;
1494  for (int i = 0; i < dates.GetEntries(); i++) {
1495 
1496  cout << "\t" << ((TObjString*) filenames.At(i))->String().
1497  Data() << "\t" << ((TObjString*) dates.At(i))->String().
1498  Data() << endl;
1499 
1500  }
1501  }
1502  }
1503 }
1504 
1505 
1506 
1507 
1516 
1517 void KVDataSet::CleanMultiRunfiles(const Char_t* data_type, Bool_t confirm)
1518 {
1519  // Check all runs for a given datatype and make sure that only one version
1520  // exists for each run. If not, we print a report on the runfiles which occur
1521  // multiple times, with the associated date and file name, and then we
1522  // destroy all but the most recent version of the file in the repository, and
1523  // update the runlist accordingly.
1524  // By default, we ask for confirmation before deleting each file.
1525  // Call with confirm=kFALSE to delete WITHOUT CONFIRMATION (DANGER!! WARNING!!!)
1526 
1527  if (!fRepository) return;
1528 
1529  KVAvailableRunsFile* ARF = GetAvailableRunsFile(data_type);
1530  auto doubles = ARF->CheckMultiRunfiles();
1531  if (doubles.empty()) {
1532  cout << "OK. No runs appear more than once." << endl;
1533  }
1534  else {
1535  cout << "Runs which appear more than once: " << endl << endl;
1536  //print dates and filenames for each run
1537 
1538  KVList filenames, dates;
1539  for (auto& rr : doubles) {
1540  //get infos for current run
1541  ARF->GetRunInfos(rr, &dates, &filenames);
1542  TDatime most_recent("1998-12-25 00:00:00");
1543  Int_t i_most_recent = 0;
1544  cout << "Run " << rr << " : " << dates.GetEntries() << " files >>>>>>" << endl;
1545  for (int i = 0; i < dates.GetEntries(); i++) {
1546  //check if run is most recent
1547  TDatime rundate(((TObjString*) dates.At(i))->String().Data());
1548  if (rundate > most_recent) {
1549  most_recent = rundate;
1550  i_most_recent = i;
1551  }
1552  }
1553  //Now, we loop over the list again, this time we destroy all but the most recent
1554  //version of the runfile
1555  for (int i = 0; i < dates.GetEntries(); i++) {
1556  if (i == i_most_recent) {
1557  cout << "KEEP : ";
1558  }
1559  else {
1560  cout << "DELETE : ";
1561  }
1562  cout << "\t" << ((TObjString*) filenames.At(i))->String().
1563  Data() << "\t" << ((TObjString*) dates.At(i))->String().
1564  Data() << endl;
1565  if (i != i_most_recent) {
1566  //delete file from repository forever and ever
1567  fRepository->DeleteFile(this, data_type,
1568  ((TObjString*) filenames.At(i))->
1569  String().Data(), confirm);
1570  //remove file entry from available runlist
1571  ARF->Remove(rr,
1572  ((TObjString*) filenames.At(i))->String());
1573  }
1574  }
1575  }
1576  }
1577 }
1578 
1579 
1580 
1581 
1587 
1589  KVDataRepository* other_repos)
1590 {
1591  //Use this method to check whether the file of type "data_type" for run number "run"
1592  //in the data repository "other_repos" is more recent than the file contained in the data
1593  //repository corresponding to this dataset.
1594  //Returns kFALSE if file in other repository is more recent.
1595 
1596  if (!other_repos)
1597  return kTRUE;
1598  //get dataset with same name as this one from dataset manager of other repository
1599  KVDataSet* ds = other_repos->GetDataSetManager()->GetDataSet(GetName());
1600  if (!ds) {
1601  Error("CheckRunfileUpToDate",
1602  "Dataset \"%s\" not found in repository \"%s\"", GetName(),
1603  other_repos->GetName());
1604  return kFALSE;
1605  }
1606  //compare dates of the two runfiles
1607  if (GetRunfileDate(data_type, run) < ds->GetRunfileDate(data_type, run))
1608  return kFALSE;
1609  return kTRUE;
1610 }
1611 
1612 
1613 
1614 
1621 
1623  const KVString& other_repos)
1624 {
1625  //Use this method to check whether the file of type "data_type" for run number "run"
1626  //in the data repository "other_repos" is more recent than the file contained in the data
1627  //repository corresponding to this dataset.
1628  //Returns kTRUE if no repository with name "other_repos" exists.
1629  //Returns kFALSE if file in other repository is more recent.
1630 
1631  KVDataRepository* _or =
1632  gDataRepositoryManager->GetRepository(other_repos);
1633  if (_or)
1634  return CheckRunfileUpToDate(data_type, run, _or);
1635  Error("CheckRunfileUpToDate",
1636  "No data repository known with this name : %s", (const char*) other_repos);
1637  return kTRUE;
1638 }
1639 
1640 
1641 
1642 
1646 
1647 void KVDataSet::CheckUpToDate(const Char_t* data_type,
1648  const Char_t* other_repos)
1649 {
1650  //Check whether all files of type "data_type" for run number "run" in the data repository
1651  //are up to date (i.e. at least as recent) as compared to the files in data repository "other_repos".
1652 
1653  if (!fRepository) return;
1654 
1655  KVDataRepository* _or =
1656  gDataRepositoryManager->GetRepository(other_repos);
1657  if (!_or) {
1658  Error("CheckUpToDate",
1659  "No data repository known with this name : %s", other_repos);
1660  return;
1661  }
1662  auto runlist = GetAvailableRunsFile(data_type)->GetRunList();
1663  Int_t need_update = 0;
1664  for (auto& rr : runlist) {
1665  //check run
1666  if (!CheckRunfileUpToDate(data_type, rr, _or)) {
1667  cout << " *** run " << rr << " needs update ***" <<
1668  endl;
1669  cout << "\t\tREPOSITORY: " << fRepository->
1670  GetName() << "\tDATE: " << GetRunfileDate(data_type,
1671  rr).
1672  AsString() << endl;
1673  cout << "\t\tREPOSITORY: " << other_repos << "\tDATE: " << _or->
1674  GetDataSetManager()->GetDataSet(GetName())->
1675  GetRunfileDate(data_type,
1676  rr).AsString() << endl;
1677  need_update++;
1678  }
1679  }
1680  if (!need_update) {
1681  cout << " *** All runfiles are up to date for data type " <<
1682  data_type << endl;
1683  }
1684 }
1685 
1686 
1687 
1688 
1692 
1693 run_index_list KVDataSet::GetUpdatableRuns(const Char_t* data_type,
1694  const Char_t* other_repos)
1695 {
1696  //Returns list of all runs of type "data_type" which may be updated
1697  //from the repository named "other_repos". See CheckUpToDate().
1698 
1699  run_index_list updates;
1700  if (!fRepository) return updates;
1701 
1702  KVDataRepository* _or =
1703  gDataRepositoryManager->GetRepository(other_repos);
1704  if (!_or) {
1705  Error("CheckUpToDate",
1706  "No data repository known with this name : %s", other_repos);
1707  return updates;
1708  }
1709  auto runlist = GetAvailableRunsFile(data_type)->GetRunList();
1710  for (auto& rr : runlist) {
1711  //check run
1712  if (!CheckRunfileUpToDate(data_type, rr, _or)) {
1713  //run is out of date
1714  updates.Add(rr);
1715  }
1716  }
1717  return updates;
1718 }
1719 
1720 
1721 
1722 
1727 
1728 run_index_list KVDataSet::GetRunList(const Char_t* data_type,
1729  const KVDBSystem* system) const
1730 {
1731  //Returns list of all files available for given "data_type"
1732  //
1733  //If a pointer to a reaction system is given, only files for the given system will be included in the list.
1734 
1735  if (!fRepository || !HasDataType(data_type)) {
1736  Error("GetRunList",
1737  "No data of type %s available. Runlist will be empty.",
1738  data_type);
1739  return {};
1740  }
1741 
1742  return GetAvailableRunsFile(data_type)->GetRunList(system);
1743 }
1744 
1745 
1746 
1747 
1778 
1780 {
1781  //This method returns a pointer to the available analysis task whose description (title) contains
1782  //all of the whitespace-separated keywords (which may be regular expressions)
1783  //given in the string "keywords". The comparison is case-insensitive.
1784  //
1785  //WARNING: this method can only be used to access analysis tasks that are
1786  //available for this dataset, i.e. for which the corresponding prerequisite data type
1787  //is available in the repository.
1788  //For unavailable data/tasks, use GetAnalysisTaskAny(const Char_t*).
1789  //
1790  //EXAMPLES
1791  //Let us suppose that the current dataset has the following list of tasks:
1792  //~~~
1793  // root [2] gDataSet->Print("tasks")
1794  // 1. Event reconstruction from raw data (raw->recon)
1795  // 2. Analysis of raw data
1796  // 3. Identification of reconstructed events (recon->ident)
1797  // 4. Analysis of reconstructed events (recon)
1798  // 5. Analysis of partially identified & calibrated reconstructed events (ident)
1799  // 6. Analysis of fully calibrated physical data (root)
1800  //~~~
1801  //Then the following will occur:
1802  //~~~
1803  // root [14] gDataSet->GetAnalysisTask("raw->recon")->Print()
1804  // KVDataAnalysisTask : Event reconstruction from raw data (raw->recon)
1805  //
1806  // root [10] gDataSet->GetAnalysisTask("analysis root")->Print()
1807  // KVDataAnalysisTask : Analysis of fully calibrated physical data (root)
1808  //~~~
1809 
1810  //case-insensitive search for matches in list based on 'title' attribute
1811  return (KVDataAnalysisTask*)fTasks.FindObjectAny("title", keywords, kTRUE, kFALSE);
1812 }
1813 
1814 
1815 
1816 
1829 
1830 void KVDataSet::MakeAnalysisClass(const Char_t* task, const Char_t* classname)
1831 {
1832  //Create a skeleton analysis class to be used for analysis of the data belonging to this dataset.
1833  //
1834  // task = keywords contained in title of analysis task (see GetAnalysisTask(const Char_t*))
1835  // (you do not need to include 'analysis', it is added automatically)
1836  // classname = name of new analysis class
1837  //
1838  //Example:
1839  // MakeAnalysisClass("raw", "MyRawDataAnalysis")
1840  // --> make skeleton raw data analysis class in files MyRawDataAnalysis.cpp & MyRawDataAnalysis.h
1841  // MakeAnalysisClass("fully calibrated", "MyDataAnalysis")
1842  // --> make skeleton data analysis class in files MyDataAnalysis.cpp & MyDataAnalysis.h
1843 
1844  KVString _task = task;
1845  if (!_task.Contains("nalysis")) _task += " analysis";
1846  //We want to be able to write analysis classes even when we don't have any data
1847  //to analyse. Therefore we use GetAnalysisTaskAny.
1848  auto dat = GetAnalysisTaskAny(_task.Data());
1849  if (!dat) {
1850  Error("MakeAnalysisClass",
1851  "called for unknown or unavailable analysis task : %s", _task.Data());
1852  return;
1853  }
1854  if (!dat->WithUserClass()) {
1855  Error("MakeAnalysisClass",
1856  "no user analysis class for analysis task : %s", dat->GetTitle());
1857  return;
1858  }
1859 
1860  //all analysis base classes must define a static Make(const Char_t * classname)
1861  //which generates the skeleton class files.
1862 
1863  TClass* cl = nullptr;
1864  //has the user base class for the task been compiled and loaded ?
1865  if (dat->CheckUserBaseClassIsLoaded()) cl = TClass::GetClass(dat->GetUserBaseClass());
1866  else
1867  return;
1868 
1869  //set up call to static Make method
1870  unique_ptr<TMethodCall> methcall(new TMethodCall(cl, "Make", Form("\"%s\"", classname)));
1871 
1872  if (!methcall->IsValid()) {
1873  Error("MakeAnalysisClass", "static Make(const Char_t*) method for class %s is not valid",
1874  cl->GetName());
1875  return;
1876  }
1877 
1878  //generate skeleton class
1879  methcall->Execute();
1880 }
1881 
1882 
1883 
1884 
1888 
1889 Bool_t KVDataSet::OpenDataSetFile(const Char_t* filename, ifstream& file)
1890 {
1891  // Look for (and open for reading, if found) the named file in the directory which
1892  // contains the files for this dataset (given by GetDataSetDir())
1893 
1894  return OpenDataSetFile(GetName(), filename, file);
1895 }
1896 
1897 
1898 
1902 
1903 Bool_t KVDataSet::OpenDataSetFile(const TString& dataset, const Char_t* filename, ifstream& file)
1904 {
1905  // Static method to look for (and open for reading, if found) the named file in the directory which
1906  // contains the files for the dataset
1907 
1908  TString datasetdir = KVBase::GetDataSetEnv(dataset, "DataSet.Directory", dataset);
1909  if (gSystem->IsAbsoluteFileName(datasetdir)) {
1910  // dataset directory is outside of standard KV installation directories
1911  // use absolute path to search for file
1912  TString abspath;
1913  abspath.Form("%s/%s", datasetdir.Data(), filename);
1914  return SearchAndOpenKVFile(abspath, file);
1915  }
1916  // dataset directory is a subdirectory of GetDATADIRFilePath()
1917  return SearchAndOpenKVFile(filename, file, datasetdir);
1918 }
1919 
1920 
1921 
1925 
1927 {
1928  // Find a file in the dataset directory (given by GetDataSetDir())
1929  // Returns full path to file if found, empty string if not
1930 
1931  return GetFullPathToDataSetFile(GetName(), filename);
1932 }
1933 
1934 
1935 
1939 
1941 {
1942  // Static method to find a file in the dataset directory (given by GetDataSetDir())
1943  // Returns full path to file if found, empty string if not
1944 
1945  TString fullpath;
1946  TString datasetdir = KVBase::GetDataSetEnv(dataset, "DataSet.Directory", dataset);
1947  if (!SearchKVFile(filename, fullpath, datasetdir)) {
1948  ::Warning("KVDataSet::GetFullPathToDataSetFile", "File %s not found in dataset subdirectory %s", filename, datasetdir.Data());
1949  fullpath = "";
1950  }
1951  return fullpath;
1952 }
1953 
1954 
1955 
1959 
1960 Bool_t KVDataSet::FindDataSetFile(const TString& dataset, const Char_t* filename)
1961 {
1962  // Static method to find a file in the dataset directory (given by GetDataSetDir())
1963  // Returns kTRUE if found, kFALSE if not
1964 
1965  TString fullpath;
1966  TString datasetdir = KVBase::GetDataSetEnv(dataset, "DataSet.Directory", dataset);
1967  return SearchKVFile(filename, fullpath, datasetdir);
1968 }
1969 
1970 
1971 
1975 
1977 {
1978  // Find a file in the dataset directory (given by GetDataSetDir())
1979  // Returns kTRUE if found, kFALSE if not
1980 
1981  return FindDataSetFile(GetName(), filename);
1982 }
1983 
1984 
1985 
1986 
1995 
1997 {
1998  //This method returns the analysis task whose description (title) contains
1999  //all of the whitespace-separated keywords (which may be regular expressions)
2000  //given in the string "keywords". The comparison is case-insensitive.
2001  //The analysis task does not need to be "available", i.e. the associated prerequisite
2002  //data type does not have to be present in the repository (see GetAnalysisTask).
2003  //
2004  // If no task is found, returns nullptr
2005 
2006  KVDataAnalysisTask* tsk = (KVDataAnalysisTask*)fAllTasks.FindObjectAny("title", keywords, kTRUE, kFALSE);
2007  if (!tsk) {
2008  Error("GetAnalysisTaskAny", "No task found with the following keywords in its title : %s", keywords);
2009  }
2010  return tsk;
2011 }
2012 
2013 
2014 
2015 
2021 
2023 {
2024  // Returns kTRUE if database needs to be regenerated from source files,
2025  // i.e. if source files are more recent than DataBase.root
2026  // In case no directory exists for dataset (dataset added 'on the fly')
2027  // we create the directory and fill it with dummy files (Makefile, Runlist.csv, Systems.dat)
2028 
2029  TString pwd = gSystem->pwd();
2030 
2031  TString path = "";
2032  if (!SearchKVFile(GetDataSetDir(), path)) {
2033  // dataset directory doesn't exist - create it
2034  Info("DataBaseNeedsUpdate", "%s: Creating new dataset directory %s",
2035  GetName(), GetDataSetDir());
2036  if (gSystem->mkdir(GetDataSetDir())) {
2037  // problem creating directory
2038  Error("DataBaseNeedsUpdate",
2039  "%s: Dataset directory %s does not exist and cannot be created ?",
2040  GetName(), GetDataSetDir());
2041  return kFALSE;
2042  }
2043  // create dummy files
2044  SearchKVFile(GetDataSetDir(), path); // get full path
2045  path += "/";
2046  TString filename = path + "Makefile";
2047  ofstream of1(filename.Data());
2048  of1 << "$(KV_WORK_DIR)/db/" << GetName() << "/DataBase.root : Runlist.csv Systems.dat" << endl;
2049  of1 << "\t@echo Database needs update" << endl;
2050  of1.close();
2051  filename = path + "Runlist.csv";
2052  ofstream of2(filename.Data());
2053  of2 << "# Automatically generated dummy Runlist.csv file" << endl;
2054  of2.close();
2055  filename = path + "Systems.dat";
2056  ofstream of3(filename.Data());
2057  of3 << "# Automatically generated dummy Systems.dat file" << endl;
2058  of3.close();
2059  }
2060  gSystem->cd(GetDataSetDir());
2061  TString cmd = "make -q";
2062  Int_t ret = gSystem->Exec(cmd.Data());
2063  gSystem->cd(pwd.Data());
2064  return (ret != 0);
2065 }
2066 
2067 
2068 
2085 
2087 {
2088  // Returns name of output repository for given task.
2089  // By default it is the name of the repository associated with this dataset,
2090  // but can be changed by the following environment variables:
2091  //
2092  // [repository].DefaultOutputRepository: [other repository]
2093  // - this means that all tasks carried out on data in [repository]
2094  // will have their output files placed in [other repository]
2095  //
2096  // [taskname].DataAnalysisTask.OutputRepository: [other repository]
2097  // - this means that for [taskname], any output files will
2098  // be placed in [other repository]
2099  //
2100  // [dataset].[taskname].DataAnalysisTask.OutputRepository: [other repository]
2101  // - this means that for given [dataset] & [taskname],
2102  // any output files will be placed in [other repository]
2103 
2104  if (gEnv->Defined(Form("%s.DataRepository.DefaultOutputRepository", GetRepository()->GetName())))
2105  return TString(gEnv->GetValue(Form("%s.DataRepository.DefaultOutputRepository", GetRepository()->GetName()), ""));
2106  TString orep = GetDataSetEnv(Form("%s.DataAnalysisTask.OutputRepository", taskname), GetRepository()->GetName());
2107  return orep;
2108 }
2109 
2110 
2111 
2112 
2115 
2116 void KVDataSet::CopyRunfilesFromRepository(const Char_t* type, const run_index_list& runs, const Char_t* destdir)
2117 {
2118  // Copies the runfiles of given "type" into the local directory "destdir".
2119 
2120  KVDataRepository* repo = GetRepository();
2121  for (auto& run : runs) {
2122  TString filename = GetRunfileName(type, run);
2123  TString destpath;
2124  AssignAndDelete(destpath, gSystem->ConcatFileName(destdir, filename));
2125  repo->CopyFileFromRepository(this, type, filename, destpath);
2126  }
2127 }
2128 
2129 
2130 
2131 
2135 
2136 void KVDataSet::CopyRunfilesToRepository(const Char_t* type, const run_index_list& runs, const Char_t* destrepo)
2137 {
2138  // Copies the runfiles of given "type" from the data repository associated
2139  // with this dataset into the local repository "destrepo".
2140 
2141  KVDataRepository* repo = GetRepository();
2142  KVDataRepository* dest_repo = gDataRepositoryManager->GetRepository(destrepo);
2143 
2144  if (!dest_repo) {
2145  Error("CopyRunfilesToRepository", "Unknown destination repository : %s", destrepo);
2146  gDataRepositoryManager->Print();
2147  return;
2148  }
2149 
2150  KVDataSet* dest_ds = dest_repo->GetDataSetManager()->GetDataSet(GetName());
2151  dest_repo->CreateAllNeededSubdirectories(dest_ds, type);
2152  for (auto& run : runs) {
2153  TString filename = GetRunfileName(type, run);
2154  TString destpath = dest_repo->GetFullPathToTransferFile(dest_ds, type, filename);
2155  repo->CopyFileFromRepository(this, type, filename, destpath);
2156  }
2157 }
2158 
2159 
int Int_t
ROOT::R::TRInterface & r
#define f(i)
bool Bool_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
#define gDirectory
R__EXTERN TEnv * gEnv
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
char * Form(const char *fmt,...)
void AssignAndDelete(TString &target, char *tobedeleted)
R__EXTERN TSystem * gSystem
Handles lists of available runs for different datasets and types of data.
virtual void Remove(const run_index_t &run, const KVString &filename="")
Remove from the db ALL entries corresponding to the given run/index (and filename if given)
std::forward_list< run_index_t > CheckMultiRunfiles()
Returns a list with all run/indexes for which more than one file is in the available runs db.
void GetRunInfos(const run_index_t &run, KVList *dates, KVList *names)
virtual void Add(const run_index_t &run, const KVString &filename)
static ValType GetDataSetEnv(const KVString &dataset, const KVString &type, const ValType &defval)
Definition: KVBase.h:304
Database class used to store information on different colliding systems studied during an experiment....
Definition: KVDBSystem.h:52
Bool_t IsCollision() const
retourne kTRUE, si le systeme est une collision ie projectile+cible
Definition: KVDBSystem.cpp:105
Define and manage data analysis tasks.
virtual void SetDataAnalyser(const Char_t *d)
virtual void SetPrereq(const Char_t *p)
virtual void SetStatusUpdateInterval(Long64_t n)
void SetExtraAClicIncludes(const KVString &list)
virtual const Char_t * GetPrereq() const
virtual void SetUserBaseClass(const Char_t *d)
KVDataRepository * GetRepository(const Char_t *name) const
void Print(Option_t *opt="") const
Base class for managing repositories of experimental data.
virtual KVDataSetManager * GetDataSetManager() const
Return pointer to data set manager for this repository.
virtual void CopyFileFromRepository(const KVDataSet *dataset, const Char_t *datatype, const Char_t *filename, const Char_t *destination)
void CreateAllNeededSubdirectories(const KVDataSet *DataSet, const Char_t *DataType)
virtual const Char_t * GetFullPathToTransferFile(const KVDataSet *dataset, const Char_t *datatype, const Char_t *runfile)
KVDataSet * GetDataSet(Int_t) const
Return pointer to DataSet using index in list of all datasets, index>=0.
Manage an experimental dataset corresponding to a given experiment or campaign.
Definition: KVDataSet.h:36
TString GetFullPathToRunfile(const KVString &type, const run_index_t &run) const
Definition: KVDataSet.cpp:931
TString GetFullPathToDB() const
Returns full path to file where database is written on disk.
Definition: KVDataSet.cpp:150
void ls(Option_t *opt="") const override
Print dataset information.
Definition: KVDataSet.cpp:422
TString GetOutputRepository(const Char_t *taskname) const
Definition: KVDataSet.cpp:2086
virtual void OpenDBFile(const Char_t *full_path_to_dbfile) const
Open the database from a file on disk.
Definition: KVDataSet.cpp:124
run_index_list GetRunList_VersionSelection(const Char_t *type, const Char_t *version, KVDBSystem *sys=0)
Definition: KVDataSet.cpp:1331
TString GetDBName() const
Definition: KVDataSet.cpp:110
void CheckMultiRunfiles(const Char_t *data_type)
Definition: KVDataSet.cpp:1473
Bool_t CheckRunfileAvailable(const KVString &type, const run_index_t &run)
Definition: KVDataSet.cpp:1019
virtual const Char_t * GetBaseFileName(const Char_t *type, const run_index_t &run) const
Definition: KVDataSet.cpp:1052
void CheckUpToDate(const Char_t *data_type, const Char_t *other_repos)
Definition: KVDataSet.cpp:1647
run_index_list GetRunList(const Char_t *data_type, const KVDBSystem *sys=0) const
Definition: KVDataSet.cpp:1728
void CopyRunfilesFromRepository(const Char_t *type, const run_index_list &runs, const Char_t *destdir)
Copies the runfiles of given "type" into the local directory "destdir".
Definition: KVDataSet.cpp:2116
KVDataRepository * GetRepository() const
Get pointer to data repository in which dataset is stored.
Definition: KVDataSet.cpp:1459
const Char_t * GetDataSetDir() const
Definition: KVDataSet.cpp:746
KVAvailableRunsFile * GetAvailableRunsFile(const Char_t *type) const
Definition: KVDataSet.cpp:50
void CommitRunfile(const KVString &type, const run_index_t &run, TFile *file)
Definition: KVDataSet.cpp:1372
TDatime GetRunfileDate(const KVString &type, const run_index_t &run)
Definition: KVDataSet.cpp:985
virtual void AddAvailableDataType(const Char_t *)
Definition: KVDataSet.cpp:551
KVDataAnalysisTask * GetAnalysisTask(Int_t) const
Definition: KVDataSet.cpp:617
virtual void SaveDataBase() const
Definition: KVDataSet.cpp:213
virtual std::unique_ptr< TList > GetListOfAvailableSystems(const Char_t *datatype, KVDBSystem *systol=0)
Definition: KVDataSet.cpp:641
virtual KVDataAnalysisTask * GetAnalysisTaskAny(const Char_t *keywords) const
Definition: KVDataSet.cpp:1996
run_index_list GetRunList_DateSelection(const Char_t *type, TDatime *min=0, TDatime *max=0)
Definition: KVDataSet.cpp:1215
virtual void SetAnalysisTasks(const KVSeqCollection *)
Definition: KVDataSet.cpp:568
TFile * NewRunfile(const KVString &type, const run_index_t &run)
Definition: KVDataSet.cpp:1112
Bool_t CheckRunfileUpToDate(const KVString &data_type, const run_index_t &run, KVDataRepository *other_repos)
Definition: KVDataSet.cpp:1588
virtual void CheckAvailable()
Definition: KVDataSet.cpp:494
void DeleteRunfile(const KVString &type, const run_index_t &run, Bool_t confirm=kTRUE)
Definition: KVDataSet.cpp:1137
virtual Int_t GetNtasks() const
Definition: KVDataSet.cpp:602
KVString GetDataSetEnv(const Char_t *type, const Char_t *defval="") const
Definition: KVDataSet.cpp:784
run_index_list GetRunList_StageSelection(const Char_t *other_type, const Char_t *base_type, KVDBSystem *sys=0, Bool_t OnlyCol=kFALSE)
Definition: KVDataSet.cpp:1277
TString GetFullPathToDataSetFile(const Char_t *filename)
Definition: KVDataSet.cpp:1926
virtual void MakeAnalysisClass(const Char_t *task, const Char_t *classname)
Definition: KVDataSet.cpp:1830
void DeleteRunfiles(const Char_t *type, const run_index_list &lrun={}, Bool_t confirm=kTRUE)
Definition: KVDataSet.cpp:1184
TObject * open_runfile(const KVString &type, const run_index_t &run)
Definition: KVDataSet.cpp:876
void CopyRunfilesToRepository(const Char_t *type, const run_index_list &runs, const Char_t *destrepo)
Definition: KVDataSet.cpp:2136
KVString GetRunfileName(const KVString &type, const run_index_t &run) const
Definition: KVDataSet.cpp:957
KVExpDB * GetDataBase(Option_t *opt="") const
Definition: KVDataSet.cpp:308
virtual Bool_t DataBaseNeedsUpdate() const
Definition: KVDataSet.cpp:2022
Bool_t OpenDataSetFile(const Char_t *filename, std::ifstream &file)
void SetDataSetSpecificTaskParameters(KVDataAnalysisTask *) const
Definition: KVDataSet.cpp:178
void cd() const
Definition: KVDataSet.cpp:762
virtual void WriteDBFile(const Char_t *full_path_to_dbfile) const
Definition: KVDataSet.cpp:274
void Print(Option_t *opt="") const override
Definition: KVDataSet.cpp:443
void SetName(const char *name) override
Definition: KVDataSet.cpp:714
virtual Bool_t CheckUserCanAccess()
Definition: KVDataSet.cpp:1416
void UpdateAvailableRuns(const KVString &type)
Definition: KVDataSet.cpp:1090
run_index_list GetUpdatableRuns(const Char_t *data_type, const Char_t *other_repos)
Definition: KVDataSet.cpp:1693
void SetRepository(KVDataRepository *)
Set pointer to data repository in which dataset is stored.
Definition: KVDataSet.cpp:1447
KVDataSet()
Default constructor.
Definition: KVDataSet.cpp:35
void CleanMultiRunfiles(const Char_t *data_type, Bool_t confirm=kTRUE)
Definition: KVDataSet.cpp:1517
virtual void OpenDataBase(Option_t *opt="") const
Definition: KVDataSet.cpp:354
static Bool_t FindDataSetFile(const TString &dataset, const Char_t *filename)
Definition: KVDataSet.cpp:1960
TString GetDBFileName() const
Definition: KVDataSet.cpp:82
Extension of TDatime to handle various useful date formats.
Definition: KVDatime.h:33
Base class to describe database of an experiment ,,.
Definition: KVExpDB.h:20
virtual void cd()
Definition: KVExpDB.cpp:576
static KVExpDB * MakeDataBase(const Char_t *name, const Char_t *datasetdir)
Definition: KVExpDB.cpp:598
Extended TList class which owns its objects by default.
Definition: KVList.h:28
Description of an individual data file in an experimental dataset.
Definition: KVRunFile.h:19
const Char_t * GetVersion() const
Definition: KVRunFile.h:80
const KVDatime & GetFileWrittenDatime() const
Definition: KVRunFile.h:72
const run_index_t & GetRunIndex() const
Definition: KVRunFile.h:56
KaliVeda extensions to ROOT collection classes.
TObject * At(Int_t idx) const override
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
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
static TClass * GetClass(Bool_t load=kTRUE, Bool_t silent=kFALSE)
virtual Int_t GetEntries() const
const char * AsSQLString() const
void Set()
virtual Bool_t cd()
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)
Bool_t Defined(const char *name) const
TObject * FindObject(const char *name) const override
virtual void SetTitle(const char *title="")
const char * GetName() const override
const char * GetTitle() const override
virtual void SetName(const char *name)
TString & String()
const char * Data() const
void ToUpper()
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)
Bool_t cd(const char *path)
const char * pwd()
virtual int Chmod(const char *file, UInt_t mode)
virtual const char * DirName(const char *pathname)
virtual char * ConcatFileName(const char *dir, const char *name)
virtual int mkdir(const char *name, Bool_t recursive=kFALSE)
virtual Int_t Exec(const char *shellcmd)
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
virtual const char * BaseName(const char *pathname)
virtual Bool_t IsAbsoluteFileName(const char *dir)
Specifies a runfile according to run number and file index ,.
Definition: run_index.h:33
int run() const
Definition: run_index.h:52
TString as_string() const
Definition: run_index.h:94
int index(int no_index=-1) const
Definition: run_index.h:57
bool has_index() const
Definition: run_index.h:61
const Int_t n
void Error(const char *location, const char *fmt,...)
void Info(const char *location, const char *fmt,...)
void Warning(const char *location, const char *fmt,...)
double min(double x, double y)
double max(double x, double y)
const char * String
TArc a
ClassImp(TPyArg)