* EveBase/AliEveEventManager.cxx
[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 <AliMagF.h>
27 #include <AliCDBManager.h>
28 #include <AliCDBStorage.h>
29 #include <AliCDBEntry.h>
30 #include <AliGRPObject.h>
31 #include <AliHeader.h>
32 #include <AliGeomManager.h>
33
34 #include <TFile.h>
35 #include <TTree.h>
36 #include <TGeoManager.h>
37 #include <TGeoGlobalMagField.h>
38 #include <TSystem.h>
39 #include <TTimeStamp.h>
40 #include <TPRegexp.h>
41 #include <TError.h>
42
43 //==============================================================================
44 //==============================================================================
45 // AliEveEventManager
46 //==============================================================================
47
48 //______________________________________________________________________________
49 //
50 // Provides interface for loading and navigating standard AliRoot data
51 // (AliRunLoader), ESD, AOD and RAW.
52 //
53 // ESDfriend is attached automatically, if the file is found.
54 //
55 // AODfriends are not attached automatically as there are several
56 // possible files involved. To have a specific AODfriend attached, call
57 // static method
58 //   AliEveEventManager::AddAODfriend("AliAOD.VertexingHF.root");
59 // before initializing the event-manager.
60 //
61 // Also provides interface to magnetic-field and geometry. Mostly
62 // intended as wrappers over standard AliRoot functionality for
63 // convenient use from visualizateion macros.
64 //
65 // There can be a single main event-manger, it is stored in private
66 // data member fgMaster and can be accessed via static member function
67 // GetMaster().
68 //
69 // For event overlaying and embedding one can instantiate additional
70 // event-managers via static method AddDependentManager(const TString& path).
71 // This interface is under development.
72
73 ClassImp(AliEveEventManager)
74
75 Bool_t AliEveEventManager::fgAssertRunLoader = kFALSE;
76 Bool_t AliEveEventManager::fgAssertESD       = kFALSE;
77 Bool_t AliEveEventManager::fgAssertAOD       = kFALSE;
78 Bool_t AliEveEventManager::fgAssertRaw       = kFALSE;
79
80 TString  AliEveEventManager::fgESDFileName("AliESDs.root");
81 TString  AliEveEventManager::fgAODFileName("AliAOD.root");
82 TString  AliEveEventManager::fgRawFileName("raw.root");
83 TString  AliEveEventManager::fgCdbUri("local://$ALICE_ROOT/OCDB");
84
85 TList*   AliEveEventManager::fgAODfriends = 0;
86
87 AliGRPObject* AliEveEventManager::fgGRPData      = 0;
88 AliMagF*      AliEveEventManager::fgMagField     = 0;
89 Bool_t        AliEveEventManager::fgUniformField = kFALSE;
90
91 AliEveEventManager* AliEveEventManager::fgMaster  = 0;
92 AliEveEventManager* AliEveEventManager::fgCurrent = 0;
93
94 void AliEveEventManager::InitInternals()
95 {
96   // Initialize internal members.
97
98   static const TEveException kEH("AliEveEventManager::InitInternals ");
99
100   if (fgCurrent != 0)
101   {
102     throw(kEH + "Dependent event-managers should be created via static method AddDependentManager().");
103   }
104
105   if (fgMaster == 0)
106   {
107     fgMaster = this;
108   }
109
110   fgCurrent = this;
111
112   fAutoLoadTimer = new TTimer;
113   fAutoLoadTimer->Connect("Timeout()", "AliEveEventManager", this, "AutoLoadNextEvent()");
114
115   fExecutor = new AliEveMacroExecutor;
116
117   fTransients = new TEveElementList("Transients", "Transient per-event elements.");
118   fTransients->IncDenyDestroy();
119   gEve->AddToListTree(fTransients, kFALSE);
120
121   fTransientLists = new TEveElementList("Transient Lists", "Containers of transient elements.");
122   fTransientLists->IncDenyDestroy();
123   gEve->AddToListTree(fTransientLists, kFALSE);
124 }
125
126 AliEveEventManager::AliEveEventManager(const TString& name) :
127   TEveEventManager(name),
128
129   fPath      ( ), fEventId (-1),
130   fRunLoader (0),
131   fESDFile   (0), fESDTree (0), fESD (0),
132   fESDfriend (0), fESDfriendExists(kFALSE),
133   fAODFile   (0), fAODTree (0), fAOD (0),
134   fRawReader (0),
135   fAutoLoad  (kFALSE), fAutoLoadTime (5.),     fAutoLoadTimer(0),
136   fIsOpen    (kFALSE), fHasEvent     (kFALSE), fExternalCtrl (kFALSE),
137   fSelectOnTriggerType(kFALSE), fTriggerType(""),
138   fExecutor    (0), fTransients(0), fTransientLists(0),
139   fSubManagers (0),
140   fAutoLoadTimerRunning(kFALSE)
141 {
142   // Default constructor.
143
144   InitInternals();
145 }
146
147 AliEveEventManager::AliEveEventManager(const TString& name, const TString& path, Int_t ev) :
148   TEveEventManager(name, path),
149
150   fPath   (path), fEventId(-1),
151   fRunLoader (0),
152   fESDFile   (0), fESDTree (0), fESD (0),
153   fESDfriend (0), fESDfriendExists(kFALSE),
154   fAODFile   (0), fAODTree (0), fAOD (0),
155   fRawReader (0),
156   fAutoLoad  (kFALSE), fAutoLoadTime (5),      fAutoLoadTimer(0),
157   fIsOpen    (kFALSE), fHasEvent     (kFALSE), fExternalCtrl (kFALSE),
158   fSelectOnTriggerType(kFALSE), fTriggerType(""),
159   fExecutor    (0), fTransients(0), fTransientLists(0),
160   fSubManagers (0),
161   fAutoLoadTimerRunning(kFALSE)
162 {
163   // Constructor with event-directory URL and event-id.
164
165   InitInternals();
166
167   Open();
168   if (ev >= 0)
169   {
170     GotoEvent(ev);
171   }
172 }
173
174 AliEveEventManager::~AliEveEventManager()
175 {
176   // Destructor.
177
178   delete fSubManagers;
179
180   if (fIsOpen)
181   {
182     Close();
183   }
184
185   fTransients->DecDenyDestroy();
186   fTransients->Destroy();
187
188   fTransientLists->DecDenyDestroy();
189   fTransientLists->Destroy();
190 }
191
192 /******************************************************************************/
193
194 void AliEveEventManager::SetESDFileName(const TString& esd)
195 {
196   // Set file-name for opening ESD, default "AliESDs.root".
197
198   if ( ! esd.IsNull()) fgESDFileName = esd;
199 }
200
201 void AliEveEventManager::SetAODFileName(const TString& aod)
202 {
203   // Set file-name for opening AOD, default "AliAOD.root".
204
205   if ( ! aod.IsNull()) fgAODFileName = aod;
206 }
207
208 void AliEveEventManager::AddAODfriend(const TString& friendFileName)
209 {
210   // Add new AOD friend file-name to be attached when opening AOD.
211   // This should include '.root', as in 'AliAOD.VertexingHF.root'.
212
213   if (fgAODfriends == 0)
214   {
215     fgAODfriends = new TList;
216     fgAODfriends->SetOwner(kTRUE);
217   }
218   fgAODfriends->Add(new TObjString(friendFileName));
219 }
220
221 void AliEveEventManager::SetRawFileName(const TString& raw)
222 {
223   // Set file-name for opening of raw-data, default "raw.root"
224   if ( ! raw.IsNull()) fgRawFileName = raw;
225 }
226
227 void AliEveEventManager::SetCdbUri(const TString& cdb)
228 {
229   // Set path to CDB, default "local://$ALICE_ROOT/OCDB".
230
231   if ( ! cdb.IsNull()) fgCdbUri = cdb;
232 }
233
234 void AliEveEventManager::SetAssertElements(Bool_t assertRunloader, Bool_t assertEsd,
235                                            Bool_t assertAod, Bool_t assertRaw)
236 {
237   // Set global flags that detrmine which parts of the event-data must
238   // be present when the event is opened.
239
240   fgAssertRunLoader = assertRunloader;
241   fgAssertESD = assertEsd;
242   fgAssertAOD = assertAod;
243   fgAssertRaw = assertRaw;
244 }
245
246 /******************************************************************************/
247
248 void AliEveEventManager::Open()
249 {
250   // Open event-data from URL specified in fPath.
251   // Attempts to create AliRunLoader() and to open ESD with ESDfriends.
252   // Warning is reported if run-loader or ESD is not found.
253   // Global data-members fgAssertRunLoader and fgAssertESD can be set
254   // to throw exceptions instead.
255
256   static const TEveException kEH("AliEveEventManager::Open ");
257
258   if (fExternalCtrl)
259   {
260     throw (kEH + "Event-loop is under external control.");
261   }
262   if (fIsOpen)
263   {
264     throw (kEH + "Event-files already opened.");
265   }
266
267   gSystem->ExpandPathName(fPath);
268   // The following magick is required for ESDfriends to be loaded properly
269   // from non-current directory.
270   if (fPath.IsNull() || fPath == ".")
271   {
272     fPath = gSystem->WorkingDirectory();
273   }
274   else if ( ! fPath.BeginsWith("file:/"))
275   {
276     TUrl    url(fPath, kTRUE);
277     TString protocol(url.GetProtocol());
278     if (protocol == "file" && fPath[0] != '/')
279       fPath = Form("%s/%s", gSystem->WorkingDirectory(), fPath.Data());
280   }
281
282   Int_t runNo = -1;
283
284   // Open ESD and ESDfriends
285
286   TString esdPath(Form("%s/%s", fPath.Data(), fgESDFileName.Data()));
287   if ((fESDFile = TFile::Open(esdPath)))
288   {
289     fESD = new AliESDEvent();
290     fESDTree = (TTree*) fESDFile->Get("esdTree");
291     if (fESDTree != 0)
292     {
293       // Check if ESDfriends exists and attach the branch.
294       // We use TFile::Open() instead of gSystem->AccessPathName
295       // as it seems to work better when attachine alieve to a
296       // running reconstruction process with auto-save on.
297       // There was also a problem with TTree::Refresh() - it didn't
298       // save the friend branch on a separate file, fixed in 5.22.2 -
299       // so we might want to try the old way again soon.
300       TString p(Form("%s/AliESDfriends.root", fPath.Data()));
301       TFile *esdFriendFile = TFile::Open(p);
302       if (esdFriendFile)
303       {
304         if (!esdFriendFile->IsZombie())
305         {
306           esdFriendFile->Close();
307           fESDfriendExists = kTRUE;
308           fESDTree->SetBranchStatus ("ESDfriend*", 1);
309         }
310         delete esdFriendFile;
311       }
312
313       fESD->ReadFromTree(fESDTree);
314       if (fESDfriendExists)
315       {
316         fESDfriend = (AliESDfriend*) fESD->FindListObject("AliESDfriend");
317         Info(kEH, "found and attached ESD friend.");
318       }
319       else
320       {
321         Warning(kEH, "ESDfriend not found.");
322       }
323
324       if (fESDTree->GetEntry(0) <= 0)
325       {
326         delete fESDFile; fESDFile = 0;
327         delete fESD; fESD = 0;
328         Warning(kEH, "failed getting the first entry from esdTree.");
329       }
330       else
331       {
332         if (runNo < 0)
333           runNo = fESD->GetESDRun()->GetRunNumber();
334       }
335     }
336     else // esdtree == 0
337     {
338       delete fESDFile; fESDFile = 0;
339       delete fESD; fESD = 0;
340       Warning(kEH, "failed getting the esdTree.");
341     }
342   }
343   else // esd not readable
344   {
345     Warning(kEH, "can not read ESD file '%s'.", esdPath.Data());
346   }
347   if (fESDTree == 0)
348   {
349     if (fgAssertESD)
350     {
351       throw (kEH + "ESD not initialized. Its precence was requested.");
352     } else {
353       Warning(kEH, "ESD not initialized.");
354     }
355   }
356
357   // Open AOD and registered friends
358
359   TString aodPath(Form("%s/%s", fPath.Data(), fgAODFileName.Data()));
360   if ((fAODFile = TFile::Open(aodPath)))
361   {
362     fAOD = new AliAODEvent();
363     fAODTree = (TTree*) fAODFile->Get("aodTree");
364     if (fAODTree != 0)
365     {
366       // Check if AODfriends exist and attach them.
367       TIter       friends(fgAODfriends);
368       TObjString *name;
369       while ((name = (TObjString*) friends()) != 0)
370       {
371         TString p(Form("%s/%s", fPath.Data(), name->GetName()));
372         if (gSystem->AccessPathName(p, kReadPermission) == kFALSE)
373         {
374           fAODTree->AddFriend("aodTree", name->GetName());
375         }
376       }
377
378       fAOD->ReadFromTree(fAODTree);
379
380       if (fAODTree->GetEntry(0) <= 0)
381       {
382         delete fAODFile; fAODFile = 0;
383         delete fAOD;     fAOD     = 0;
384         Warning(kEH, "failed getting the first entry from addTree.");
385       }
386       else
387       {
388         if (runNo < 0)
389           runNo = fAOD->GetRunNumber();
390       }
391     }
392     else // aodtree == 0
393     {
394       delete fAODFile; fAODFile = 0;
395       delete fAOD;     fAOD     = 0;
396       Warning(kEH, "failed getting the aodTree.");
397     }
398   }
399   else // aod not readable
400   {
401     Warning(kEH, "can not read AOD file '%s'.", aodPath.Data());
402   }
403   if (fAODTree == 0)
404   {
405     if (fgAssertAOD)
406     {
407       throw (kEH + "AOD not initialized. Its precence was requested.");
408     } else {
409       Warning(kEH, "AOD not initialized.");
410     }
411   }
412
413   // Open RunLoader from galice.root
414
415   TString gaPath(Form("%s/galice.root", fPath.Data()));
416   // If i use open directly, we get fatal.
417   // Is AccessPathName check ok for xrootd / alien? Yes, not for http.
418   if (gSystem->AccessPathName(gaPath, kReadPermission) == kFALSE)
419   {
420     fRunLoader = AliRunLoader::Open(gaPath, GetName());
421     if (fRunLoader)
422     {
423       TString alicePath = fPath + "/";
424       fRunLoader->SetDirName(alicePath);
425
426       if (fRunLoader->LoadgAlice() != 0)
427         Warning(kEH, "failed loading gAlice via run-loader.");
428
429       if (fRunLoader->LoadHeader() == 0)
430       {
431         if (runNo < 0)
432           runNo = fRunLoader->GetHeader()->GetRun();
433       }
434       else
435       {
436         Warning(kEH, "failed loading run-loader's header.");
437         delete fRunLoader;
438         fRunLoader = 0;
439       }
440     }
441     else // run-loader open failed
442     {
443       Warning(kEH, "failed opening ALICE run-loader from '%s'.", gaPath.Data());
444     }
445   }
446   else // galice not readable
447   {
448     Warning(kEH, "can not read '%s'.", gaPath.Data());
449   }
450   if (fRunLoader == 0)
451   {
452     if (fgAssertRunLoader)
453       throw (kEH + "Bootstraping of run-loader failed. Its precence was requested.");
454     else
455       Warning(kEH, "Bootstraping of run-loader failed.");
456   }
457
458   // Open raw-data file
459
460   TString rawPath(Form("%s/%s", fPath.Data(), fgRawFileName.Data()));
461   // If i use open directly, raw-reader reports an error but i have
462   // no way to detect it.
463   // Is this (AccessPathName check) ok for xrootd / alien? Yes, not for http.
464   AliLog::EType_t oldLogLevel = (AliLog::EType_t) AliLog::GetGlobalLogLevel();
465   if (fgAssertRaw == kFALSE)
466   {
467     AliLog::SetGlobalLogLevel(AliLog::kFatal);
468   }
469   if (gSystem->AccessPathName(rawPath, kReadPermission) == kFALSE)
470   {
471     fRawReader = AliRawReader::Create(rawPath);
472   }
473   else
474   {
475     fRawReader = AliRawReader::Create(fgRawFileName);
476   }
477   if (fgAssertRaw == kFALSE)
478   {
479     AliLog::SetGlobalLogLevel(oldLogLevel);
480   }
481
482   if (fRawReader == 0)
483   {
484     if (fgAssertRaw)
485     {
486       throw (kEH + "raw-data not initialized. Its precence was requested.");
487     } else {
488       Warning(kEH, "raw-data not initialized.");
489     }
490   }
491
492   if (runNo < 0)
493   {
494     if (fRawReader)
495     {
496       fRawReader->NextEvent();
497       runNo = fRawReader->GetRunNumber();
498       Info(kEH, "Determining run-no from raw ... run=%d.", runNo);
499       fRawReader->RewindEvents();
500     } else {
501       throw (kEH + "unknown run number.");
502     }
503   }
504
505   // Initialize OCDB ... only in master event-manager
506
507   if (this == fgMaster)
508   {
509     AliCDBManager* cdb = AliCDBManager::Instance();
510     if (cdb->IsDefaultStorageSet() == kTRUE)
511     {
512       Warning(kEH, "CDB already set - using the old storage:\n  '%s'",
513               cdb->GetDefaultStorage()->GetURI().Data());
514     }
515     else
516     {
517       cdb->SetDefaultStorage(fgCdbUri);
518       if (cdb->IsDefaultStorageSet() == kFALSE)
519         throw (kEH + "CDB initialization failed.");
520     }
521     cdb->SetRun(runNo);
522   }
523
524   fIsOpen = kTRUE;
525 }
526
527 void AliEveEventManager::SetEvent(AliRunLoader *runLoader, AliRawReader *rawReader, AliESDEvent *esd, AliESDfriend *esdf)
528 {
529   // Set an event from an external source.
530   // The method is used in the online visualisation.
531   // AOD is not supported.
532
533   static const TEveException kEH("AliEveEventManager::SetEvent ");
534
535   if (fIsOpen)
536   {
537     Warning(kEH, "Event-files were open. Closing and switching to external control.");
538     Close();
539   }
540
541   fRunLoader = runLoader;
542   fRawReader = rawReader;
543   fESD       = esd;
544   fESDfriend = esdf;
545   fAOD       = 0;
546
547   fEventId++;
548   fHasEvent     = kTRUE;
549   fExternalCtrl = kTRUE;
550
551   SetTitle("Online event in memory");
552   SetName ("Online Event");
553   ElementChanged();
554
555   AfterNewEventLoaded();
556
557   if (fAutoLoad) StartAutoLoadTimer();
558 }
559
560 Int_t AliEveEventManager::GetMaxEventId(Bool_t /*refreshESD*/) const
561 {
562   // Returns maximum available event id.
563   // If under external control or event is not opened -1 is returned.
564   // If raw-data is the only data-source this can not be known
565   // and 10,000,000 is returned.
566   // If neither data-source is initialised an exception is thrown.
567   // If refresh_esd is true and ESD is the primary event-data source
568   // its header is re-read from disk.
569
570   static const TEveException kEH("AliEveEventManager::GetMaxEventId ");
571
572   if (fExternalCtrl || fIsOpen == kFALSE)
573   {
574     return -1;
575   }
576
577   if (fESDTree)
578   {
579     // Refresh crashes with root-5.21.1-alice.
580     // Fixed by Philippe 5.8.2008 r25053, can be reactivated
581     // when we move to a newer root.
582     // if (refreshESD)
583     //   fESDTree->Refresh();
584     return fESDTree->GetEntries() - 1;
585   }
586   else if (fAODTree)
587   {
588     return fAODTree->GetEntries() - 1;
589   }
590   else if (fRunLoader)
591   {
592     return fRunLoader->GetNumberOfEvents() - 1;
593   }
594   else if (fRawReader)
595   {
596     Int_t n = fRawReader->GetNumberOfEvents() - 1;
597     return n > -1 ? n : 10000000;
598   }
599   else
600   {
601     throw (kEH + "neither ESD, AOD, RunLoader nor Raw loaded.");
602   }
603 }
604
605 void AliEveEventManager::GotoEvent(Int_t event)
606 {
607   // Load data for specified event.
608   // If event is out of range an exception is thrown and old state
609   // is preserved.
610   // After successful loading of event, the virtual function
611   // AfterNewEventLoaded() is called. This executes commands that
612   // were registered via TEveEventManager::AddNewEventCommand().
613   //
614   // If event is negative, it is subtracted from the number of
615   // available events, thus passing -1 will load the last event.
616   // This is not supported when raw-data is the only data-source
617   // as the number of events is not known.
618
619   static const TEveException kEH("AliEveEventManager::GotoEvent ");
620
621   if (fAutoLoadTimerRunning)
622   {
623     throw (kEH + "Event auto-load timer is running.");
624   }
625   if (fExternalCtrl)
626   {
627     throw (kEH + "Event-loop is under external control.");
628   }
629   else if (!fIsOpen)
630   {
631     throw (kEH + "Event-files not opened.");
632   }
633
634   fHasEvent = kFALSE;
635
636   Int_t maxEvent = 0;
637   if (fESDTree)
638   {
639     // Refresh crashes with root-5.21.1-alice.
640     // Fixed by Philippe 5.8.2008 r25053, can be reactivated
641     // when we move to a newer root.
642     // fESDTree->Refresh();
643     maxEvent = fESDTree->GetEntries() - 1;
644     if (event < 0)
645       event = fESDTree->GetEntries() + event;
646   }
647   else if (fAODTree)
648   {
649     maxEvent = fAODTree->GetEntries() - 1;
650     if (event < 0)
651       event = fAODTree->GetEntries() + event;
652   }
653   else if (fRunLoader)
654   {
655     maxEvent = fRunLoader->GetNumberOfEvents() - 1;
656     if (event < 0)
657       event = fRunLoader->GetNumberOfEvents() + event;
658   }
659   else if (fRawReader)
660   {
661     maxEvent = fRawReader->GetNumberOfEvents() - 1;
662     if (maxEvent < 0)
663     {
664       maxEvent = 10000000;
665       if (event < 0) {
666         Error(kEH, "current raw-data source does not support direct event access.");
667         return;
668       }
669       Info(kEH, "number of events unknown for current raw-data source, setting max-event id to 10M.");
670     }
671     else
672     {
673       if (event < 0)
674         event = fRawReader->GetNumberOfEvents() + event;
675     }
676   }
677   else
678   {
679     throw (kEH + "neither RunLoader, ESD nor Raw loaded.");
680   }
681   if (event < 0 || event > maxEvent)
682   {
683     throw (kEH + Form("event %d not present, available range [%d, %d].",
684                       event, 0, maxEvent));
685   }
686
687   TEveManager::TRedrawDisabler rd(gEve);
688   gEve->Redraw3D(kFALSE, kTRUE); // Enforce drop of all logicals.
689
690   // !!! MT this is somewhat brutal; at least optionally, one could be
691   // a bit gentler, checking for objs owning their external refs and having
692   // additinal parents.
693   fTransients->DestroyElements();
694   for (TEveElement::List_i i = fTransientLists->BeginChildren();
695        i != fTransientLists->EndChildren(); ++i)
696   {
697     (*i)->DestroyElements();
698   }
699   DestroyElements();
700
701   if (fESDTree) {
702     if (fESDTree->GetEntry(event) <= 0)
703       throw (kEH + "failed getting required event from ESD.");
704
705     if (fESDfriendExists)
706       fESD->SetESDfriend(fESDfriend);
707   }
708
709   if (fAODTree) {
710     if (fAODTree->GetEntry(event) <= 0)
711       throw (kEH + "failed getting required event from AOD.");
712   }
713
714   if (fRunLoader) {
715     if (fRunLoader->GetEvent(event) != 0)
716       throw (kEH + "failed getting required event.");
717   }
718
719   if (fRawReader)
720   {
721     // AliRawReader::GotoEvent(Int_t) works for AliRawReaderRoot/Chain.
722     if (fRawReader->GotoEvent(event) == kFALSE)
723     {
724       // Use fallback method - iteration with NextEvent().
725       Int_t rawEv = fEventId;
726       if (event < rawEv)
727       {
728         fRawReader->RewindEvents();
729         rawEv = -1;
730       }
731
732       while (rawEv < event)
733       {
734         if ( ! fRawReader->NextEvent())
735         {
736           fRawReader->RewindEvents();
737           fEventId = -1;
738           throw (kEH + Form("Error going to next raw-event from event %d.", rawEv));
739         }
740         ++rawEv;
741       }
742       Warning(kEH, "Loaded raw-event %d with fallback method.\n", rawEv);
743     }
744   }
745
746   fHasEvent = kTRUE;
747   fEventId  = event;
748   if (this == fgMaster)
749   {
750     SetName(Form("Event %d", fEventId));
751     ElementChanged();
752   }
753
754   AfterNewEventLoaded();
755 }
756
757 void AliEveEventManager::NextEvent()
758 {
759   // Loads next event.
760   // Does magick needed for online display when under external event control.
761
762   static const TEveException kEH("AliEveEventManager::NextEvent ");
763
764   if (fAutoLoadTimerRunning)
765   {
766     throw (kEH + "Event auto-load timer is running.");
767   }
768
769   if (fExternalCtrl)
770   {
771     // !!! This should really go somewhere else. It is done in GotoEvent(),
772     // so here we should do it in SetEvent().
773     DestroyElements();
774
775     gSystem->ExitLoop();
776   }
777   else
778   {
779     Int_t nexteventbytrigger=0;
780     if (fSelectOnTriggerType)
781     {
782       if (FindNextByTrigger(nexteventbytrigger)) //if not found do nothing
783         GotoEvent(nexteventbytrigger);
784     }
785     else if (fEventId < GetMaxEventId(kTRUE))
786       GotoEvent(fEventId + 1);
787     else
788       GotoEvent(0);
789   }
790 }
791
792 void AliEveEventManager::PrevEvent()
793 {
794   // Loads previous event.
795
796   static const TEveException kEH("AliEveEventManager::PrevEvent ");
797
798   if (fAutoLoadTimerRunning)
799   {
800     throw (kEH + "Event auto-load timer is running.");
801   }
802   if (fExternalCtrl)
803   {
804     throw (kEH + "Event-loop is under external control.");
805   }
806   Int_t nexteventbytrigger=0;
807   if (fSelectOnTriggerType)
808   {
809     if (FindPrevByTrigger(nexteventbytrigger))
810       GotoEvent(nexteventbytrigger);
811   }
812   else
813     GotoEvent(fEventId - 1);
814 }
815
816 void AliEveEventManager::Close()
817 {
818   // Close the event data-files and delete ESD, ESDfriend, run-loader
819   // and raw-reader.
820
821   static const TEveException kEH("AliEveEventManager::Close ");
822
823   if (!fIsOpen)
824   {
825     throw (kEH + "Event-files not opened.");
826   }
827
828   if (fAutoLoadTimerRunning)
829     StopAutoLoadTimer();
830
831   if (fESDTree) {
832     delete fESD;       fESD       = 0;
833     delete fESDfriend; fESDfriend = 0;
834     fESDfriendExists = kFALSE;
835
836     delete fESDTree;   fESDTree = 0;
837     delete fESDFile;   fESDFile = 0;
838   }
839
840   if (fAODTree) {
841     delete fAOD;       fAOD       = 0;
842
843     delete fAODTree;   fAODTree = 0;
844     delete fAODFile;   fAODFile = 0;
845   }
846
847   if (fRunLoader) {
848     delete fRunLoader; fRunLoader = 0;
849   }
850
851   if (fRawReader) {
852     delete fRawReader; fRawReader = 0;
853   }
854
855   fEventId  = -1;
856   fIsOpen   = kFALSE;
857   fHasEvent = kFALSE;
858 }
859
860
861 //------------------------------------------------------------------------------
862 // Static convenience functions, mainly used from macros.
863 //------------------------------------------------------------------------------
864
865 Bool_t AliEveEventManager::HasRunLoader()
866 {
867   // Check if AliRunLoader is initialized.
868
869   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fRunLoader;
870 }
871
872 Bool_t AliEveEventManager::HasESD()
873 {
874   // Check if AliESDEvent is initialized.
875
876   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fESD;
877 }
878
879 Bool_t AliEveEventManager::HasESDfriend()
880 {
881   // Check if AliESDfriend is initialized.
882
883   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fESDfriend;
884 }
885
886 Bool_t AliEveEventManager::HasAOD()
887 {
888   // Check if AliESDEvent is initialized.
889
890   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fAOD;
891 }
892
893 Bool_t AliEveEventManager::HasRawReader()
894 {
895   // Check if raw-reader is initialized.
896
897   return fgCurrent && fgCurrent->fHasEvent && fgCurrent->fRawReader;
898 }
899
900 AliRunLoader* AliEveEventManager::AssertRunLoader()
901 {
902   // Make sure AliRunLoader is initialized and return it.
903   // Throws exception in case run-loader is not available.
904   // Static utility for macros.
905
906   static const TEveException kEH("AliEveEventManager::AssertRunLoader ");
907
908   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
909     throw (kEH + "ALICE event not ready.");
910   if (fgCurrent->fRunLoader == 0)
911     throw (kEH + "AliRunLoader not initialised.");
912   return fgCurrent->fRunLoader;
913 }
914
915 AliESDEvent* AliEveEventManager::AssertESD()
916 {
917   // Make sure AliESDEvent is initialized and return it.
918   // Throws exception in case ESD is not available.
919   // Static utility for macros.
920
921   static const TEveException kEH("AliEveEventManager::AssertESD ");
922
923   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
924     throw (kEH + "ALICE event not ready.");
925   if (fgCurrent->fESD == 0)
926     throw (kEH + "AliESD not initialised.");
927   return fgCurrent->fESD;
928 }
929
930 AliESDfriend* AliEveEventManager::AssertESDfriend()
931 {
932   // Make sure AliESDfriend is initialized and return it.
933   // Throws exception in case ESDfriend-loader is not available.
934   // Static utility for macros.
935
936   static const TEveException kEH("AliEveEventManager::AssertESDfriend ");
937
938   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
939     throw (kEH + "ALICE event not ready.");
940   if (fgCurrent->fESDfriend == 0)
941     throw (kEH + "AliESDfriend not initialised.");
942   return fgCurrent->fESDfriend;
943 }
944
945 AliAODEvent* AliEveEventManager::AssertAOD()
946 {
947   // Make sure AliAODEvent is initialized and return it.
948   // Throws exception in case AOD is not available.
949   // Static utility for macros.
950
951   static const TEveException kEH("AliEveEventManager::AssertAOD ");
952
953   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
954     throw (kEH + "ALICE event not ready.");
955   if (fgCurrent->fAOD == 0)
956     throw (kEH + "AliAOD not initialised.");
957   return fgCurrent->fAOD;
958 }
959
960 AliRawReader* AliEveEventManager::AssertRawReader()
961 {
962   // Make sure raw-reader is initialized and return it.
963
964   static const TEveException kEH("AliEveEventManager::AssertRawReader ");
965
966   if (fgCurrent == 0 || fgCurrent->fHasEvent == kFALSE)
967     throw (kEH + "ALICE event not ready.");
968   if (fgCurrent->fRawReader == 0)
969     throw (kEH + "RawReader not ready.");
970
971   return fgCurrent->fRawReader;
972 }
973
974 //==============================================================================
975
976 AliMagF* AliEveEventManager::AssertMagField()    
977 {        
978   // Make sure AliMagF is initialized and returns it.    
979   // Throws exception in case magnetic field is not available.   
980   // Static utility for macros.          
981
982   static const TEveException kEH("AliEveEventManager::AssertMagField ");         
983                  
984   if (fgMagField)
985     return fgMagField;
986
987   if (fgGRPData == 0)
988   {
989     InitGRP();
990   }
991
992   if (TGeoGlobalMagField::Instance())
993   {
994     fgMagField = dynamic_cast<AliMagF*>(TGeoGlobalMagField::Instance()->GetField());
995     if (fgMagField == 0)
996       throw kEH + "Global field set, but it is not AliMagF.";
997   }
998   else
999   {
1000     throw kEH + "Could not initialize magnetic field.";
1001   }
1002
1003   return fgMagField;     
1004 }
1005
1006 TGeoManager* AliEveEventManager::AssertGeometry()
1007 {
1008   // Make sure AliGeomManager is initialized and returns the
1009   // corresponding TGeoManger.
1010   // gGeoManager is set to the return value.
1011   // Throws exception if geometry can not be loaded or if it is not
1012   // available and the TGeoManager is locked.
1013   // Static utility for macros.
1014
1015   static const TEveException kEH("AliEveEventManager::AssertGeometry ");
1016
1017   if (AliGeomManager::GetGeometry() == 0)
1018   {
1019     if (TGeoManager::IsLocked())
1020       throw (kEH + "geometry is not loaded but TGeoManager is locked.");
1021
1022     gGeoManager = 0;
1023     AliGeomManager::LoadGeometry();
1024     if ( ! AliGeomManager::GetGeometry())
1025     {
1026       throw (kEH + "can not load geometry.");
1027     }
1028     if ( ! AliGeomManager::ApplyAlignObjsFromCDB("ITS TPC TRD TOF PHOS HMPID EMCAL MUON FMD ZDC PMD T0 VZERO ACORDE"))
1029     {
1030       ::Warning(kEH, "mismatch of alignable volumes. Proceeding.");
1031       // throw (kEH + "could not apply align objs.");
1032     }
1033     AliGeomManager::GetGeometry()->DefaultColors();
1034   }
1035
1036   gGeoManager = AliGeomManager::GetGeometry();
1037   return gGeoManager;
1038 }
1039
1040 //------------------------------------------------------------------------------
1041
1042 AliEveEventManager* AliEveEventManager::AddDependentManager(const TString& name, const TString& path)
1043 {
1044   // Create and attach a dependent event-manager.
1045   // It is not added into eve list tree.
1046
1047   static const TEveException kEH("AliEveEventManager::AddDependentManager ");
1048
1049   if (fgMaster == 0)
1050     throw(kEH + "Master event-manager must be instantiated first.");
1051
1052   if (fgMaster->fSubManagers == 0)
1053   {
1054     fgMaster->fSubManagers = new TList;
1055     fgMaster->fSubManagers->SetOwner(kTRUE);
1056   }
1057
1058   AliEveEventManager* new_mgr = 0;
1059   fgCurrent = 0;
1060   try
1061   {
1062     new_mgr = new AliEveEventManager(name, path, fgMaster->fEventId);
1063     fgMaster->fSubManagers->Add(new_mgr);
1064   }
1065   catch (TEveException& exc)
1066   {
1067     ::Error(kEH, "Creation of new event-manager failed: '%s'.", exc.Data());
1068   }
1069   fgCurrent = fgMaster;
1070
1071   return new_mgr;
1072 }
1073
1074 AliEveEventManager* AliEveEventManager::GetDependentManager(const TString& name)
1075 {
1076   // Get a dependant manager by name.
1077   // This will not change the current manager, use helper class
1078   // AliEveEventManager::CurrentChanger for that.
1079
1080   static const TEveException kEH("AliEveEventManager::GetDependentManager ");
1081
1082   if (fgMaster == 0)
1083     throw(kEH + "Master event-manager must be instantiated first.");
1084
1085   if (fgMaster->fSubManagers == 0)
1086     return 0;
1087
1088   return dynamic_cast<AliEveEventManager*>(fgMaster->fSubManagers->FindObject(name));
1089 }
1090
1091 AliEveEventManager* AliEveEventManager::GetMaster()
1092 {
1093   // Get master event-manager.
1094
1095   return fgMaster;
1096 }
1097
1098 AliEveEventManager* AliEveEventManager::GetCurrent()
1099 {
1100   // Get current event-manager.
1101
1102   return fgCurrent;
1103 }
1104
1105 void AliEveEventManager::RegisterTransient(TEveElement* element)
1106 {
1107   GetCurrent()->fTransients->AddElement(element);
1108 }
1109
1110 void AliEveEventManager::RegisterTransientList(TEveElement* element)
1111 {
1112   GetCurrent()->fTransientLists->AddElement(element);
1113 }
1114
1115 //------------------------------------------------------------------------------
1116 // Autoloading of events
1117 //------------------------------------------------------------------------------
1118
1119 void AliEveEventManager::SetAutoLoadTime(Float_t time)
1120 {
1121   // Set the auto-load time in seconds
1122
1123   fAutoLoadTime = time;
1124 }
1125
1126 void AliEveEventManager::SetAutoLoad(Bool_t autoLoad)
1127 {
1128   // Set the automatic event loading mode
1129
1130   static const TEveException kEH("AliEveEventManager::SetAutoLoad ");
1131
1132   if (fAutoLoad == autoLoad)
1133   {
1134     Warning(kEH, "Setting autoload to the same value as before - %s. Ignoring.", fAutoLoad ? "true" : "false");
1135     return;
1136   }
1137
1138   fAutoLoad = autoLoad;
1139   if (fAutoLoad)
1140   {
1141     StartAutoLoadTimer();
1142   }
1143   else
1144   {
1145     StopAutoLoadTimer();
1146   }
1147 }
1148
1149 void AliEveEventManager::StartAutoLoadTimer()
1150 {
1151   // Start the auto-load timer.
1152
1153   fAutoLoadTimer->SetTime((Long_t)(1000*fAutoLoadTime));
1154   fAutoLoadTimer->Reset();
1155   fAutoLoadTimer->TurnOn();
1156   fAutoLoadTimerRunning = kTRUE;
1157 }
1158
1159 void AliEveEventManager::StopAutoLoadTimer()
1160 {
1161   // Stop the auto-load timer.
1162
1163   fAutoLoadTimerRunning = kFALSE;
1164   fAutoLoadTimer->TurnOff();
1165 }
1166
1167 void AliEveEventManager::AutoLoadNextEvent()
1168 {
1169   // Called from auto-load timer, so it has to be public.
1170   // Do NOT call it directly.
1171
1172   static const TEveException kEH("AliEveEventManager::AutoLoadNextEvent ");
1173
1174   if ( ! fAutoLoadTimerRunning || ! fAutoLoadTimer->HasTimedOut())
1175   {
1176     Warning(kEH, "Called unexpectedly - ignoring the call. Should ONLY be called from an internal timer.");
1177     return;
1178   }
1179
1180   StopAutoLoadTimer();
1181   NextEvent();
1182   if (fAutoLoad && !fExternalCtrl)
1183     StartAutoLoadTimer();
1184 }
1185
1186
1187 //------------------------------------------------------------------------------
1188 // Event selection by trigger
1189 //------------------------------------------------------------------------------
1190
1191 Bool_t AliEveEventManager::FindNextByTrigger(Int_t& event)
1192 {
1193   // Find next event that matches the trigger.
1194   // If a matching event is not found, we loop around and eventually
1195   // end up at the same event.
1196
1197   static const TEveException kEH("AliEveEventManager::FindNextByTrigger ");
1198
1199   if (!fESDTree) return kFALSE;
1200   TString firedtrclasses;
1201   for (Int_t i = fEventId+1; i<GetMaxEventId(kTRUE)+1; i++)
1202   {
1203     if (fESDTree->GetEntry(i) <= 0)
1204       throw (kEH + "failed getting required event from ESD.");
1205     firedtrclasses = fESD->GetFiredTriggerClasses();
1206     if (firedtrclasses.Contains(fTriggerType))
1207     {
1208       event=i;
1209       return kTRUE;
1210     }
1211   }
1212   for (Int_t i = 0; i<fEventId+1; i++)
1213   {
1214     if (fESDTree->GetEntry(i) <= 0)
1215       throw (kEH + "failed getting required event from ESD.");
1216     firedtrclasses = fESD->GetFiredTriggerClasses();
1217     if (firedtrclasses.Contains(fTriggerType))
1218     {
1219       event=i;
1220       return kTRUE;
1221     }
1222   }
1223   return kFALSE;
1224 }
1225
1226 Bool_t AliEveEventManager::FindPrevByTrigger(Int_t& event)
1227 {
1228   // Find previous event that matches the trigger.
1229
1230   static const TEveException kEH("AliEveEventManager::FindPrevByTrigger ");
1231
1232   if (!fESDTree) return kFALSE;
1233   TString firedtrclasses;
1234   for (Int_t i = fEventId-1; i>=0; i--)
1235   {
1236     if (fESDTree->GetEntry(i) <= 0)
1237       throw (kEH + "failed getting required event from ESD.");
1238     firedtrclasses = fESD->GetFiredTriggerClasses();
1239     if (firedtrclasses.Contains(fTriggerType))
1240     {
1241       event=i;
1242       return kTRUE;
1243     }
1244   }
1245   for (Int_t i = GetMaxEventId(kTRUE); i>fEventId-1; i--)
1246   {
1247     if (fESDTree->GetEntry(i) <= 0)
1248       throw (kEH + "failed getting required event from ESD.");
1249     firedtrclasses = fESD->GetFiredTriggerClasses();
1250     if (firedtrclasses.Contains(fTriggerType))
1251     {
1252       event=i;
1253       return kTRUE;
1254     }
1255   }
1256   return kFALSE;
1257 }
1258
1259
1260 //------------------------------------------------------------------------------
1261 // Post event-loading functions
1262 //------------------------------------------------------------------------------
1263
1264 void AliEveEventManager::AfterNewEventLoaded()
1265 {
1266   // Execute registered macros and commands.
1267   // At the end emit NewEventLoaded signal.
1268   //
1269   // Virtual from TEveEventManager.
1270
1271   static const TEveException kEH("AliEveEventManager::AfterNewEventLoaded ");
1272
1273   if (fExecutor)
1274     fExecutor->ExecMacros();
1275
1276   TEveEventManager::AfterNewEventLoaded();
1277
1278   NewEventLoaded();
1279
1280   if (this == fgMaster && fSubManagers != 0)
1281   {
1282     TIter next(fSubManagers);
1283     while ((fgCurrent = dynamic_cast<AliEveEventManager*>(next())) != 0)
1284     {
1285       gEve->SetCurrentEvent(fgCurrent);
1286       try
1287       {
1288         fgCurrent->GotoEvent(fEventId);
1289       }
1290       catch (TEveException& exc)
1291       {
1292         // !!! Should somehow tag / disable / remove it?
1293         Error(kEH, "Getting event %d for sub-event-manager '%s' failed: '%s'.",
1294               fEventId, fgCurrent->GetName(), exc.Data());
1295       }
1296     }
1297     fgCurrent = fgMaster;
1298     gEve->SetCurrentEvent(fgMaster);
1299   }
1300 }
1301
1302 void AliEveEventManager::NewEventLoaded()
1303 {
1304   // Emit NewEventLoaded signal.
1305
1306   Emit("NewEventLoaded()");
1307 }
1308
1309
1310 //------------------------------------------------------------------------------
1311 // Event info dumpers
1312 //------------------------------------------------------------------------------
1313
1314 TString AliEveEventManager::GetEventInfoHorizontal() const
1315 {
1316   // Dumps the event-header contents in vertical formatting.
1317
1318   TString rawInfo, esdInfo;
1319
1320   if (!fRawReader)
1321   {
1322     rawInfo = "No raw-data event info is available!\n";
1323   }
1324   else
1325   {
1326     const UInt_t* attr = fRawReader->GetAttributes();
1327     TTimeStamp ts(fRawReader->GetTimestamp());
1328     rawInfo.Form("RAW event info: Run#: %d  Event type: %d (%s)  Period: %x  Orbit: %x  BC: %x\n"
1329                  "Trigger: %llx\nDetectors: %x (%s)\nAttributes:%x-%x-%x  Timestamp: %s\n",
1330                  fRawReader->GetRunNumber(),fRawReader->GetType(),AliRawEventHeaderBase::GetTypeName(fRawReader->GetType()),
1331                  fRawReader->GetPeriod(),fRawReader->GetOrbitID(),fRawReader->GetBCID(),
1332                  fRawReader->GetClassMask(),
1333                  *fRawReader->GetDetectorPattern(),AliDAQ::ListOfTriggeredDetectors(*fRawReader->GetDetectorPattern()),
1334                  attr[0],attr[1],attr[2], ts.AsString("s"));
1335   }
1336
1337   if (!fESD)
1338   {
1339     esdInfo = "No ESD event info is available!";
1340   }
1341   else
1342   {
1343     TString acttrclasses   = fESD->GetESDRun()->GetActiveTriggerClasses();
1344     TString firedtrclasses = fESD->GetFiredTriggerClasses();
1345     TTimeStamp ts(fESD->GetTimeStamp());
1346     esdInfo.Form("ESD event info: Run#: %d  Event type: %d (%s)  Period: %x  Orbit: %x  BC: %x\n"
1347                  "Active trigger classes: %s\nTrigger: %llx (%s)\nEvent# in file: %d  Timestamp: %s, MagField: %.2e",
1348                  fESD->GetRunNumber(),
1349                  fESD->GetEventType(),AliRawEventHeaderBase::GetTypeName(fESD->GetEventType()),
1350                  fESD->GetPeriodNumber(),fESD->GetOrbitNumber(),fESD->GetBunchCrossNumber(),
1351                  acttrclasses.Data(),
1352                  fESD->GetTriggerMask(),firedtrclasses.Data(),
1353                  fESD->GetEventNumberInFile(), ts.AsString("s"), fESD->GetMagneticField());
1354   }
1355
1356   return rawInfo + esdInfo;
1357 }
1358
1359 TString AliEveEventManager::GetEventInfoVertical() const
1360 {
1361   // Dumps the event-header contents in vertical formatting.
1362
1363   TString rawInfo, esdInfo;
1364
1365   if (!fRawReader)
1366   {
1367     rawInfo = "No raw-data event info is available!\n";
1368   }
1369   else
1370   {
1371     const UInt_t* attr = fRawReader->GetAttributes();
1372     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",
1373                  fRawReader->GetRunNumber(),fRawReader->GetType(),AliRawEventHeaderBase::GetTypeName(fRawReader->GetType()),
1374                  fRawReader->GetPeriod(),fRawReader->GetOrbitID(),fRawReader->GetBCID(),
1375                  fRawReader->GetClassMask(),
1376                  *fRawReader->GetDetectorPattern(),AliDAQ::ListOfTriggeredDetectors(*fRawReader->GetDetectorPattern()),
1377                  attr[0],attr[1],attr[2],
1378                  fRawReader->GetTimestamp());
1379   }
1380
1381   if (!fESD)
1382   {
1383     esdInfo = "No ESD event info is available!\n";
1384   }
1385   else
1386   {
1387     TString acttrclasses   = fESD->GetESDRun()->GetActiveTriggerClasses();
1388     TString firedtrclasses = fESD->GetFiredTriggerClasses();
1389     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",
1390                  fESD->GetRunNumber(),
1391                  acttrclasses.Data(),
1392                  fESD->GetEventType(),AliRawEventHeaderBase::GetTypeName(fESD->GetEventType()),
1393                  fESD->GetPeriodNumber(),fESD->GetOrbitNumber(),fESD->GetBunchCrossNumber(),
1394                  fESD->GetTriggerMask(),firedtrclasses.Data(),
1395                  fESD->GetEventNumberInFile(),
1396                  fESD->GetTimeStamp());
1397   }
1398
1399   return rawInfo + "\n" + esdInfo;
1400 }
1401
1402
1403 //==============================================================================
1404 // Reading of GRP and MagneticField.
1405 // This is a reap-off from reconstruction ... should really be a common
1406 // code to do this somewhere in STEER.
1407 //==============================================================================
1408
1409 Bool_t AliEveEventManager::InitGRP()
1410 {
1411   //------------------------------------
1412   // Initialization of the GRP entry 
1413   //------------------------------------
1414
1415   static const TEveException kEH("AliEveEventManager::InitGRP ");
1416
1417   AliCDBEntry* entry = AliCDBManager::Instance()->Get("GRP/GRP/Data");
1418
1419   if (entry)
1420   {
1421     TMap* m = dynamic_cast<TMap*>(entry->GetObject());  // old GRP entry
1422
1423     if (m)
1424     {
1425       ::Info(kEH, "Found a TMap in GRP/GRP/Data, converting it into an AliGRPObject");
1426       fgGRPData = new AliGRPObject();
1427       fgGRPData->ReadValuesFromMap(m);
1428     }
1429     else
1430     {
1431       ::Info(kEH, "Found an AliGRPObject in GRP/GRP/Data, reading it");
1432       fgGRPData = dynamic_cast<AliGRPObject*>(entry->GetObject());  // new GRP entry
1433       entry->SetOwner(0);
1434     }
1435
1436     AliCDBManager::Instance()->UnloadFromCache("GRP/GRP/Data");
1437   }
1438
1439   if (!fgGRPData)
1440   {
1441     ::Error(kEH, "No GRP entry found in OCDB!");
1442     return kFALSE;
1443   }
1444
1445   TString lhcState = fgGRPData->GetLHCState();
1446   if (lhcState==AliGRPObject::GetInvalidString())
1447   {
1448     ::Error(kEH, "GRP/GRP/Data entry:  missing value for the LHC state ! Using UNKNOWN");
1449     lhcState = "UNKNOWN";
1450   }
1451
1452   TString beamType = fgGRPData->GetBeamType();
1453   if (beamType==AliGRPObject::GetInvalidString())
1454   {
1455     ::Error(kEH, "GRP/GRP/Data entry:  missing value for the beam type ! Using UNKNOWN");
1456     beamType = "UNKNOWN";
1457   }
1458
1459   Float_t beamEnergy = fgGRPData->GetBeamEnergy();
1460   if (beamEnergy==AliGRPObject::GetInvalidFloat())
1461   {
1462     ::Error(kEH, "GRP/GRP/Data entry:  missing value for the beam energy ! Using 0");
1463     beamEnergy = 0;
1464   }
1465   beamEnergy /= 120E3; // energy is provided in MeV*120
1466
1467   TString runType = fgGRPData->GetRunType();
1468   if (runType==AliGRPObject::GetInvalidString())
1469   {
1470     ::Error(kEH, "GRP/GRP/Data entry:  missing value for the run type ! Using UNKNOWN");
1471     runType = "UNKNOWN";
1472   }
1473
1474   Int_t activeDetectors = fgGRPData->GetDetectorMask();
1475   if (activeDetectors==AliGRPObject::GetInvalidUInt())
1476   {
1477     ::Error(kEH, "GRP/GRP/Data entry:  missing value for the detector mask ! Using 1074790399");
1478     activeDetectors = 1074790399;
1479   }
1480
1481
1482   // Might become useful.
1483   /*
1484     fRunInfo = new AliRunInfo(lhcState, beamType, beamEnergy, runType, activeDetectors);
1485     printf("AliRunInfo - %s %s %f %s %d\n", lhcState.Data(), beamType.Data(), beamEnergy, runType.Data(), activeDetectors);
1486     fRunInfo->Dump();
1487
1488
1489     // Process the list of active detectors
1490     if (activeDetectors) {
1491     UInt_t detMask = activeDetectors;
1492     fRunLocalReconstruction = MatchDetectorList(fRunLocalReconstruction,detMask);
1493     fRunTracking = MatchDetectorList(fRunTracking,detMask);
1494     fFillESD = MatchDetectorList(fFillESD,detMask);
1495     fQADetectors = MatchDetectorList(fQADetectors,detMask);
1496     fLoadCDB.Form("%s %s %s %s",
1497     fRunLocalReconstruction.Data(),
1498     fRunTracking.Data(),
1499     fFillESD.Data(),
1500     fQADetectors.Data());
1501     fLoadCDB = MatchDetectorList(fLoadCDB,detMask);
1502     if (!((detMask >> AliDAQ::DetectorID("ITSSPD")) & 0x1)) {
1503     // switch off the vertexer
1504     ::Info(kEH, "SPD is not in the list of active detectors. Vertexer switched off.");
1505     fRunVertexFinder = kFALSE;
1506     }
1507     if (!((detMask >> AliDAQ::DetectorID("TRG")) & 0x1)) {
1508     // switch off the reading of CTP raw-data payload
1509     if (fFillTriggerESD) {
1510     ::Info(kEH, "CTP is not in the list of active detectors. CTP data reading switched off.");
1511     fFillTriggerESD = kFALSE;
1512     }
1513     }
1514     }
1515
1516     ::Info(kEH, "===================================================================================");
1517     ::Info(kEH, "Running local reconstruction for detectors: %s",fRunLocalReconstruction.Data());
1518     ::Info(kEH, "Running tracking for detectors: %s",fRunTracking.Data());
1519     ::Info(kEH, "Filling ESD for detectors: %s",fFillESD.Data());
1520     ::Info(kEH, "Quality assurance is active for detectors: %s",fQADetectors.Data());
1521     ::Info(kEH, "CDB and reconstruction parameters are loaded for detectors: %s",fLoadCDB.Data());
1522     ::Info(kEH, "===================================================================================");
1523   */
1524
1525   //*** Dealing with the magnetic field map
1526   if (TGeoGlobalMagField::Instance()->IsLocked())
1527   {
1528     ::Info(kEH, "Running with externally locked B field!");
1529   }
1530   else
1531   {
1532     // Construct the field map out of the information retrieved from GRP.
1533
1534     Float_t l3Current = fgGRPData->GetL3Current((AliGRPObject::Stats)0);
1535     if (l3Current == AliGRPObject::GetInvalidFloat())
1536       throw kEH + "GRPData entry: missing value for the L3 current!";
1537     
1538     Char_t l3Polarity = fgGRPData->GetL3Polarity();
1539     if (l3Polarity == AliGRPObject::GetInvalidChar())
1540       throw kEH + "GRPData entry: missing value for the L3 polarity!";
1541
1542     Float_t diCurrent = fgGRPData->GetDipoleCurrent((AliGRPObject::Stats)0);
1543     if (diCurrent == AliGRPObject::GetInvalidFloat())
1544       throw kEH + "GRPData entry: missing value for the dipole current!";
1545
1546     Char_t diPolarity = fgGRPData->GetDipolePolarity();
1547     if (diPolarity == AliGRPObject::GetInvalidChar()) 
1548       throw kEH + "GRPData entry: missing value for the dipole polarity!";
1549
1550     if (!SetFieldMap(l3Current, diCurrent, l3Polarity ? -1:1, diPolarity ? -1:1))
1551       throw kEH + "Failed to create B field map!";
1552
1553     ::Info(kEH, "Running with the B field constructed from GRP.");
1554   }
1555   
1556   //*** Get the diamond profiles from OCDB
1557   // Eventually useful.
1558
1559   /*
1560     entry = AliCDBManager::Instance()->Get("GRP/Calib/MeanVertexSPD");
1561     if (entry) {
1562     fDiamondProfileSPD = dynamic_cast<AliESDVertex*> (entry->GetObject());  
1563     } else {
1564     ::Error(kEH, "No SPD diamond profile found in OCDB!");
1565     }
1566
1567     entry = AliCDBManager::Instance()->Get("GRP/Calib/MeanVertex");
1568     if (entry) {
1569     fDiamondProfile = dynamic_cast<AliESDVertex*> (entry->GetObject());  
1570     } else {
1571     ::Error(kEH, "No diamond profile found in OCDB!");
1572     }
1573
1574     entry = AliCDBManager::Instance()->Get("GRP/Calib/MeanVertexTPC");
1575     if (entry) {
1576     fDiamondProfileTPC = dynamic_cast<AliESDVertex*> (entry->GetObject());  
1577     } else {
1578     ::Error(kEH, "No TPC diamond profile found in OCDB!");
1579     }
1580   */
1581
1582   return kTRUE;
1583
1584
1585 Bool_t AliEveEventManager::SetFieldMap(Float_t l3Cur, Float_t diCur,
1586                                        Float_t l3Pol, Float_t diPol,
1587                                        Float_t beamenergy,
1588                                        const Char_t *beamtype,
1589                                        const Char_t *path) 
1590 {
1591   //------------------------------------------------
1592   // The magnetic field map, defined externally...
1593   // L3 current 30000 A  -> 0.5 T
1594   // L3 current 12000 A  -> 0.2 T
1595   // dipole current 6000 A
1596   // The polarities must be the same
1597   //------------------------------------------------
1598
1599   static const TEveException kEH("AliEveEventManager::SetFieldMap ");
1600
1601   const Float_t l3NominalCurrent1 = 30000.0; // (A)
1602   const Float_t l3NominalCurrent2 = 12000.0; // (A)
1603   const Float_t diNominalCurrent  = 6000.0;  // (A)
1604
1605   const Float_t tolerance = 0.03; // relative current tolerance
1606   const Float_t zero      = 77.0; // "zero" current (A)
1607
1608   TString s = (l3Pol < 0) ? "L3: -" : "L3: +";
1609
1610   AliMagF::BMap_t map = AliMagF::k5kG;
1611
1612   double fcL3, fcDip;
1613
1614   l3Cur = TMath::Abs(l3Cur);
1615   if (TMath::Abs(l3Cur-l3NominalCurrent1)/l3NominalCurrent1 < tolerance)
1616   {
1617     fcL3 = l3Cur/l3NominalCurrent1;
1618     map  = AliMagF::k5kG;
1619     s   += "0.5 T;  ";
1620   }
1621   else if (TMath::Abs(l3Cur-l3NominalCurrent2)/l3NominalCurrent2 < tolerance)
1622   {
1623     fcL3 = l3Cur/l3NominalCurrent2;
1624     map  = AliMagF::k2kG;
1625     s   += "0.2 T;  ";
1626   }
1627   else if (l3Cur <= zero)
1628   {
1629     fcL3 = 0;
1630     map  = AliMagF::k5kGUniform;
1631     s   += "0.0 T;  ";
1632     fgUniformField = kTRUE; // track with the uniform (zero) B field
1633   }
1634   else
1635   {
1636     ::Error(kEH, "Wrong L3 current (%f A)!", l3Cur);
1637     return kFALSE;
1638   }
1639
1640   diCur = TMath::Abs(diCur);
1641   if (TMath::Abs(diCur-diNominalCurrent)/diNominalCurrent < tolerance)
1642   {
1643     // 3% current tolerance...
1644     fcDip = diCur/diNominalCurrent;
1645     s    += "Dipole ON";
1646   }
1647   else if (diCur <= zero)
1648   { // some small current..
1649     fcDip = 0.;
1650     s    += "Dipole OFF";
1651   }
1652   else
1653   {
1654     ::Error(kEH, "Wrong dipole current (%f A)!", diCur);
1655     return kFALSE;
1656   }
1657
1658   if (l3Pol != diPol && (map==AliMagF::k5kG || map==AliMagF::k2kG) && fcDip != 0)
1659   {
1660     ::Error(kEH, "L3 and Dipole polarities must be the same");
1661     return kFALSE;
1662   }
1663
1664   if (l3Pol<0) fcL3  = -fcL3;
1665   if (diPol<0) fcDip = -fcDip;
1666
1667   AliMagF::BeamType_t btype = AliMagF::kNoBeamField;
1668   TString btypestr = beamtype;
1669   btypestr.ToLower();
1670
1671   TPRegexp protonBeam("(proton|p)\\s*-?\\s*\\1");
1672   TPRegexp ionBeam   ("(lead|pb|ion|a)\\s*-?\\s*\\1");
1673
1674   if (btypestr.Contains(ionBeam))
1675     btype = AliMagF::kBeamTypeAA;
1676   else if (btypestr.Contains(protonBeam))
1677     btype = AliMagF::kBeamTypepp;
1678   else
1679     ::Info(kEH, "Cannot determine the beam type from %s, assume no LHC magnet field",
1680            beamtype);
1681
1682   AliMagF* fld = new AliMagF("MagneticFieldMap", s.Data(), 2, fcL3, fcDip, 10., map, path, 
1683                              btype,beamenergy);
1684   TGeoGlobalMagField::Instance()->SetField(fld);
1685   TGeoGlobalMagField::Instance()->Lock();
1686
1687   return kTRUE;
1688 }