Adding ESD friend in case of online reconstruction
[u/mrichter/AliRoot.git] / EVE / EveBase / AliEveEventManager.cxx
1 // $Id$
2 // Main authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007
3
4 /**************************************************************************
5  * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
6  * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
7  * full copyright notice.                                                 *
8  **************************************************************************/
9
10 #include "AliEveEventManager.h"
11 #include "AliEveMacroExecutor.h"
12 #include <TEveManager.h>
13
14 #include <AliRunLoader.h>
15 #include <AliRun.h>
16 #include <AliESDRun.h>
17 #include <AliESDEvent.h>
18 #include <AliESDfriend.h>
19 #include <AliAODEvent.h>
20
21 #include <AliDAQ.h>
22 #include <AliRawEventHeaderBase.h>
23 #include <AliRawReaderRoot.h>
24 #include <AliRawReaderFile.h>
25 #include <AliRawReaderDate.h>
26 #include <AliMagFMaps.h>
27 #include <AliCDBManager.h>
28 #include <AliCDBStorage.h>
29 #include <AliHeader.h>
30 #include <AliGeomManager.h>
31
32 #include <TFile.h>
33 #include <TTree.h>
34 #include <TGeoManager.h>
35 #include <TSystem.h>
36 #include <TTimeStamp.h>
37
38 //==============================================================================
39 //==============================================================================
40 // AliEveEventManager
41 //==============================================================================
42
43 //______________________________________________________________________________
44 //
45 // Provides interface for loading and navigating standard AliRoot data
46 // (AliRunLoader), ESD, AOD and RAW.
47 //
48 // ESDfriend is attached automatically, if the file is found.
49 //
50 // AODfriends are not attached automatically as there are several
51 // possible files involved. To have a specific AODfriend attached, call
52 // static method
53 //   AliEveEventManager::AddAODfriend("AliAOD.VertexingHF.root");
54 // before initializing the event-manager.
55 //
56 // Also provides interface to magnetic-field and geometry. Mostly
57 // intended as wrappers over standard AliRoot functionality for
58 // convenient use from visualizateion macros.
59 //
60 // There can be a single main event-manger, it is stored in private
61 // data member fgMaster and can be accessed via static member function
62 // GetMaster().
63 //
64 // For event overlaying and embedding one can instantiate additional
65 // event-managers via static method AddDependentManager(const TString& path).
66 // This interface is under development.
67
68 ClassImp(AliEveEventManager)
69
70 Bool_t AliEveEventManager::fgAssertRunLoader = kFALSE;
71 Bool_t AliEveEventManager::fgAssertESD       = kFALSE;
72 Bool_t AliEveEventManager::fgAssertAOD       = kFALSE;
73 Bool_t AliEveEventManager::fgAssertRaw       = kFALSE;
74
75 TString  AliEveEventManager::fgESDFileName("AliESDs.root");
76 TString  AliEveEventManager::fgAODFileName("AliAOD.root");
77 TString  AliEveEventManager::fgRawFileName("raw.root");
78 TString  AliEveEventManager::fgCdbUri("local://$ALICE_ROOT");
79
80 AliMagF* AliEveEventManager::fgMagField = 0;
81
82 TList*   AliEveEventManager::fgAODfriends = 0;
83
84 AliEveEventManager* AliEveEventManager::fgMaster  = 0;
85 AliEveEventManager* AliEveEventManager::fgCurrent = 0;
86
87 void AliEveEventManager::InitInternals()
88 {
89   // Initialize internal members.
90
91   static const TEveException kEH("AliEveEventManager::InitInternals ");
92
93   if (fgCurrent != 0)
94   {
95     throw(kEH + "Dependent event-managers should be created via static method AddDependentManager().");
96   }
97
98   if (fgMaster == 0)
99   {
100     fgMaster = this;
101   }
102
103   fgCurrent = this;
104
105   fAutoLoadTimer = new TTimer;
106   fAutoLoadTimer->Connect("Timeout()", "AliEveEventManager", this, "AutoLoadNextEvent()");
107
108   fExecutor = new AliEveMacroExecutor;
109 }
110
111 AliEveEventManager::AliEveEventManager(const TString& name) :
112   TEveEventManager(name),
113
114   fPath      ( ), fEventId (-1),
115   fRunLoader (0),
116   fESDFile   (0), fESDTree (0), fESD (0),
117   fESDfriend (0), fESDfriendExists(kFALSE),
118   fAODFile   (0), fAODTree (0), fAOD (0),
119   fRawReader (0),
120   fAutoLoad  (kFALSE), fAutoLoadTime (5.),     fAutoLoadTimer(0),
121   fIsOpen    (kFALSE), fHasEvent     (kFALSE), fExternalCtrl (kFALSE),
122   fSelectOnTriggerType(kFALSE), fTriggerType(""),
123   fExecutor    (0),
124   fSubManagers (0),
125   fAutoLoadTimerRunning(kFALSE)
126 {
127   // Default constructor.
128
129   InitInternals();
130 }
131
132 AliEveEventManager::AliEveEventManager(const TString& name, const TString& path, Int_t ev) :
133   TEveEventManager(name, path),
134
135   fPath   (path), fEventId(-1),
136   fRunLoader (0),
137   fESDFile   (0), fESDTree (0), fESD (0),
138   fESDfriend (0), fESDfriendExists(kFALSE),
139   fAODFile   (0), fAODTree (0), fAOD (0),
140   fRawReader (0),
141   fAutoLoad  (kFALSE), fAutoLoadTime (5),      fAutoLoadTimer(0),
142   fIsOpen    (kFALSE), fHasEvent     (kFALSE), fExternalCtrl (kFALSE),
143   fSelectOnTriggerType(kFALSE), fTriggerType(""),
144   fExecutor    (0),
145   fSubManagers (0),
146   fAutoLoadTimerRunning(kFALSE)
147 {
148   // Constructor with event-directory URL and event-id.
149
150   InitInternals();
151
152   Open();
153   if (ev >= 0)
154   {
155     GotoEvent(ev);
156   }
157 }
158
159 AliEveEventManager::~AliEveEventManager()
160 {
161   // Destructor.
162
163   delete fSubManagers;
164
165   if (fIsOpen)
166   {
167     Close();
168   }
169 }
170
171 /******************************************************************************/
172
173 void AliEveEventManager::SetESDFileName(const TString& esd)
174 {
175   // Set file-name for opening ESD, default "AliESDs.root".
176
177   if ( ! esd.IsNull()) fgESDFileName = esd;
178 }
179
180 void AliEveEventManager::SetAODFileName(const TString& aod)
181 {
182   // Set file-name for opening AOD, default "AliAOD.root".
183
184   if ( ! aod.IsNull()) fgAODFileName = aod;
185 }
186
187 void AliEveEventManager::AddAODfriend(const TString& friendFileName)
188 {
189   // Add new AOD friend file-name to be attached when opening AOD.
190   // This should include '.root', as in 'AliAOD.VertexingHF.root'.
191
192   if (fgAODfriends == 0)
193   {
194     fgAODfriends = new TList;
195     fgAODfriends->SetOwner(kTRUE);
196   }
197   fgAODfriends->Add(new TObjString(friendFileName));
198 }
199
200 void AliEveEventManager::SetRawFileName(const TString& raw)
201 {
202   // Set file-name for opening of raw-data, default "raw.root"
203   if ( ! raw.IsNull()) fgRawFileName = raw;
204 }
205
206 void AliEveEventManager::SetCdbUri(const TString& cdb)
207 {
208   // Set path to CDB, default "local://$ALICE_ROOT".
209
210   if ( ! cdb.IsNull()) fgCdbUri = cdb;
211 }
212
213 void AliEveEventManager::SetAssertElements(Bool_t assertRunloader, Bool_t assertEsd,
214                                            Bool_t assertAod, Bool_t assertRaw)
215 {
216   // Set global flags that detrmine which parts of the event-data must
217   // be present when the event is opened.
218
219   fgAssertRunLoader = assertRunloader;
220   fgAssertESD = assertEsd;
221   fgAssertAOD = assertAod;
222   fgAssertRaw = assertRaw;
223 }
224
225 /******************************************************************************/
226
227 void AliEveEventManager::Open()
228 {
229   // Open event-data from URL specified in fPath.
230   // Attempts to create AliRunLoader() and to open ESD with ESDfriends.
231   // Warning is reported if run-loader or ESD is not found.
232   // Global data-members fgAssertRunLoader and fgAssertESD can be set
233   // to throw exceptions instead.
234
235   static const TEveException kEH("AliEveEventManager::Open ");
236
237   if (fExternalCtrl)
238   {
239     throw (kEH + "Event-loop is under external control.");
240   }
241   if (fIsOpen)
242   {
243     throw (kEH + "Event-files already opened.");
244   }
245
246   gSystem->ExpandPathName(fPath);
247   // The following magick is required for ESDfriends to be loaded properly
248   // from non-current directory.
249   if (fPath.IsNull() || fPath == ".")
250   {
251     fPath = gSystem->WorkingDirectory();
252   }
253   else if ( ! fPath.BeginsWith("file:/"))
254   {
255     TUrl    url(fPath, kTRUE);
256     TString protocol(url.GetProtocol());
257     if (protocol == "file" && fPath[0] != '/')
258       fPath = Form("%s/%s", gSystem->WorkingDirectory(), fPath.Data());
259   }
260
261   Int_t runNo = -1;
262
263   // Open ESD and ESDfriends
264
265   TString esdPath(Form("%s/%s", fPath.Data(), fgESDFileName.Data()));
266   if ((fESDFile = TFile::Open(esdPath)))
267   {
268     fESD = new AliESDEvent();
269     fESDTree = (TTree*) fESDFile->Get("esdTree");
270     if (fESDTree != 0)
271     {
272       // Check if ESDfriends exists and attach the branch.
273       // We use TFile::Open() instead of gSystem->AccessPathName
274       // as it seems to work better when attachine alieve to a
275       // running reconstruction process with auto-save on.
276       // There was also a problem with TTree::Refresh() - it didn't
277       // save the friend branch on a separate file, fixed in 5.22.2 -
278       // so we might want to try the old way again soon.
279       TString p(Form("%s/AliESDfriends.root", fPath.Data()));
280       TFile *esdFriendFile = TFile::Open(p);
281       if (esdFriendFile)
282       {
283         if (!esdFriendFile->IsZombie())
284         {
285           esdFriendFile->Close();
286           fESDfriendExists = kTRUE;
287           fESDTree->SetBranchStatus ("ESDfriend*", 1);
288         }
289         delete esdFriendFile;
290       }
291
292       fESD->ReadFromTree(fESDTree);
293       if (fESDfriendExists)
294       {
295         fESDfriend = (AliESDfriend*) fESD->FindListObject("AliESDfriend");
296         Info(kEH, "found and attached ESD friend.");
297       }
298       else
299       {
300         Warning(kEH, "ESDfriend not found.");
301       }
302
303       if (fESDTree->GetEntry(0) <= 0)
304       {
305         delete fESDFile; fESDFile = 0;
306         delete fESD; fESD = 0;
307         Warning(kEH, "failed getting the first entry from esdTree.");
308       }
309       else
310       {
311         if (runNo < 0)
312           runNo = fESD->GetESDRun()->GetRunNumber();
313       }
314     }
315     else // esdtree == 0
316     {
317       delete fESDFile; fESDFile = 0;
318       delete fESD; fESD = 0;
319       Warning(kEH, "failed getting the esdTree.");
320     }
321   }
322   else // esd not readable
323   {
324     Warning(kEH, "can not read ESD file '%s'.", esdPath.Data());
325   }
326   if (fESDTree == 0)
327   {
328     if (fgAssertESD)
329     {
330       throw (kEH + "ESD not initialized. Its precence was requested.");
331     } else {
332       Warning(kEH, "ESD not initialized.");
333     }
334   }
335
336   // Open AOD and registered friends
337
338   TString aodPath(Form("%s/%s", fPath.Data(), fgAODFileName.Data()));
339   if ((fAODFile = TFile::Open(aodPath)))
340   {
341     fAOD = new AliAODEvent();
342     fAODTree = (TTree*) fAODFile->Get("aodTree");
343     if (fAODTree != 0)
344     {
345       // Check if AODfriends exist and attach them.
346       TIter       friends(fgAODfriends);
347       TObjString *name;
348       while ((name = (TObjString*) friends()) != 0)
349       {
350         TString p(Form("%s/%s", fPath.Data(), name->GetName()));
351         if (gSystem->AccessPathName(p, kReadPermission) == kFALSE)
352         {
353           fAODTree->AddFriend("aodTree", name->GetName());
354         }
355       }
356
357       fAOD->ReadFromTree(fAODTree);
358
359       if (fAODTree->GetEntry(0) <= 0)
360       {
361         delete fAODFile; fAODFile = 0;
362         delete fAOD;     fAOD     = 0;
363         Warning(kEH, "failed getting the first entry from addTree.");
364       }
365       else
366       {
367         if (runNo < 0)
368           runNo = fAOD->GetRunNumber();
369       }
370     }
371     else // aodtree == 0
372     {
373       delete fAODFile; fAODFile = 0;
374       delete fAOD;     fAOD     = 0;
375       Warning(kEH, "failed getting the aodTree.");
376     }
377   }
378   else // aod not readable
379   {
380     Warning(kEH, "can not read AOD file '%s'.", aodPath.Data());
381   }
382   if (fAODTree == 0)
383   {
384     if (fgAssertAOD)
385     {
386       throw (kEH + "AOD not initialized. Its precence was requested.");
387     } else {
388       Warning(kEH, "AOD not initialized.");
389     }
390   }
391
392   // Open RunLoader from galice.root
393
394   TString gaPath(Form("%s/galice.root", fPath.Data()));
395   // If i use open directly, we get fatal.
396   // Is AccessPathName check ok for xrootd / alien? Yes, not for http.
397   if (gSystem->AccessPathName(gaPath, kReadPermission) == kFALSE)
398   {
399     fRunLoader = AliRunLoader::Open(gaPath, GetName());
400     if (fRunLoader)
401     {
402       TString alicePath = fPath + "/";
403       fRunLoader->SetDirName(alicePath);
404
405       if (fRunLoader->LoadgAlice() != 0)
406         Warning(kEH, "failed loading gAlice via run-loader.");
407
408       if (fRunLoader->LoadHeader() == 0)
409       {
410         if (runNo < 0)
411           runNo = fRunLoader->GetHeader()->GetRun();
412       }
413       else
414       {
415         Warning(kEH, "failed loading run-loader's header.");
416         delete fRunLoader;
417         fRunLoader = 0;
418       }
419     }
420     else // run-loader open failed
421     {
422       Warning(kEH, "failed opening ALICE run-loader from '%s'.", gaPath.Data());
423     }
424   }
425   else // galice not readable
426   {
427     Warning(kEH, "can not read '%s'.", gaPath.Data());
428   }
429   if (fRunLoader == 0)
430   {
431     if (fgAssertRunLoader)
432       throw (kEH + "Bootstraping of run-loader failed. Its precence was requested.");
433     else
434       Warning(kEH, "Bootstraping of run-loader failed.");
435   }
436
437   // Open raw-data file
438
439   TString rawPath(Form("%s/%s", fPath.Data(), fgRawFileName.Data()));
440   // If i use open directly, raw-reader reports an error but i have
441   // no way to detect it.
442   // Is this (AccessPathName check) ok for xrootd / alien? Yes, not for http.
443   AliLog::EType_t oldLogLevel = (AliLog::EType_t) AliLog::GetGlobalLogLevel();
444   if (fgAssertRaw == kFALSE)
445   {
446     AliLog::SetGlobalLogLevel(AliLog::kFatal);
447   }
448   if (gSystem->AccessPathName(rawPath, kReadPermission) == kFALSE)
449   {
450     fRawReader = AliRawReader::Create(rawPath);
451   }
452   else
453   {
454     fRawReader = AliRawReader::Create(fgRawFileName);
455   }
456   if (fgAssertRaw == kFALSE)
457   {
458     AliLog::SetGlobalLogLevel(oldLogLevel);
459   }
460
461   if (fRawReader == 0)
462   {
463     if (fgAssertRaw)
464     {
465       throw (kEH + "raw-data not initialized. Its precence was requested.");
466     } else {
467       Warning(kEH, "raw-data not initialized.");
468     }
469   }
470
471   if (runNo < 0)
472   {
473     if (fRawReader)
474     {
475       fRawReader->NextEvent();
476       runNo = fRawReader->GetRunNumber();
477       Info(kEH, "Determining run-no from raw ... run=%d.", runNo);
478       fRawReader->RewindEvents();
479     } else {
480       throw (kEH + "unknown run number.");
481     }
482   }
483
484   // Initialize OCDB ... only in master event-manager
485
486   if (this == fgMaster)
487   {
488     AliCDBManager* cdb = AliCDBManager::Instance();
489     if (cdb->IsDefaultStorageSet() == kTRUE)
490     {
491       Warning(kEH, "CDB already set - using the old storage:\n  '%s'",
492               cdb->GetDefaultStorage()->GetURI().Data());
493     }
494     else
495     {
496       cdb->SetDefaultStorage(fgCdbUri);
497       if (cdb->IsDefaultStorageSet() == kFALSE)
498         throw (kEH + "CDB initialization failed.");
499     }
500     cdb->SetRun(runNo);
501   }
502
503   fIsOpen = kTRUE;
504 }
505
506 void AliEveEventManager::SetEvent(AliRunLoader *runLoader, AliRawReader *rawReader, AliESDEvent *esd, AliESDfriend *esdf)
507 {
508   // Set an event from an external source.
509   // The method is used in the online visualisation.
510   // AOD is not supported.
511
512   static const TEveException kEH("AliEveEventManager::SetEvent ");
513
514   if (fIsOpen)
515   {
516     Warning(kEH, "Event-files were open. Closing and switching to external control.");
517     Close();
518   }
519
520   fRunLoader = runLoader;
521   fRawReader = rawReader;
522   fESD       = esd;
523   fESDfriend = esdf;
524   fAOD       = 0;
525
526   fEventId++;
527   fHasEvent     = kTRUE;
528   fExternalCtrl = kTRUE;
529
530   SetTitle("Online event in memory");
531   SetName ("Online Event");
532   ElementChanged();
533
534   AfterNewEventLoaded();
535
536   if (fAutoLoad) StartAutoLoadTimer();
537 }
538
539 Int_t AliEveEventManager::GetMaxEventId(Bool_t /*refreshESD*/) const
540 {
541   // Returns maximum available event id.
542   // If under external control or event is not opened -1 is returned.
543   // If raw-data is the only data-source this can not be known
544   // and 10,000,000 is returned.
545   // If neither data-source is initialised an exception is thrown.
546   // If refresh_esd is true and ESD is the primary event-data source
547   // its header is re-read from disk.
548
549   static const TEveException kEH("AliEveEventManager::GetMaxEventId ");
550
551   if (fExternalCtrl || fIsOpen == kFALSE)
552   {
553     return -1;
554   }
555
556   if (fESDTree)
557   {
558     // Refresh crashes with root-5.21.1-alice.
559     // Fixed by Philippe 5.8.2008 r25053, can be reactivated
560     // when we move to a newer root.
561     // if (refreshESD)
562     //   fESDTree->Refresh();
563     return fESDTree->GetEntries() - 1;
564   }
565   else if (fAODTree)
566   {
567     return fAODTree->GetEntries() - 1;
568   }
569   else if (fRunLoader)
570   {
571     return fRunLoader->GetNumberOfEvents() - 1;
572   }
573   else if (fRawReader)
574   {
575     Int_t n = fRawReader->GetNumberOfEvents() - 1;
576     return n > -1 ? n : 10000000;
577   }
578   else
579   {
580     throw (kEH + "neither ESD, AOD, RunLoader nor Raw loaded.");
581   }
582 }
583
584 void AliEveEventManager::GotoEvent(Int_t event)
585 {
586   // Load data for specified event.
587   // If event is out of range an exception is thrown and old state
588   // is preserved.
589   // After successful loading of event, the virtual function
590   // AfterNewEventLoaded() is called. This executes commands that
591   // were registered via TEveEventManager::AddNewEventCommand().
592   //
593   // If event is negative, it is subtracted from the number of
594   // available events, thus passing -1 will load the last event.
595   // This is not supported when raw-data is the only data-source
596   // as the number of events is not known.
597
598   static const TEveException kEH("AliEveEventManager::GotoEvent ");
599
600   if (fAutoLoadTimerRunning)
601   {
602     throw (kEH + "Event auto-load timer is running.");
603   }
604   if (fExternalCtrl)
605   {
606     throw (kEH + "Event-loop is under external control.");
607   }
608   else if (!fIsOpen)
609   {
610     throw (kEH + "Event-files not opened.");
611   }
612
613   fHasEvent = kFALSE;
614
615   Int_t maxEvent = 0;
616   if (fESDTree)
617   {
618     // Refresh crashes with root-5.21.1-alice.
619     // Fixed by Philippe 5.8.2008 r25053, can be reactivated
620     // when we move to a newer root.
621     // fESDTree->Refresh();
622     maxEvent = fESDTree->GetEntries() - 1;
623     if (event < 0)
624       event = fESDTree->GetEntries() + event;
625   }
626   else if (fAODTree)
627   {
628     maxEvent = fAODTree->GetEntries() - 1;
629     if (event < 0)
630       event = fAODTree->GetEntries() + event;
631   }
632   else if (fRunLoader)
633   {
634     maxEvent = fRunLoader->GetNumberOfEvents() - 1;
635     if (event < 0)
636       event = fRunLoader->GetNumberOfEvents() + event;
637   }
638   else if (fRawReader)
639   {
640     maxEvent = fRawReader->GetNumberOfEvents() - 1;
641     if (maxEvent < 0)
642     {
643       maxEvent = 10000000;
644       if (event < 0) {
645         Error(kEH, "current raw-data source does not support direct event access.");
646         return;
647       }
648       Info(kEH, "number of events unknown for current raw-data source, setting max-event id to 10M.");
649     }
650     else
651     {
652       if (event < 0)
653         event = fRawReader->GetNumberOfEvents() + event;
654     }
655   }
656   else
657   {
658     throw (kEH + "neither RunLoader, ESD nor Raw loaded.");
659   }
660   if (event < 0 || event > maxEvent)
661   {
662     throw (kEH + Form("event %d not present, available range [%d, %d].",
663                       event, 0, maxEvent));
664   }
665
666   TEveManager::TRedrawDisabler rd(gEve);
667   gEve->Redraw3D(kFALSE, kTRUE); // Enforce drop of all logicals.
668
669   // !!! MT this is somewhat brutal; at least optionally, one could be
670   // a bit gentler, checking for objs owning their external refs and having
671   // additinal parents.
672   DestroyElements();
673
674   if (fESDTree) {
675     if (fESDTree->GetEntry(event) <= 0)
676       throw (kEH + "failed getting required event from ESD.");
677
678     if (fESDfriendExists)
679       fESD->SetESDfriend(fESDfriend);
680   }
681
682   if (fAODTree) {
683     if (fAODTree->GetEntry(event) <= 0)
684       throw (kEH + "failed getting required event from AOD.");
685   }
686
687   if (fRunLoader) {
688     if (fRunLoader->GetEvent(event) != 0)
689       throw (kEH + "failed getting required event.");
690   }
691
692   if (fRawReader)
693   {
694     // AliRawReader::GotoEvent(Int_t) works for AliRawReaderRoot/Chain.
695     if (fRawReader->GotoEvent(event) == kFALSE)
696     {
697       // Use fallback method - iteration with NextEvent().
698       Int_t rawEv = fEventId;
699       if (event < rawEv)
700       {
701         fRawReader->RewindEvents();
702         rawEv = -1;
703       }
704
705       while (rawEv < event)
706       {
707         if ( ! fRawReader->NextEvent())
708         {
709           fRawReader->RewindEvents();
710           fEventId = -1;
711           throw (kEH + Form("Error going to next raw-event from event %d.", rawEv));
712         }
713         ++rawEv;
714       }
715       Warning(kEH, "Loaded raw-event %d with fallback method.\n", rawEv);
716     }
717   }
718
719   fHasEvent = kTRUE;
720   fEventId  = event;
721   if (this == fgMaster)
722   {
723     SetName(Form("Event %d", fEventId));
724     ElementChanged();
725   }
726
727   AfterNewEventLoaded();
728 }
729
730 void AliEveEventManager::NextEvent()
731 {
732   // Loads next event.
733   // Does magick needed for online display when under external event control.
734
735   static const TEveException kEH("AliEveEventManager::NextEvent ");
736
737   if (fAutoLoadTimerRunning)
738   {
739     throw (kEH + "Event auto-load timer is running.");
740   }
741
742   if (fExternalCtrl)
743   {
744     // !!! This should really go somewhere else. It is done in GotoEvent(),
745     // so here we should do it in SetEvent().
746     DestroyElements();
747
748     gSystem->ExitLoop();
749   }
750   else
751   {
752     Int_t nexteventbytrigger=0;
753     if (fSelectOnTriggerType)
754     {
755       if (FindNextByTrigger(nexteventbytrigger)) //if not found do nothing
756         GotoEvent(nexteventbytrigger);
757     }
758     else if (fEventId < GetMaxEventId(kTRUE))
759       GotoEvent(fEventId + 1);
760     else
761       GotoEvent(0);
762   }
763 }
764
765 void AliEveEventManager::PrevEvent()
766 {
767   // Loads previous event.
768
769   static const TEveException kEH("AliEveEventManager::PrevEvent ");
770
771   if (fAutoLoadTimerRunning)
772   {
773     throw (kEH + "Event auto-load timer is running.");
774   }
775   if (fExternalCtrl)
776   {
777     throw (kEH + "Event-loop is under external control.");
778   }
779   Int_t nexteventbytrigger=0;
780   if (fSelectOnTriggerType)
781   {
782     if (FindPrevByTrigger(nexteventbytrigger))
783       GotoEvent(nexteventbytrigger);
784   }
785   else
786     GotoEvent(fEventId - 1);
787 }
788
789 void AliEveEventManager::Close()
790 {
791   // Close the event data-files and delete ESD, ESDfriend, run-loader
792   // and raw-reader.
793
794   static const TEveException kEH("AliEveEventManager::Close ");
795
796   if (!fIsOpen)
797   {
798     throw (kEH + "Event-files not opened.");
799   }
800
801   if (fAutoLoadTimerRunning)
802     StopAutoLoadTimer();
803
804   if (fESDTree) {
805     delete fESD;       fESD       = 0;
806     delete fESDfriend; fESDfriend = 0;
807     fESDfriendExists = kFALSE;
808
809     delete fESDTree;   fESDTree = 0;
810     delete fESDFile;   fESDFile = 0;
811   }
812
813   if (fAODTree) {
814     delete fAOD;       fAOD       = 0;
815
816     delete fAODTree;   fAODTree = 0;
817     delete fAODFile;   fAODFile = 0;
818   }
819
820   if (fRunLoader) {
821     delete fRunLoader; fRunLoader = 0;
822   }
823
824   if (fRawReader) {
825     delete fRawReader; fRawReader = 0;
826   }
827
828   fEventId  = -1;
829   fIsOpen   = kFALSE;
830   fHasEvent = kFALSE;
831 }
832
833
834 //------------------------------------------------------------------------------
835 // Static convenience functions, mainly used from macros.
836 //------------------------------------------------------------------------------
837
838 Bool_t AliEveEventManager::HasRunLoader()
839 {
840   // Check if AliRunLoader is initialized.
841
842   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fRunLoader;
843 }
844
845 Bool_t AliEveEventManager::HasESD()
846 {
847   // Check if AliESDEvent is initialized.
848
849   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fESD;
850 }
851
852 Bool_t AliEveEventManager::HasESDfriend()
853 {
854   // Check if AliESDfriend is initialized.
855
856   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fESDfriend;
857 }
858
859 Bool_t AliEveEventManager::HasAOD()
860 {
861   // Check if AliESDEvent is initialized.
862
863   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fAOD;
864 }
865
866 Bool_t AliEveEventManager::HasRawReader()
867 {
868   // Check if raw-reader is initialized.
869
870   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fRawReader;
871 }
872
873 AliRunLoader* AliEveEventManager::AssertRunLoader()
874 {
875   // Make sure AliRunLoader is initialized and return it.
876   // Throws exception in case run-loader is not available.
877   // Static utility for macros.
878
879   static const TEveException kEH("AliEveEventManager::AssertRunLoader ");
880
881   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
882     throw (kEH + "ALICE event not ready.");
883   if (fgCurrent->fRunLoader == 0)
884     throw (kEH + "AliRunLoader not initialised.");
885   return fgCurrent->fRunLoader;
886 }
887
888 AliESDEvent* AliEveEventManager::AssertESD()
889 {
890   // Make sure AliESDEvent is initialized and return it.
891   // Throws exception in case ESD is not available.
892   // Static utility for macros.
893
894   static const TEveException kEH("AliEveEventManager::AssertESD ");
895
896   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
897     throw (kEH + "ALICE event not ready.");
898   if (fgCurrent->fESD == 0)
899     throw (kEH + "AliESD not initialised.");
900   return fgCurrent->fESD;
901 }
902
903 AliESDfriend* AliEveEventManager::AssertESDfriend()
904 {
905   // Make sure AliESDfriend is initialized and return it.
906   // Throws exception in case ESDfriend-loader is not available.
907   // Static utility for macros.
908
909   static const TEveException kEH("AliEveEventManager::AssertESDfriend ");
910
911   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
912     throw (kEH + "ALICE event not ready.");
913   if (fgCurrent->fESDfriend == 0)
914     throw (kEH + "AliESDfriend not initialised.");
915   return fgCurrent->fESDfriend;
916 }
917
918 AliAODEvent* AliEveEventManager::AssertAOD()
919 {
920   // Make sure AliAODEvent is initialized and return it.
921   // Throws exception in case AOD is not available.
922   // Static utility for macros.
923
924   static const TEveException kEH("AliEveEventManager::AssertAOD ");
925
926   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
927     throw (kEH + "ALICE event not ready.");
928   if (fgCurrent->fAOD == 0)
929     throw (kEH + "AliAOD not initialised.");
930   return fgCurrent->fAOD;
931 }
932
933 AliRawReader* AliEveEventManager::AssertRawReader()
934 {
935   // Make sure raw-reader is initialized and return it.
936
937   static const TEveException kEH("AliEveEventManager::AssertRawReader ");
938
939   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
940     throw (kEH + "ALICE event not ready.");
941   if (fgCurrent->fRawReader == 0)
942     throw (kEH + "RawReader not ready.");
943
944   return fgCurrent->fRawReader;
945 }
946
947 AliMagF* AliEveEventManager::AssertMagField()
948 {
949   // Make sure AliMagF is initialized and returns it.
950   // Run-loader must be initialized to get the correct magnetic field!
951   // Throws exception in case magnetic field is not available.
952   // Static utility for macros.
953
954   // !!!! This should be fixed ... get field also in some other way,
955   // not only via run-loader.
956
957   static const TEveException kEH("AliEveEventManager::AssertMagField ");
958
959   if (fgMagField == 0)
960   {
961     if (fgMaster && fgMaster->fRunLoader && fgMaster->fRunLoader->GetAliRun())
962     {
963       ::Info(kEH, "Retrieving magnetic field from AliRun.");
964       fgMagField = fgMaster->fRunLoader->GetAliRun()->Field();
965     }
966     else
967     {
968       ::Warning(kEH, "Instantiating default magnetic field (5kG).");
969       fgMagField = new AliMagFMaps("Maps","Maps", 1, 1., 10., AliMagFMaps::k5kG);
970     }
971   }
972   return fgMagField;
973 }
974
975 TGeoManager* AliEveEventManager::AssertGeometry()
976 {
977   // Make sure AliGeomManager is initialized and returns the
978   // corresponding TGeoManger.
979   // gGeoManager is set to the return value.
980   // Throws exception if geometry can not be loaded or if it is not
981   // available and the TGeoManager is locked.
982   // Static utility for macros.
983
984   static const TEveException kEH("AliEveEventManager::AssertGeometry ");
985
986   if (AliGeomManager::GetGeometry() == 0)
987   {
988     if (TGeoManager::IsLocked())
989       throw (kEH + "geometry is not loaded but TGeoManager is locked.");
990
991     gGeoManager = 0;
992     AliGeomManager::LoadGeometry();
993     if ( ! AliGeomManager::GetGeometry())
994     {
995       throw (kEH + "can not load geometry.");
996     }
997     if ( ! AliGeomManager::ApplyAlignObjsFromCDB("ITS TPC TRD TOF PHOS HMPID EMCAL MUON FMD ZDC PMD T0 VZERO ACORDE"))
998     {
999       ::Warning(kEH, "mismatch of alignable volumes. Proceeding.");
1000       // throw (kEH + "could not apply align objs.");
1001     }
1002     AliGeomManager::GetGeometry()->DefaultColors();
1003   }
1004
1005   gGeoManager = AliGeomManager::GetGeometry();
1006   return gGeoManager;
1007 }
1008
1009 //------------------------------------------------------------------------------
1010
1011 AliEveEventManager* AliEveEventManager::AddDependentManager(const TString& name, const TString& path)
1012 {
1013   // Create and attach a dependent event-manager.
1014   // It is not added into eve list tree.
1015
1016   static const TEveException kEH("AliEveEventManager::AddDependentManager ");
1017
1018   if (fgMaster == 0)
1019     throw(kEH + "Master event-manager must be instantiated first.");
1020
1021   if (fgMaster->fSubManagers == 0)
1022   {
1023     fgMaster->fSubManagers = new TList;
1024     fgMaster->fSubManagers->SetOwner(kTRUE);
1025   }
1026
1027   AliEveEventManager* new_mgr = 0;
1028   fgCurrent = 0;
1029   try
1030   {
1031     new_mgr = new AliEveEventManager(name, path, fgMaster->fEventId);
1032     fgMaster->fSubManagers->Add(new_mgr);
1033   }
1034   catch (TEveException& exc)
1035   {
1036     ::Error(kEH, "Creation of new event-manager failed: '%s'.", exc.Data());
1037   }
1038   fgCurrent = fgMaster;
1039
1040   return new_mgr;
1041 }
1042
1043 AliEveEventManager* AliEveEventManager::GetDependentManager(const TString& name)
1044 {
1045   // Get a dependant manager by name.
1046   // This will not change the current manager, use helper class
1047   // AliEveEventManager::CurrentChanger for that.
1048
1049   static const TEveException kEH("AliEveEventManager::GetDependentManager ");
1050
1051   if (fgMaster == 0)
1052     throw(kEH + "Master event-manager must be instantiated first.");
1053
1054   if (fgMaster->fSubManagers == 0)
1055     return 0;
1056
1057   return dynamic_cast<AliEveEventManager*>(fgMaster->fSubManagers->FindObject(name));
1058 }
1059
1060 AliEveEventManager* AliEveEventManager::GetMaster()
1061 {
1062   // Get master event-manager.
1063
1064   return fgMaster;
1065 }
1066
1067 AliEveEventManager* AliEveEventManager::GetCurrent()
1068 {
1069   // Get current event-manager.
1070
1071   return fgCurrent;
1072 }
1073
1074 //------------------------------------------------------------------------------
1075 // Autoloading of events
1076 //------------------------------------------------------------------------------
1077
1078 void AliEveEventManager::SetAutoLoadTime(Float_t time)
1079 {
1080   // Set the auto-load time in seconds
1081
1082   fAutoLoadTime = time;
1083 }
1084
1085 void AliEveEventManager::SetAutoLoad(Bool_t autoLoad)
1086 {
1087   // Set the automatic event loading mode
1088
1089   static const TEveException kEH("AliEveEventManager::SetAutoLoad ");
1090
1091   if (fAutoLoad == autoLoad)
1092   {
1093     Warning(kEH, "Setting autoload to the same value as before - %s. Ignoring.", fAutoLoad ? "true" : "false");
1094     return;
1095   }
1096
1097   fAutoLoad = autoLoad;
1098   if (fAutoLoad)
1099   {
1100     StartAutoLoadTimer();
1101   }
1102   else
1103   {
1104     StopAutoLoadTimer();
1105   }
1106 }
1107
1108 void AliEveEventManager::StartAutoLoadTimer()
1109 {
1110   // Start the auto-load timer.
1111
1112   fAutoLoadTimer->SetTime((Long_t)(1000*fAutoLoadTime));
1113   fAutoLoadTimer->Reset();
1114   fAutoLoadTimer->TurnOn();
1115   fAutoLoadTimerRunning = kTRUE;
1116 }
1117
1118 void AliEveEventManager::StopAutoLoadTimer()
1119 {
1120   // Stop the auto-load timer.
1121
1122   fAutoLoadTimerRunning = kFALSE;
1123   fAutoLoadTimer->TurnOff();
1124 }
1125
1126 void AliEveEventManager::AutoLoadNextEvent()
1127 {
1128   // Called from auto-load timer, so it has to be public.
1129   // Do NOT call it directly.
1130
1131   static const TEveException kEH("AliEveEventManager::AutoLoadNextEvent ");
1132
1133   if ( ! fAutoLoadTimerRunning || ! fAutoLoadTimer->HasTimedOut())
1134   {
1135     Warning(kEH, "Called unexpectedly - ignoring the call. Should ONLY be called from an internal timer.");
1136     return;
1137   }
1138
1139   StopAutoLoadTimer();
1140   NextEvent();
1141   if (fAutoLoad && !fExternalCtrl)
1142     StartAutoLoadTimer();
1143 }
1144
1145
1146 //------------------------------------------------------------------------------
1147 // Event selection by trigger
1148 //------------------------------------------------------------------------------
1149
1150 Bool_t AliEveEventManager::FindNextByTrigger(Int_t& event)
1151 {
1152   // Find next event that matches the trigger.
1153   // If a matching event is not found, we loop around and eventually
1154   // end up at the same event.
1155
1156   static const TEveException kEH("AliEveEventManager::FindNextByTrigger ");
1157
1158   if (!fESDTree) return kFALSE;
1159   TString firedtrclasses;
1160   for (Int_t i = fEventId+1; i<GetMaxEventId(kTRUE)+1; i++)
1161   {
1162     if (fESDTree->GetEntry(i) <= 0)
1163       throw (kEH + "failed getting required event from ESD.");
1164     firedtrclasses = fESD->GetFiredTriggerClasses();
1165     if (firedtrclasses.Contains(fTriggerType))
1166     {
1167       event=i;
1168       return kTRUE;
1169     }
1170   }
1171   for (Int_t i = 0; i<fEventId+1; i++)
1172   {
1173     if (fESDTree->GetEntry(i) <= 0)
1174       throw (kEH + "failed getting required event from ESD.");
1175     firedtrclasses = fESD->GetFiredTriggerClasses();
1176     if (firedtrclasses.Contains(fTriggerType))
1177     {
1178       event=i;
1179       return kTRUE;
1180     }
1181   }
1182   return kFALSE;
1183 }
1184
1185 Bool_t AliEveEventManager::FindPrevByTrigger(Int_t& event)
1186 {
1187   // Find previous event that matches the trigger.
1188
1189   static const TEveException kEH("AliEveEventManager::FindPrevByTrigger ");
1190
1191   if (!fESDTree) return kFALSE;
1192   TString firedtrclasses;
1193   for (Int_t i = fEventId-1; i>=0; i--)
1194   {
1195     if (fESDTree->GetEntry(i) <= 0)
1196       throw (kEH + "failed getting required event from ESD.");
1197     firedtrclasses = fESD->GetFiredTriggerClasses();
1198     if (firedtrclasses.Contains(fTriggerType))
1199     {
1200       event=i;
1201       return kTRUE;
1202     }
1203   }
1204   for (Int_t i = GetMaxEventId(kTRUE); i>fEventId-1; i--)
1205   {
1206     if (fESDTree->GetEntry(i) <= 0)
1207       throw (kEH + "failed getting required event from ESD.");
1208     firedtrclasses = fESD->GetFiredTriggerClasses();
1209     if (firedtrclasses.Contains(fTriggerType))
1210     {
1211       event=i;
1212       return kTRUE;
1213     }
1214   }
1215   return kFALSE;
1216 }
1217
1218
1219 //------------------------------------------------------------------------------
1220 // Post event-loading functions
1221 //------------------------------------------------------------------------------
1222
1223 void AliEveEventManager::AfterNewEventLoaded()
1224 {
1225   // Execute registered macros and commands.
1226   // At the end emit NewEventLoaded signal.
1227   //
1228   // Virtual from TEveEventManager.
1229
1230   static const TEveException kEH("AliEveEventManager::AfterNewEventLoaded ");
1231
1232   if (fExecutor)
1233     fExecutor->ExecMacros();
1234
1235   TEveEventManager::AfterNewEventLoaded();
1236
1237   NewEventLoaded();
1238
1239   if (this == fgMaster && fSubManagers != 0)
1240   {
1241     TIter next(fSubManagers);
1242     while ((fgCurrent = dynamic_cast<AliEveEventManager*>(next())) != 0)
1243     {
1244       // gEve->SetCurrentEvent(fgCurrent);
1245       try
1246       {
1247         fgCurrent->GotoEvent(fEventId);
1248       }
1249       catch (TEveException& exc)
1250       {
1251         // !!! Should somehow tag / disable / remove it?
1252         Error(kEH, "Getting event %d for sub-event-manager '%s' failed: '%s'.",
1253               fEventId, fgCurrent->GetName(), exc.Data());
1254       }
1255     }
1256     fgCurrent = fgMaster;
1257     // gEve->SetCurrentEvent(fgMaster);
1258   }
1259 }
1260
1261 void AliEveEventManager::NewEventLoaded()
1262 {
1263   // Emit NewEventLoaded signal.
1264
1265   Emit("NewEventLoaded()");
1266 }
1267
1268
1269 //------------------------------------------------------------------------------
1270 // Event info dumpers
1271 //------------------------------------------------------------------------------
1272
1273 TString AliEveEventManager::GetEventInfoHorizontal() const
1274 {
1275   // Dumps the event-header contents in vertical formatting.
1276
1277   TString rawInfo, esdInfo;
1278
1279   if (!fRawReader)
1280   {
1281     rawInfo = "No raw-data event info is available!\n";
1282   }
1283   else
1284   {
1285     const UInt_t* attr = fRawReader->GetAttributes();
1286     TTimeStamp ts(fRawReader->GetTimestamp());
1287     rawInfo.Form("RAW event info: Run#: %d  Event type: %d (%s)  Period: %x  Orbit: %x  BC: %x\n"
1288                  "Trigger: %llx\nDetectors: %x (%s)\nAttributes:%x-%x-%x  Timestamp: %s\n",
1289                  fRawReader->GetRunNumber(),fRawReader->GetType(),AliRawEventHeaderBase::GetTypeName(fRawReader->GetType()),
1290                  fRawReader->GetPeriod(),fRawReader->GetOrbitID(),fRawReader->GetBCID(),
1291                  fRawReader->GetClassMask(),
1292                  *fRawReader->GetDetectorPattern(),AliDAQ::ListOfTriggeredDetectors(*fRawReader->GetDetectorPattern()),
1293                  attr[0],attr[1],attr[2], ts.AsString("s"));
1294   }
1295
1296   if (!fESD)
1297   {
1298     esdInfo = "No ESD event info is available!";
1299   }
1300   else
1301   {
1302     TString acttrclasses   = fESD->GetESDRun()->GetActiveTriggerClasses();
1303     TString firedtrclasses = fESD->GetFiredTriggerClasses();
1304     TTimeStamp ts(fESD->GetTimeStamp());
1305     esdInfo.Form("ESD event info: Run#: %d  Event type: %d (%s)  Period: %x  Orbit: %x  BC: %x\n"
1306                  "Active trigger classes: %s\nTrigger: %llx (%s)\nEvent# in file: %d  Timestamp: %s, MagField: %.2e",
1307                  fESD->GetRunNumber(),
1308                  fESD->GetEventType(),AliRawEventHeaderBase::GetTypeName(fESD->GetEventType()),
1309                  fESD->GetPeriodNumber(),fESD->GetOrbitNumber(),fESD->GetBunchCrossNumber(),
1310                  acttrclasses.Data(),
1311                  fESD->GetTriggerMask(),firedtrclasses.Data(),
1312                  fESD->GetEventNumberInFile(), ts.AsString("s"), fESD->GetMagneticField());
1313   }
1314
1315   return rawInfo + esdInfo;
1316 }
1317
1318 TString AliEveEventManager::GetEventInfoVertical() const
1319 {
1320   // Dumps the event-header contents in vertical formatting.
1321
1322   TString rawInfo, esdInfo;
1323
1324   if (!fRawReader)
1325   {
1326     rawInfo = "No raw-data event info is available!\n";
1327   }
1328   else
1329   {
1330     const UInt_t* attr = fRawReader->GetAttributes();
1331     rawInfo.Form("Raw-data event info:\nRun#: %d\nEvent type: %d (%s)\nPeriod: %x\nOrbit: %x   BC: %x\nTrigger: %llx\nDetectors: %x (%s)\nAttributes:%x-%x-%x\nTimestamp: %x\n",
1332                  fRawReader->GetRunNumber(),fRawReader->GetType(),AliRawEventHeaderBase::GetTypeName(fRawReader->GetType()),
1333                  fRawReader->GetPeriod(),fRawReader->GetOrbitID(),fRawReader->GetBCID(),
1334                  fRawReader->GetClassMask(),
1335                  *fRawReader->GetDetectorPattern(),AliDAQ::ListOfTriggeredDetectors(*fRawReader->GetDetectorPattern()),
1336                  attr[0],attr[1],attr[2],
1337                  fRawReader->GetTimestamp());
1338   }
1339
1340   if (!fESD)
1341   {
1342     esdInfo = "No ESD event info is available!\n";
1343   }
1344   else
1345   {
1346     TString acttrclasses   = fESD->GetESDRun()->GetActiveTriggerClasses();
1347     TString firedtrclasses = fESD->GetFiredTriggerClasses();
1348     esdInfo.Form("ESD event info:\nRun#: %d\nActive trigger classes: %s\nEvent type: %d (%s)\nPeriod: %x\nOrbit: %x   BC: %x\nTrigger: %llx (%s)\nEvent# in file:%d\nTimestamp: %x\n",
1349                  fESD->GetRunNumber(),
1350                  acttrclasses.Data(),
1351                  fESD->GetEventType(),AliRawEventHeaderBase::GetTypeName(fESD->GetEventType()),
1352                  fESD->GetPeriodNumber(),fESD->GetOrbitNumber(),fESD->GetBunchCrossNumber(),
1353                  fESD->GetTriggerMask(),firedtrclasses.Data(),
1354                  fESD->GetEventNumberInFile(),
1355                  fESD->GetTimeStamp());
1356   }
1357
1358   return rawInfo + "\n" + esdInfo;
1359 }