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