1abb6f33694cae966c77913cbb54a1fd8b3076ec
[u/mrichter/AliRoot.git] / STEER / AliDataLoader.cxx
1 /////////////////////////////////////////////////////////////////////////////////////////////
2 //                                                                                         //
3 //  class AliDataLoader                                                                    //
4 //                                                                                         //
5 //  Container of all data needed for full                                                  //
6 //  description of each data type                                                          //
7 //  (Hits, Kine, ...)                                                                      //
8 //                                                                                         //
9 //  Each data loader has a basic standard setup of BaseLoaders                             //
10 //  which can be identuified by indexes (defined by EStdBasicLoaders)                      //
11 //  Data managed by these standard base loaders has fixed naming convention                //
12 //  e.g. - tree with hits is always named TreeH                                            //
13 //                     (defined in AliLoader::fgkDefaultHitsContainerName)                 //
14 //       - task DtectorName+Name defined                                                   //
15 //                                                                                         //
16 //  EStdBasicLoaders   idx     Object Type        Description                              //
17 //      kData           0    TTree or TObject     main data itself (hits,digits,...)       //
18 //      kTask           1        TTask            object producing main data               //
19 //      kQA             2        TTree                quality assurance tree               //
20 //      kQATask         3        TTask            task producing QA object                 //
21 //                                                                                         //
22 //                                                                                         //
23 //  User can define and add more basic loaders even Run Time.                              //
24 //  Caution: in order to save information about added base loader                          //
25 //  user must rewrite Run Loader to galice.file, overwriting old setup                     //
26 //                                                                                         //
27 /////////////////////////////////////////////////////////////////////////////////////////////
28
29 /* $Id$ */
30
31 #include <TBits.h>
32 #include <TFile.h>
33 #include <TROOT.h>
34 #include <TString.h>
35
36 #include "AliDataLoader.h"
37 #include "AliLog.h"
38 #include "AliObjectLoader.h"
39 #include "AliRunLoader.h"
40 #include "AliTreeLoader.h"
41
42 ClassImp(AliDataLoader)
43
44 //______________________________________________________________________________
45 AliDataLoader::AliDataLoader():
46  fFileName(0),
47  fFile(0x0),
48  fDirectory(0x0),
49  fFileOption(),
50  fCompressionLevel(2),
51  fNEventsPerFile(0),
52  fBaseLoaders(0x0),
53  fHasTask(kFALSE),
54  fTaskName(),
55  fParentalTask(0x0),
56  fEventFolder(0x0),
57  fFolder(0x0)
58 {
59   
60 }
61
62 //______________________________________________________________________________
63 AliDataLoader::AliDataLoader(const char* filename, const char* contname, 
64                              const char* name, Option_t* opt):
65  TNamed(name,name),
66  fFileName(filename),
67  fFile(0x0),
68  fDirectory(0x0),
69  fFileOption(0),
70  fCompressionLevel(2),
71  fNEventsPerFile(0),
72  fBaseLoaders(new TObjArray(4)),
73  fHasTask(kFALSE),
74  fTaskName(),
75  fParentalTask(0x0),
76  fEventFolder(0x0),
77  fFolder(0x0)
78 {
79   //constructor
80   // creates a 0 loader, depending on option, default "T" is specialized loader for trees
81   // else standard object loader
82   // trees needs special care, becouse we need to set dir before writing
83   AliDebug(1, Form("File name is %s",fFileName.Data()));
84   
85   TString option(opt);
86   AliBaseLoader* bl;
87   if (option.CompareTo("T",TString::kIgnoreCase) == 0)
88     bl = new AliTreeLoader(contname,this);
89   else 
90     bl = new AliObjectLoader(contname,this);
91   fBaseLoaders->AddAt(bl,kData);
92   
93 }
94
95 //______________________________________________________________________________
96 AliDataLoader::~AliDataLoader()
97 {
98   //
99   //dtor
100   //
101   UnloadAll();
102 }
103
104 //______________________________________________________________________________
105 Int_t  AliDataLoader::SetEvent()
106 {
107   //
108   // The same that GetEvent but do not post data to folders
109   //
110   AliRunLoader* rl = GetRunLoader();
111   if (rl == 0x0)
112     {
113       AliError("Can not get RunGettr");
114       return 1;
115     }
116   
117   Int_t evno = rl->GetEventNumber();
118   
119   TIter next(fBaseLoaders);
120   AliBaseLoader* bl;
121   while ((bl = (AliBaseLoader*)next()))
122     {
123       if (bl->DoNotReload() == kFALSE) bl->Clean();
124     }
125   
126   if(fFile)
127     {
128       if (CheckReload())
129         {
130           delete fFile;
131           fFile = 0x0;
132           AliDebug(1, Form("Reloading new file. File opt is %s",fFileOption.Data()));
133           OpenFile(fFileOption);
134         }
135       
136       fDirectory = AliLoader::ChangeDir(fFile,evno);
137       if (fDirectory == 0x0)
138         {
139           AliError(Form("Can not chage directory in file %s",fFile->GetName()));
140           return 1;
141         }
142     }
143   return 0;
144 }
145
146 //______________________________________________________________________________
147 Int_t  AliDataLoader::GetEvent()
148 {
149   // posts all loaded data from files to White Board
150   // event number is defined in RunLoader
151   // 
152   //returns:
153   //     0  - in case of no error
154   //     1  - event not found
155   //     
156   //for each base laoder post, if was loaded before GetEvent
157   
158   //call set event to switch to new directory in file
159   
160   
161   //post all data that were loaded before 
162   // ->SetEvent does not call Unload, but only cleans White Board
163   // such IsLoaded flag stays untached
164   
165   if ( AliLoader::TestFileOption(fFileOption) == kTRUE ) //if file is read or update mode try to post
166     {                                                     //in other case there is no sense to post: file is new
167       TIter nextbl(fBaseLoaders);
168       AliBaseLoader* bl;
169       while ((bl = (AliBaseLoader*)nextbl()))
170         {
171           if (bl->IsLoaded())
172             {
173               if (bl->DoNotReload() == kFALSE) bl->Post();
174             }
175         } 
176     }
177   return 0;
178 }
179
180 //______________________________________________________________________________
181 Int_t AliDataLoader::OpenFile(Option_t* opt)
182 {
183   //Opens file named 'filename', and assigns pointer to it to 'file'
184   //jumps to fDirectoryectory corresponding to current event and stores the pointer to it in 'fDirectory'
185   //option 'opt' is passed to TFile::Open
186   if (fFile)
187     {
188       if(fFile->IsOpen() == kTRUE)
189         {
190           AliWarning(Form(" File %s already opened. First close it.",fFile->GetName()));
191           return 0;
192         }
193       else
194         {
195           AliWarning(Form("Pointer to file %s is not null, but file is not opened",
196                           fFile->GetName()));
197           delete fFile;
198           fFile = 0x0;
199         }
200     }
201   
202   TString fname(SetFileOffset(fFileName));
203   
204   fFile = (TFile *)(gROOT->GetListOfFiles()->FindObject(fname));
205   if (fFile)
206     {
207       if(fFile->IsOpen() == kTRUE)
208         {
209           TString option1 = fFile->GetOption();
210           if (option1.CompareTo("read",TString::kIgnoreCase) == 0)
211             {
212               AliInfo(Form("File %s already opened in read mode.",fFile->GetName()));
213             }
214           else
215             {
216               TString option2 = opt;
217               if (option2.CompareTo("read",TString::kIgnoreCase) == 0)
218                 {
219                   AliInfo(Form("Open already opened file %s in read mode.",fFile->GetName()));
220                 }
221               else {
222                 AliWarning(Form("File %s already opened by sombody else. First close it.",
223                                 fFile->GetName()));
224                 return 0;
225               }
226             }
227         }
228     }
229   
230   fFileOption = opt;
231   fFile = TFile::Open(fname,fFileOption);//open the file
232   if (fFile == 0x0)
233     {//file is null
234       AliError(Form("Can not open file %s",fname.Data()));
235       return 1;
236     }
237   if (fFile->IsOpen() == kFALSE)
238     {//file is null
239       AliError(Form("Can not open file %s",fname.Data()));
240       return 1;
241     }
242   
243   fFile->SetCompressionLevel(fCompressionLevel);
244   
245   AliRunLoader* rg = GetRunLoader();
246   if (rg == 0x0)
247     {
248       AliError("Can not find Run-Loader in folder.");
249       return 2;
250     }
251   Int_t evno = rg->GetEventNumber();
252   
253   fDirectory = AliLoader::ChangeDir(fFile,evno);
254   if (fDirectory == 0x0)
255     {
256       AliError(Form("Can not chage fDirectory in file %s.",fFile->GetName()));
257       return 3; 
258     }
259   return 0;
260 }
261
262 //______________________________________________________________________________
263 void AliDataLoader::Unload()
264 {
265   //
266   //unloads main data -  shortcut method 
267   //
268   GetBaseLoader(0)->Unload();
269 }
270
271 //______________________________________________________________________________
272 void AliDataLoader::UnloadAll()
273 {
274   //
275   // Unloads all data and tasks
276   //
277   if ( fFile == 0x0 ) return; //nothing loaded
278   
279   TIter next(fBaseLoaders);
280   AliBaseLoader* bl;
281   while ((bl = (AliBaseLoader*)next()))
282     {
283       bl->Unload();
284     }
285 }
286
287
288 //______________________________________________________________________________
289 Int_t AliDataLoader::Reload()
290 {
291   //
292   // Unloads and loads data again
293   //
294   if ( fFile == 0x0 ) return 0;
295   
296   TBits loaded(fBaseLoaders->GetEntries());  
297   TIter next(fBaseLoaders);
298   AliBaseLoader* bl;
299   
300   Int_t i = 0;
301   while ((bl = (AliBaseLoader*)next()))
302     {
303       if (bl->IsLoaded())
304         {
305           loaded.SetBitNumber(i++,kTRUE);
306           bl->Unload();
307         }
308     }
309   
310   Int_t retval;
311   i = 0;  
312   next.Reset();
313   while ((bl = (AliBaseLoader*)next()))
314     {
315       if (loaded.TestBitNumber(i++))
316         {
317           retval = bl->Load(fFileOption);
318           if (retval) 
319             {
320               AliError(Form("Error occur while loading %s",bl->GetName()));
321               return retval;
322             }
323         }
324     }
325   return 0;
326 }
327
328
329 //______________________________________________________________________________
330 Int_t AliDataLoader::WriteData(Option_t* opt)
331 {
332   //
333   // Writes primary data ==  first BaseLoader
334   //
335   AliDebug(1, Form("Writing %s container for %s data. Option is %s.",
336                    GetBaseLoader(0)->GetName(),GetName(),opt));
337   return GetBaseLoader(0)->WriteData(opt);
338 }
339
340 //______________________________________________________________________________
341 Int_t AliDataLoader::Load(Option_t* opt)
342 {
343   //
344   // Writes primary data ==  first BaseLoader
345   //
346   return GetBaseLoader(0)->Load(opt);
347 }
348
349 //______________________________________________________________________________
350 Int_t  AliDataLoader::SetEventFolder(TFolder* eventfolder)
351 {
352   //
353   // Sets the event folder
354   //
355   if (eventfolder == 0x0)
356     {
357       AliError("Stupid joke. Argument is NULL");
358       return 1;
359     }
360   AliDebug(1, Form("name = %s Setting Event Folder named %s.",
361                    GetName(),eventfolder->GetName()));
362   
363   fEventFolder = eventfolder;
364   return 0;
365 }
366
367
368 //______________________________________________________________________________
369 Int_t  AliDataLoader::SetFolder(TFolder* folder)
370 {
371   // Sets the folder and the data loaders
372   if (folder == 0x0)
373     {
374       AliError("Stupid joke. Argument is NULL");
375     return 1;
376     }
377   
378   AliDebug(1, Form("name = %s Setting folder named %s.",GetName(),folder->GetName()));
379   
380   fFolder = folder;
381   TIter next(fBaseLoaders);
382   AliBaseLoader* bl;
383   
384   while ((bl = (AliBaseLoader*)next()))
385     {
386       bl->SetDataLoader(this);
387     }  
388   
389   return 0;
390 }
391
392 //______________________________________________________________________________
393 TFolder* AliDataLoader::GetEventFolder()
394 {
395   //
396   // Get EVENT folder
397   // Data that are changing from event to event, even in single run
398   //
399   AliDebug(1, "EF = %#x");
400   return fEventFolder;
401 }
402
403 //______________________________________________________________________________
404 AliRunLoader* AliDataLoader::GetRunLoader()
405 {
406   //
407   // Gets the run-loader from event folder
408   //
409   AliRunLoader* rg = 0x0;
410   TFolder* ef = GetEventFolder();
411   if (ef == 0x0)
412    {
413      AliError("Can not get event folder.");
414      return 0;
415    }
416   rg = dynamic_cast<AliRunLoader*>(ef->FindObject(AliRunLoader::GetRunLoaderName()));
417   return rg;
418 }
419
420 //______________________________________________________________________________
421 void AliDataLoader::CloseFile()
422 {
423   //
424   // Closes file
425   //
426   TIter next(fBaseLoaders);
427   AliBaseLoader* bl;
428   while ((bl = (AliBaseLoader*)next()))
429     {
430       if (bl->IsLoaded()) return;
431     }
432   
433   AliDebug(1, "Closing and deleting (object) file.");
434   
435   delete fFile;
436   fFile = 0x0;
437   fDirectory = 0x0;
438 }
439
440
441 //______________________________________________________________________________
442 void AliDataLoader::Clean()
443 {
444   //
445   // Cleans main data
446   //
447   GetBaseLoader(0)->Clean();
448 }
449
450 //______________________________________________________________________________
451 void AliDataLoader::CleanAll()
452 {
453   //
454   // Cleans all folders and tasks
455   //
456   TIter next(fBaseLoaders);
457   AliBaseLoader* bl;
458   while ((bl = (AliBaseLoader*)next()))
459     {
460       bl->Clean();
461     }
462 }
463
464 //______________________________________________________________________________
465 void AliDataLoader::SetFileNameSuffix(const TString& suffix)
466 {
467   //
468   // adds the suffix before ".root", 
469   // e.g. TPC.Digits.root -> TPC.DigitsMerged.root
470   // made on Jiri Chudoba demand
471   //
472   AliDebug(1, Form("suffix=%s",suffix.Data()));
473   AliDebug(1, Form("   Digits File Name before: %s",fFileName.Data()));
474   
475   static const TString dotroot(".root");
476   const TString& suffixdotroot = suffix + dotroot;
477   fFileName = fFileName.ReplaceAll(dotroot,suffixdotroot);
478   
479   AliDebug(1, Form("                    after : %s",fFileName.Data()));
480 }
481
482 //______________________________________________________________________________
483 Bool_t AliDataLoader::CheckReload()
484 {
485   //
486   // Checks if we have to reload given file
487   //
488   if (fFile == 0x0) return kFALSE;
489   TString tmp = SetFileOffset(fFileName);
490   if (tmp.CompareTo(fFile->GetName())) return kTRUE;  //file must be reloaded
491   return  kFALSE;
492 }
493
494 //______________________________________________________________________________
495 const TString AliDataLoader::SetFileOffset(const TString& fname)
496 {
497   //
498   // Return fname
499   //
500   Long_t offset = (Long_t)GetRunLoader()->GetFileOffset();
501   if (fNEventsPerFile > 0) {
502     offset = GetRunLoader()->GetEventNumber()/fNEventsPerFile;
503   }
504   if (offset < 1) return fname;
505   
506   TString soffset;
507   soffset += offset;//automatic conversion to string
508   TString dotroot(".root");
509   const TString& offfsetdotroot = offset + dotroot;
510   TString out = fname;
511   out = out.ReplaceAll(dotroot,offfsetdotroot);
512   AliDebug(1, Form("in=%s  out=%s.",fname.Data(),out.Data()));
513   return out;
514 }
515
516 //______________________________________________________________________________
517 void AliDataLoader::SetFileOption(Option_t* newopt)
518 {
519   //
520   // Sets file option
521   //
522   if (fFileOption.CompareTo(newopt) == 0) return;
523   fFileOption = newopt;
524   Reload();
525 }
526
527 //______________________________________________________________________________
528 void AliDataLoader::SetCompressionLevel(Int_t cl)
529 {
530   //
531   // Sets comression level for data defined by di
532   //
533   fCompressionLevel = cl;
534   if (fFile) fFile->SetCompressionLevel(cl);
535 }
536
537 //______________________________________________________________________________
538 void AliDataLoader::MakeTree()
539 {
540   //
541   // Makes tree for the current data loader
542   //
543   AliTreeLoader* tl = dynamic_cast<AliTreeLoader*>(fBaseLoaders->At(0));
544   if (tl == 0x0)
545    {
546      AliError("Can not make a tree because main base loader is not a tree loader");
547      return;
548    }
549   tl->MakeTree();
550 }
551
552 //______________________________________________________________________________
553 Bool_t AliDataLoader::IsFileWritable() const
554 {
555   //
556   // Returns true if file is writable
557   //
558   return (fFile)?fFile->IsWritable():kFALSE;
559 }
560
561 //______________________________________________________________________________
562 Bool_t AliDataLoader::IsFileOpen() const
563 {
564   //
565   // Returns true if file is writable
566   //
567   return (fFile)?fFile->IsOpen():kFALSE;
568 }
569
570 //______________________________________________________________________________
571 Bool_t AliDataLoader::IsOptionContrary(const TString& option) const
572 {
573   // Checks if passed option is contrary with file open option 
574   // which is passed option "writable" and existing option not wriable
575   // in reverse case it is no harm so it is NOT contrary
576   if (fFile == 0x0) return kFALSE; //file is not opened - no problem
577   
578   if ( ( AliLoader::IsOptionWritable(option)      == kTRUE  ) &&     // passed option is writable and 
579        ( AliLoader::IsOptionWritable(fFileOption) == kFALSE )    )   // existing one is not writable
580     {
581       return kTRUE;
582     }
583   
584   return kFALSE;
585 }
586
587
588 //______________________________________________________________________________
589 void AliDataLoader::AddBaseLoader(AliBaseLoader* bl)
590 {
591   //Adds a base loader to lits of base loaders managed by this data loader
592   //Managed data/task will be stored in proper root directory,
593   //and posted to 
594   // - in case of tree/object - data folder connected with detector associated with this data loader
595   // - in case of task - parental task which defined in this AliTaskLoader 
596   
597   if (bl == 0x0)
598     {
599       AliWarning("Pointer is null.");
600       return;
601     }
602   
603   TObject* obj = fBaseLoaders->FindObject(bl->GetName());
604   if (obj)
605     {
606       AliError("Can not add this base loader.");
607       AliError(Form("There exists already base loader which manages data named %s for this detector.",obj->GetName()));
608       return;
609     }
610  
611   fBaseLoaders->Add(bl);
612 }
613
614 //______________________________________________________________________________
615 AliBaseLoader* AliDataLoader::GetBaseLoader(const TString& name) const
616 {
617   //
618   // Return pointer to base loader
619   //
620   return dynamic_cast<AliBaseLoader*>(fBaseLoaders->FindObject(name));
621 }
622
623 //______________________________________________________________________________
624 AliBaseLoader* AliDataLoader::GetBaseLoader(Int_t n) const
625 {
626   //
627   // Gets the n-th base loader (what is n?)
628   //
629   return dynamic_cast<AliBaseLoader*>(fBaseLoaders->At(n));
630 }
631
632 //______________________________________________________________________________
633 TTree* AliDataLoader::Tree() const
634 {
635   // Returns tree from the main base loader
636   // it is just shortcut method for comfort of user
637   // main storage object does not have to be Tree  - 
638   // that is why first we need to check if it is a TreeLoader 
639   AliTreeLoader* tl = dynamic_cast<AliTreeLoader*>(GetBaseLoader(0));
640   if (tl == 0x0) return 0x0;
641   return tl->Tree();
642 }
643
644 //______________________________________________________________________________
645 void  AliDataLoader::SetDirName(TString& dirname)
646 {
647   //
648   // Sets the directory name where the files will be stored
649   //
650   AliDebug(10, Form("FileName before %s",fFileName.Data()));
651   Int_t n = fFileName.Last('/');
652   AliDebug(10, Form("Slash found on pos %d",n));
653   if (n > 0) fFileName = fFileName.Remove(0,n+1);
654   AliDebug(10, Form("Core FileName %s",fFileName.Data()));
655   fFileName = dirname + fFileName;
656   AliDebug(10, Form("FileName after %s",fFileName.Data()));
657 }
658
659 //______________________________________________________________________________
660 AliObjectLoader* AliDataLoader::GetBaseDataLoader()
661 {
662   //
663   // Gets the base data loader
664   //
665   return dynamic_cast<AliObjectLoader*>(GetBaseLoader(kData));
666 }
667
668 //______________________________________________________________________________
669 AliTaskLoader* AliDataLoader::GetBaseTaskLoader()
670 {
671   //
672   // Gets the base task loader
673   //
674   return dynamic_cast<AliTaskLoader*>(GetBaseLoader(kTask));
675 }
676
677 //______________________________________________________________________________
678 AliBaseLoader* AliDataLoader::GetBaseQALoader()
679 {
680   //
681   // Gets the base QA loader
682   //
683   return GetBaseLoader(kQA);
684 }
685
686 //______________________________________________________________________________
687 AliTaskLoader* AliDataLoader::GetBaseQATaskLoader()
688 {
689   //
690   // Returns pointer to QA base loader
691   //
692   return dynamic_cast<AliTaskLoader*>(GetBaseLoader(kQATask));
693 }
694
695 //______________________________________________________________________________
696 void AliDataLoader::SetBaseDataLoader(AliBaseLoader* bl)
697 {
698   //
699   // Sets data base loader
700   //
701   if (bl == 0x0)
702     {
703       AliError("Parameter is null");
704       return;
705     }
706   if (GetBaseDataLoader()) delete GetBaseDataLoader();
707   fBaseLoaders->AddAt(bl,kData);
708 }
709
710 //______________________________________________________________________________
711 void AliDataLoader::SetBaseTaskLoader(AliTaskLoader* bl)
712 {
713   //
714   // Sets Task base loader
715   //
716   if (bl == 0x0)
717    {
718      AliError("Parameter is null");
719      return;
720    }
721   if (GetBaseTaskLoader()) delete GetBaseTaskLoader();
722   fBaseLoaders->AddAt(bl,kTask);
723 }
724
725 //______________________________________________________________________________
726 void AliDataLoader::SetBaseQALoader(AliBaseLoader* bl)
727 {
728   //
729   // Sets QA base loader
730   //
731   if (bl == 0x0)
732     {
733       AliError("Parameter is null");
734       return;
735     }
736   if (GetBaseQALoader()) delete GetBaseQALoader();
737   fBaseLoaders->AddAt(bl,kQA);
738 }
739
740 //______________________________________________________________________________
741 void AliDataLoader::SetBaseQATaskLoader(AliTaskLoader* bl)
742 {
743   //
744   // Sets QA Task base loader
745   //
746   if (bl == 0x0)
747     {
748       AliError("Parameter is null");
749       return;
750    }
751   if (GetBaseQATaskLoader()) delete GetBaseQATaskLoader();
752   fBaseLoaders->AddAt(bl,kQATask);
753 }
754
755 //______________________________________________________________________________
756 void AliDataLoader::Synchronize()
757 {
758   //
759   // Synchronizes all writable files 
760   //
761   if ( fFile ) fFile->Flush();
762 }
763
764
765