Do not make event-path absolute unless it is specifying a local file/directory.
[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 <TEveManager.h>
12
13 #include <AliRunLoader.h>
14 #include <AliRun.h>
15 #include <AliESDEvent.h>
16 #include <AliESDfriend.h>
17 #include <AliRawReaderRoot.h>
18 #include <AliRawReaderFile.h>
19 #include <AliRawReaderDate.h>
20 #include <AliMagFMaps.h>
21 #include <AliCDBManager.h>
22 #include <AliHeader.h>
23 #include <AliGeomManager.h>
24
25 #include <TFile.h>
26 #include <TTree.h>
27 #include <TGeoManager.h>
28 #include <TSystem.h>
29
30 //==============================================================================
31 //==============================================================================
32 // AliEveEventManager
33 //==============================================================================
34
35 //______________________________________________________________________________
36 //
37 // Provide interface for loading and navigating standard AliRoot data
38 // (AliRunLoader) and ESDs.
39 //
40 // Missing support for raw-data. For now this is handled individually
41 // by each sub-detector.
42 //
43 // Also provides interface to magnetic-field and geometry. Mostly
44 // intended as wrappers over standard AliRoot functionality for
45 // convenient use from visualizateion macros.
46
47 ClassImp(AliEveEventManager)
48
49 AliEveEventManager* gAliEveEvent = 0;
50
51 Bool_t AliEveEventManager::fgAssertRunLoader = kFALSE;
52 Bool_t AliEveEventManager::fgAssertESD       = kFALSE;
53 Bool_t AliEveEventManager::fgAssertRaw       = kFALSE;
54
55 TString  AliEveEventManager::fgESDFileName("AliESDs.root");
56 TString  AliEveEventManager::fgRawFileName("raw.root");
57 TString  AliEveEventManager::fgCdbUri("local://$ALICE_ROOT");
58
59 AliMagF* AliEveEventManager::fgMagField = 0;
60
61
62 AliEveEventManager::AliEveEventManager() :
63   TEveEventManager(),
64
65   fPath      ( ), fEventId (-1),
66   fRunLoader (0),
67   fESDFile   (0), fESDTree (0), fESD (0),
68   fESDfriend (0), fESDfriendExists(kFALSE),
69   fRawReader (0),
70   fAutoLoad(kFALSE),
71   fAutoLoadTime(5.),
72   fAutoLoadTimer(0),
73   fIsOnline(kFALSE)
74 {
75   // Default constructor.
76 }
77
78 AliEveEventManager::AliEveEventManager(TString path, Int_t ev) :
79   TEveEventManager("AliEVE AliEveEventManager"),
80
81   fPath   (path), fEventId(-1),
82   fRunLoader (0),
83   fESDFile   (0), fESDTree (0), fESD (0),
84   fESDfriend (0), fESDfriendExists(kFALSE),
85   fRawReader (0),
86   fAutoLoad(kFALSE),
87   fAutoLoadTime(5.),
88   fAutoLoadTimer(0),
89   fIsOnline(kFALSE)
90 {
91   // Constructor with event-directory URL and event-id.
92
93   Open();
94   if (ev >= 0) GotoEvent(ev);
95 }
96
97 AliEveEventManager::~AliEveEventManager()
98 {
99   // Destructor.
100
101   if (fAutoLoadTimer) delete fAutoLoadTimer;
102   // Somewhat unclear what to do here.
103   // In principle should close all data sources and deregister from
104   // TEveManager.
105 }
106
107 /******************************************************************************/
108
109 void AliEveEventManager::SetESDFileName(const Text_t* esd)
110 {
111   // Set file-name for opening ESD, default "AliESDs.root".
112
113   if (esd) fgESDFileName = esd;
114 }
115
116 void AliEveEventManager::SetRawFileName(const Text_t* raw)
117 {
118   // Set file-name for opening of raw-data, default "raw.root"
119   if (raw) fgRawFileName = raw;
120 }
121
122 void AliEveEventManager::SetCdbUri(const Text_t* cdb)
123 {
124   // Set path to CDB, default "local://$ALICE_ROOT".
125
126   if (cdb) fgCdbUri = cdb;
127 }
128
129 void AliEveEventManager::SetAssertElements(Bool_t assertRunloader,
130                                            Bool_t assertEsd,
131                                            Bool_t assertRaw)
132 {
133   // Set global flags that detrmine which parts of the event-data must
134   // be present when the event is opened.
135
136   fgAssertRunLoader = assertRunloader;
137   fgAssertESD = assertEsd;
138   fgAssertRaw = assertRaw;
139 }
140
141 /******************************************************************************/
142
143 void AliEveEventManager::Open()
144 {
145   // Open event-data from URL specified in fPath.
146   // Attempts to create AliRunLoader() and to open ESD with ESDfriends.
147   // Warning is reported if run-loader or ESD is not found.
148   // Global data-members fgAssertRunLoader and fgAssertESD can be set
149   // to throw exceptions instead.
150
151   static const TEveException kEH("AliEveEventManager::Open ");
152
153   gSystem->ExpandPathName(fPath);
154   // The following magick is required for ESDriends to be loaded properly
155   // from non-current directory.
156   if (fPath.IsNull() || fPath == ".")
157   {
158     fPath = gSystem->WorkingDirectory();
159   }
160   else if ( ! fPath.BeginsWith("file:/"))
161   {
162     TUrl    url(fPath, kTRUE);
163     TString protocol(url.GetProtocol());
164     if (protocol == "file" && fPath[0] != '/')
165       fPath = Form("%s/%s", gSystem->WorkingDirectory(), fPath.Data());
166   }
167
168   Int_t runNo = -1;
169
170   TString gaPath(Form("%s/galice.root", fPath.Data()));
171   // If i use open directly, we get fatal.
172   // Is this (AccessPathName check) ok for xrootd / alien?
173   if (gSystem->AccessPathName(gaPath, kReadPermission) == kFALSE)
174   {
175     fRunLoader = AliRunLoader::Open(gaPath);
176     if (fRunLoader)
177     {
178       TString alicePath = fPath + "/";
179       fRunLoader->SetDirName(alicePath);
180
181       if (fRunLoader->LoadgAlice() != 0)
182         Warning(kEH, "failed loading gAlice via run-loader.");
183
184       if (fRunLoader->LoadHeader() == 0)
185       {
186         runNo = fRunLoader->GetHeader()->GetRun();
187       }
188       else
189       {
190         Warning(kEH, "failed loading run-loader's header.");
191         delete fRunLoader;
192         fRunLoader = 0;
193       }
194     }
195     else // run-loader open failed
196     {
197       Warning(kEH, "failed opening ALICE run-loader from '%s'.", gaPath.Data());
198     }
199   }
200   else // galice not readable
201   {
202     Warning(kEH, "can not read '%s'.", gaPath.Data());
203   }
204   if (fRunLoader == 0)
205   {
206     if (fgAssertRunLoader)
207       throw (kEH + "Bootstraping of run-loader failed. Its precence was requested.");
208     else
209       Warning(kEH, "Bootstraping of run-loader failed.");
210   }
211
212
213   TString esdPath(Form("%s/%s", fPath.Data(), fgESDFileName.Data()));
214   if ((fESDFile = TFile::Open(esdPath)))
215   {
216     fESD = new AliESDEvent();
217     fESDTree = (TTree*) fESDFile->Get("esdTree");
218     if (fESDTree != 0)
219     {
220       fESD->ReadFromTree(fESDTree);
221       fESDTree->GetEntry(0);
222       runNo = fESD->GetESDRun()->GetRunNumber();
223
224       // Check if ESDfriends exists and attach the branch
225       TString p(Form("%s/AliESDfriends.root", fPath.Data()));
226       if (gSystem->AccessPathName(p, kReadPermission) == kFALSE)
227       {
228         fESDfriendExists = kTRUE;
229         fESDTree->SetBranchStatus ("ESDfriend*", 1);
230         fESDTree->SetBranchAddress("ESDfriend.", &fESDfriend);
231       }
232     }
233     else // esdtree == 0
234     {
235       delete fESDFile; fESDFile = 0;
236       Warning(kEH, "failed getting the esdTree.");
237     }
238   }
239   else // esd not readable
240   {
241     Warning(kEH, "can not read ESD file '%s'.", esdPath.Data());
242   }
243   if (fESDTree == 0)
244   {
245     if (fgAssertESD)
246     {
247       throw (kEH + "ESD not initialized. Its precence was requested.");
248     } else {
249       Warning(kEH, "ESD not initialized.");
250     }
251   }
252
253   TString rawPath(Form("%s/%s", fPath.Data(), fgRawFileName.Data()));
254   // If i use open directly, raw-reader reports an error but i have
255   // no way to detect it.
256   // Is this (AccessPathName check) ok for xrootd / alien?
257   if (gSystem->AccessPathName(rawPath, kReadPermission) == kFALSE)
258   {
259     if (fgRawFileName.EndsWith("/"))
260     {
261       fRawReader = new AliRawReaderFile(rawPath);
262     }
263     else if (fgRawFileName.EndsWith(".root"))
264     {
265       fRawReader = new AliRawReaderRoot(rawPath);
266     }
267     else if (!fgRawFileName.IsNull())
268     {
269       fRawReader = new AliRawReaderDate(rawPath);
270     } 
271   }
272
273   if (fRawReader == 0)
274   {
275     if (fgAssertRaw)
276     {
277       throw (kEH + "raw-data not initialized. Its precence was requested.");
278     } else {
279       Warning(kEH, "raw-data not initialized.");
280     }
281   }
282
283   if (runNo < 0)
284   {
285     if (fRawReader)
286     {
287       fRawReader->NextEvent();
288       runNo = fRawReader->GetRunNumber();
289       printf("Determining run-no from raw ... run=%d\n", runNo);
290       fRawReader->RewindEvents();
291     } else {
292       throw (kEH + "unknown run number.");
293     }
294   }
295
296   {
297     AliCDBManager* cdb = AliCDBManager::Instance();
298     cdb->SetDefaultStorage(fgCdbUri);
299     if (cdb->IsDefaultStorageSet() == kFALSE)
300       throw (kEH + "CDB initialization failed.");
301     cdb->SetRun(runNo);
302   }
303
304   SetName(Form("Event %d", fEventId));
305   SetTitle(fPath);
306 }
307
308 void AliEveEventManager::SetEvent(AliRunLoader *runLoader, AliRawReader *rawReader, AliESDEvent *esd)
309 {
310   // Set an event from an external source
311   // The method is used in the online visualisation
312   fRunLoader = runLoader;
313   fRawReader = rawReader;
314   fESD = esd;
315   fIsOnline = kTRUE;
316   SetTitle("Online event in memory");
317   SetName("Online Event");
318
319   ElementChanged();
320   AfterNewEventLoaded();
321 }
322
323 void AliEveEventManager::GotoEvent(Int_t event)
324 {
325   // Load data for specified event.
326   // If event is out of range an exception is thrown and old state
327   // is preserved.
328   // After successful loading of event, the virtual function
329   // AfterNewEventLoaded() is called. This executes commands that
330   // were registered via TEveEventManager::AddNewEventCommand().
331
332   static const TEveException kEH("AliEveEventManager::GotoEvent ");
333
334   if (event < 0) {
335     Error(kEH, "event must be non-negative.");
336     return;
337   }
338
339   Int_t maxEvent = 0;
340   if (fRunLoader) {
341     maxEvent = fRunLoader->GetNumberOfEvents() - 1;
342   } else if (fESDTree) {
343     maxEvent = fESDTree->GetEntries() - 1;
344   } else if (fRawReader) {
345     maxEvent = 10000000;
346     Info(kEH, "number of events unknown for raw-data, setting max-event id to 10M.");
347   } else {
348     throw (kEH + "neither RunLoader, ESD nor Raw loaded.");
349   }
350   if (event < 0 || event > maxEvent)
351     throw (kEH + Form("event %d not present, available range [%d, %d].",
352                       event, 0, maxEvent));
353
354   TEveManager::TRedrawDisabler rd(gEve);
355   gEve->Redraw3D(kFALSE, kTRUE); // Enforce drop of all logicals.
356
357   // !!! MT this is somewhat brutal; at least optionally, one could be
358   // a bit gentler, checking for objs owning their external refs and having
359   // additinal parents.
360   DestroyElements();
361
362   if (fRunLoader) {
363     if (fRunLoader->GetEvent(event) != 0)
364       throw (kEH + "failed getting required event.");
365   }
366
367   if (fESDTree) {
368     if (fESDTree->GetEntry(event) <= 0)
369       throw (kEH + "failed getting required event from ESD.");
370
371     if (fESDfriendExists)
372       fESD->SetESDfriend(fESDfriend);
373   }
374
375   if (fRawReader)
376   {
377     Int_t rawEv = fEventId;
378     if (event < rawEv)
379     {
380       fRawReader->RewindEvents();
381       rawEv = -1;
382     }
383
384     while (rawEv < event)
385     {
386       if ( ! fRawReader->NextEvent())
387       {
388         fRawReader->RewindEvents();
389         fEventId = -1;
390         throw (kEH + Form("Error going to next raw-event from event %d.", rawEv));
391       }
392       ++rawEv;
393     }
394
395     printf ("Loaded raw-event %d.\n", rawEv);
396   }
397
398   fEventId = event;
399   SetName(Form("Event %d", fEventId));
400   ElementChanged();
401
402   AfterNewEventLoaded();
403 }
404
405 void AliEveEventManager::Close()
406 {
407   // Close the event files.
408   // For the moment only ESD is closed. Needs to be investigated for
409   // AliRunLoader and Raw.
410
411   if (fESDTree) {
412     delete fESD;       fESD       = 0;
413     delete fESDfriend; fESDfriend = 0;
414
415     delete fESDTree; fESDTree = 0;
416     delete fESDFile; fESDFile = 0;
417   }
418 }
419
420
421 /******************************************************************************/
422 // Static convenience functions, mainly used from macros.
423 /******************************************************************************/
424
425 AliRunLoader* AliEveEventManager::AssertRunLoader()
426 {
427   // Make sure AliRunLoader is initialized and return it.
428   // Throws exception in case run-loader is not available.
429   // Static utility for macros.
430
431   static const TEveException kEH("AliEveEventManager::AssertRunLoader ");
432
433   if (gAliEveEvent == 0)
434     throw (kEH + "ALICE event not ready.");
435   if (gAliEveEvent->fRunLoader == 0)
436     throw (kEH + "AliRunLoader not initialised.");
437   return gAliEveEvent->fRunLoader;
438 }
439
440 AliESDEvent* AliEveEventManager::AssertESD()
441 {
442   // Make sure AliESDEvent is initialized and return it.
443   // Throws exception in case ESD is not available.
444   // Static utility for macros.
445
446   static const TEveException kEH("AliEveEventManager::AssertESD ");
447
448   if (gAliEveEvent == 0)
449     throw (kEH + "ALICE event not ready.");
450   if (gAliEveEvent->fESD == 0)
451     throw (kEH + "AliESD not initialised.");
452   return gAliEveEvent->fESD;
453 }
454
455 AliESDfriend* AliEveEventManager::AssertESDfriend()
456 {
457   // Make sure AliESDfriend is initialized and return it.
458   // Throws exception in case ESDfriend-loader is not available.
459   // Static utility for macros.
460
461   static const TEveException kEH("AliEveEventManager::AssertESDfriend ");
462
463   if (gAliEveEvent == 0)
464     throw (kEH + "ALICE event not ready.");
465   if (gAliEveEvent->fESDfriend == 0)
466     throw (kEH + "AliESDfriend not initialised.");
467   return gAliEveEvent->fESDfriend;
468 }
469
470 AliRawReader* AliEveEventManager::AssertRawReader()
471 {
472   // Make sure raw-reader is initialized and return it.
473
474   static const TEveException kEH("AliEveEventManager::AssertRawReader ");
475
476   if (gAliEveEvent == 0)
477     throw (kEH + "ALICE event not ready.");
478   if (gAliEveEvent->fRawReader == 0)
479     throw (kEH + "RawReader not ready.");
480
481   return gAliEveEvent->fRawReader;
482 }
483
484 AliMagF* AliEveEventManager::AssertMagField()
485 {
486   // Make sure AliMagF is initialized and return it.
487   // Throws exception in case magnetic field is not available.
488   // Static utility for macros.
489
490   if (fgMagField == 0)
491   {
492     if (gAliEveEvent && gAliEveEvent->fRunLoader && gAliEveEvent->fRunLoader->GetAliRun())
493       fgMagField = gAliEveEvent->fRunLoader->GetAliRun()->Field();
494     else
495       fgMagField = new AliMagFMaps("Maps","Maps", 1, 1., 10., AliMagFMaps::k5kG);
496   }
497   return fgMagField;
498 }
499
500 TGeoManager* AliEveEventManager::AssertGeometry()
501 {
502   // Make sure AliGeomManager is initialized and returns the
503   // corresponding TGeoManger.
504   // gGeoManager is set to the return value.
505   // Throws exception if geometry can not be loaded or if it is not
506   // available and the TGeoManager is locked.
507   // Static utility for macros.
508
509   static const TEveException kEH("AliEveEventManager::AssertGeometry ");
510
511   if (AliGeomManager::GetGeometry() == 0)
512   {
513     if (TGeoManager::IsLocked())
514       throw (kEH + "geometry is not loaded but TGeoManager is locked.");
515
516     gGeoManager = 0;
517     AliGeomManager::LoadGeometry();
518     if ( ! AliGeomManager::GetGeometry())
519     {
520       throw (kEH + "can not load geometry.");
521     }
522     if ( ! AliGeomManager::ApplyAlignObjsFromCDB("ITS TPC TRD TOF PHOS HMPID EMCAL MUON FMD ZDC PMD T0 VZERO ACORDE"))
523     {
524       ::Warning(kEH, "mismatch of alignable volumes. Proceeding.");
525       // throw (kEH + "could not apply align objs.");
526     }
527     AliGeomManager::GetGeometry()->DefaultColors();
528   }
529
530   gGeoManager = AliGeomManager::GetGeometry();
531   return gGeoManager;
532 }
533
534 void AliEveEventManager::SetAutoLoad(Bool_t autoLoad)
535 {
536   // Set the automatic event loading mode
537   fAutoLoad = autoLoad;
538   StartStopAutoLoadTimer();
539 }
540
541 void AliEveEventManager::SetAutoLoadTime(Double_t time)
542 {
543   // Set the auto-load time in seconds
544   fAutoLoadTime = time;
545   StartStopAutoLoadTimer();
546 }
547
548 void AliEveEventManager::StartStopAutoLoadTimer()
549 {
550   // Create if needed and start
551   // the automatic event loading timer
552   if (fAutoLoad) {
553     if (!fAutoLoadTimer) {
554       fAutoLoadTimer = new TTimer;
555       fAutoLoadTimer->Connect("Timeout()","AliEveEventManager",this,"NextEvent()");
556     }
557     fAutoLoadTimer->Start((Long_t)fAutoLoadTime*1000,kTRUE);
558   }
559   else {
560     if (fAutoLoadTimer) fAutoLoadTimer->Stop();
561   }
562 }
563
564 void AliEveEventManager::PrevEvent()
565 {
566   // Loads previous event
567   // only in case of manual mode
568   if (!fIsOnline) {
569     GotoEvent(fEventId - 1);
570     StartStopAutoLoadTimer();
571   }
572 }
573
574 void AliEveEventManager::NextEvent()
575 {
576   // Loads next event
577   // either in automatic (online) or
578   // manual mode
579   
580   if (fIsOnline) {
581     if (fAutoLoadTimer) fAutoLoadTimer->Stop();
582
583     DestroyElements();
584
585     gSystem->ExitLoop();
586   }
587   else {
588     GotoEvent(fEventId + 1);
589     StartStopAutoLoadTimer();
590   }
591 }
592
593 const char* AliEveEventManager::GetEventInfo() const
594 {
595   // Dumps the event-header contents
596
597   static TString eventInfo;
598
599   if (!fRawReader) return "No event information is available";
600
601   const UInt_t* id = fRawReader->GetEventId();
602   const UInt_t* pattern = fRawReader->GetTriggerPattern();
603   const UInt_t* attr = fRawReader->GetAttributes();
604   eventInfo.Form("Run#: %d\nEvent type: %d\nPeriod: %x\nOrbit: %x\nBC: %x\nTrigger: %x-%x\nDetectors: %x\nAttributes:%x-%x-%x",
605                  fRawReader->GetRunNumber(),fRawReader->GetType(),
606                  (((id)[0]>>4)&0x0fffffff),((((id)[0]<<20)&0xf00000)|(((id)[1]>>12)&0xfffff)),((id)[1]&0x00000fff),
607                  pattern[0],pattern[1],
608                  *fRawReader->GetDetectorPattern(),
609                  attr[0],attr[1],attr[2]);
610
611   return eventInfo.Data();
612 }
613