Adding setting of default CDB storage (if not defined)
[u/mrichter/AliRoot.git] / MUON / AliMUONMCDataInterface.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercial purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 // $Id$
17
18 //-----------------------------------------------------------------------------
19 /// \class AliMUONMCDataInterface
20 ///
21 /// Easy to use MC data accessor
22 ///
23 /// \author Laurent Aphecetche, Subatech
24 ///
25 // Moved parts of old AliMUONDataInterface interface to AliMUONMCDataInterface
26 //  Artur Szostak <artursz@iafrica.com> (University of Cape Town)
27 //-----------------------------------------------------------------------------
28
29 #include "AliMUONMCDataInterface.h"
30 #include "AliMUONVDigitStore.h"
31 #include "AliMUONVHitStore.h"
32 #include "AliMUONVTriggerStore.h"
33 #include "AliMUONHit.h"
34 #include "AliMUONVDigit.h"
35 #include "AliMUONLocalTrigger.h"
36 #include "AliMUONRegionalTrigger.h"
37 #include "AliMUONGlobalTrigger.h"
38
39 #include "AliMpIntPair.h"
40 #include "AliMpDEManager.h"
41 #include "AliMpConstants.h"
42 #include "AliMpCDB.h"
43
44 #include "AliLog.h"
45 #include "AliRunLoader.h"
46 #include "AliHeader.h"
47 #include "AliStack.h"
48 #include "AliCDBManager.h"
49
50 #include <Riostream.h>
51 #include <TClonesArray.h>
52 #include <TList.h>
53 #include <TParticle.h>
54 #include <TIterator.h>
55 #include <cstdlib>
56 #include <cassert>
57
58 /// \cond CLASSIMP
59 ClassImp(AliMUONMCDataInterface)
60 /// \endcond
61
62 Int_t AliMUONMCDataInterface::fgInstanceCounter(0);
63
64 //_____________________________________________________________________________
65 AliMUONMCDataInterface::AliMUONMCDataInterface(const char* filename) :
66 TObject(),
67 fLoader(0x0),
68 fHitStore(0x0),
69 fSDigitStore(0x0),
70 fDigitStore(0x0),
71 fTriggerStore(0x0),
72 fTrackRefs(0x0),
73 fCurrentEvent(-1),
74 fIsValid(kFALSE),
75 fCurrentIteratorType(kNoIterator),
76 fCurrentIndex(-1),
77 fDataX(-1),
78 fDataY(-1),
79 fIterator(0x0)
80 {
81   /// ctor
82   
83   ++fgInstanceCounter;
84   
85   if (AliCDBManager::Instance() != NULL)
86   {
87     if (AliCDBManager::Instance()->GetDefaultStorage() == NULL)
88     {
89       AliInfo("Default storage for CDB not set.");
90       AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
91     }
92   }
93   
94   Open(filename);
95
96   // Load mapping
97   if ( ! AliMpCDB::LoadMpSegmentation() ) {
98     AliFatal("Could not access mapping from OCDB !");
99   }
100 }
101
102 //_____________________________________________________________________________
103 AliMUONMCDataInterface::~AliMUONMCDataInterface()
104 {
105   /// dtor
106   if ( fLoader ) 
107   {
108     delete fLoader->GetRunLoader();
109   }
110   --fgInstanceCounter;
111 }
112
113 //_____________________________________________________________________________
114 AliMUONVHitStore* 
115 AliMUONMCDataInterface::HitStore(Int_t event, Int_t track)
116 {
117   /// Return the hitStore for a given track of one event
118   /// Return 0x0 if event and/or track not found
119   /// Returned pointer should not be deleted
120   
121   if (not IsValid()) return 0x0;
122
123   if (event == fCurrentEvent)
124   {
125     if (track == fDataX and fHitStore != 0x0)  // using fDataX as track number.
126       return fHitStore;
127   }
128   else
129   {
130     ResetStores();
131     if ( not LoadEvent(event) ) return 0x0;
132   }
133   
134   fLoader->LoadHits();
135   
136   TTree* treeH = fLoader->TreeH();
137   if (treeH == 0x0)
138   {
139     AliError("Could not get treeH");
140     return 0x0;
141   }
142   
143   fHitStore = AliMUONVHitStore::Create(*treeH);
144   AliDebug(1,"Creating hitStore from treeH");
145   if ( fHitStore != 0x0 )
146   {
147     fHitStore->Connect(*treeH);
148     if ( treeH->GetEvent(track) == 0 ) 
149     {
150       AliError(Form("Could not read track %d",track));
151       fHitStore->Clear();
152       return 0x0;
153     }
154     fDataX = track; // using fDataX as track number.
155   }
156   
157   fLoader->UnloadHits();
158
159   return fHitStore;
160 }
161
162 //_____________________________________________________________________________
163 AliMUONVDigitStore*
164 AliMUONMCDataInterface::SDigitStore(Int_t event)
165 {
166   /// Return the SDigit store for a given event.
167   /// Return 0 if event not found
168   /// Returned pointer should not be deleted
169   
170   if (not IsValid()) return 0x0;
171   
172   if (event == fCurrentEvent)
173   {
174     if (fSDigitStore != 0x0)
175       return fSDigitStore;
176   }
177   else
178   {
179     ResetStores();
180     if ( not LoadEvent(event) ) return 0x0;
181   }
182   
183   fLoader->LoadSDigits();
184   
185   TTree* treeS = fLoader->TreeS();
186   if (treeS == 0x0)
187   {
188     AliError("Could not get treeS");
189     return 0x0;
190   }
191   
192   fSDigitStore = AliMUONVDigitStore::Create(*treeS);
193   if ( fSDigitStore != 0x0 )
194   {
195     fSDigitStore->Clear();
196     fSDigitStore->Connect(*treeS);
197     treeS->GetEvent(0);
198   }
199   
200   fLoader->UnloadSDigits();
201   
202   return fSDigitStore;
203 }
204
205 //_____________________________________________________________________________
206 AliMUONVDigitStore*
207 AliMUONMCDataInterface::DigitStore(Int_t event)
208 {
209   /// Return a pointer to the digitStore for a given event (or 0 if not found)
210   /// Returned pointer should not be deleted
211   
212   if (not IsValid()) return 0x0;
213   
214   if (event == fCurrentEvent)
215   {
216     if (fDigitStore != 0x0)
217       return fDigitStore;
218   }
219   else
220   {
221     ResetStores();
222     if ( not LoadEvent(event) ) return 0x0;
223   }
224   
225   fLoader->LoadDigits();
226   
227   TTree* treeD = fLoader->TreeD();
228   if (treeD == 0x0)
229   {
230     AliError("Could not get treeD");
231     return 0x0;
232   }
233   
234   fDigitStore = AliMUONVDigitStore::Create(*treeD);
235   if ( fDigitStore != 0x0 ) 
236   {
237     fDigitStore->Clear();
238     fDigitStore->Connect(*treeD);
239     treeD->GetEvent(0);
240   }
241   
242   fLoader->UnloadDigits();
243   
244   return fDigitStore;
245 }
246
247 //_____________________________________________________________________________
248 AliStack*
249 AliMUONMCDataInterface::Stack(Int_t event)
250 {
251   /// Get the Stack (list of generated particles) for one event
252   /// Returned pointer should not be deleted
253   
254   if ( not IsValid() ) return 0x0;
255
256   if (event != fCurrentEvent)
257   {
258     ResetStores();
259     if ( not LoadEvent(event) ) return 0x0;
260   }
261   
262   fLoader->GetRunLoader()->LoadKinematics();
263   
264   return fLoader->GetRunLoader()->Stack();
265 }
266
267 //_____________________________________________________________________________
268 TClonesArray*
269 AliMUONMCDataInterface::TrackRefs(Int_t event, Int_t track)
270 {
271   /// Get the track references for a given (generated) track of one event
272   /// Returned pointer should not be deleted
273   
274   if ( not IsValid() ) return 0x0;
275   
276   if (event == fCurrentEvent)
277   {
278     if (track == fDataX and fTrackRefs != 0x0)  // using fDataX as track number.
279       return fTrackRefs;
280   }
281   else
282   {
283     ResetStores();
284     if ( not LoadEvent(event) ) return 0x0;
285   }
286   
287   fLoader->GetRunLoader()->LoadTrackRefs();
288   
289   TTree* treeTR = fLoader->GetRunLoader()->TreeTR();
290   
291   if ( fTrackRefs != 0x0 ) fTrackRefs->Clear("C");
292   
293   if (treeTR != 0x0)
294   {
295     if ( treeTR->GetEvent(track) > 0 ) 
296     {
297       TBranch* branch = treeTR->GetBranch("TrackReferences");
298       branch->SetAddress(&fTrackRefs);
299       branch->GetEvent(track);
300       fDataX = track;  // using fDataX as track number.
301     }
302   }
303   else
304   {
305     AliError("Could not get TreeTR");
306   }
307   
308   fLoader->GetRunLoader()->UnloadTrackRefs();
309   
310   return fTrackRefs;
311 }
312
313 //_____________________________________________________________________________
314 AliMUONVTriggerStore*
315 AliMUONMCDataInterface::TriggerStore(Int_t event)
316 {
317   /// Return the triggerStore for a given event.
318   /// Return 0x0 if event not found.
319   /// Returned pointer should not be deleted.
320   
321   if (not IsValid()) return 0x0;
322   
323   if (event == fCurrentEvent)
324   {
325     if (fTriggerStore != 0x0)
326       return fTriggerStore;
327   }
328   else
329   {
330     ResetStores();
331     if ( not LoadEvent(event) ) return 0x0;
332   }
333   
334   fLoader->LoadDigits();
335   
336   TTree* treeD = fLoader->TreeD();
337   if ( treeD == 0x0 ) 
338   {
339     AliError("Could not get treeD");
340     return 0x0;
341   }
342   
343   fTriggerStore = AliMUONVTriggerStore::Create(*treeD);
344   if ( fTriggerStore != 0x0 )
345   {
346     fTriggerStore->Clear();
347     fTriggerStore->Connect(*treeD);
348     treeD->GetEvent(0);
349   }
350   
351   fLoader->UnloadDigits();
352   
353   return fTriggerStore;
354 }
355
356 //_____________________________________________________________________________
357 void
358 AliMUONMCDataInterface::DumpDigits(Int_t event, Bool_t sorted)
359 {
360   /// Dump the digits for a given event, sorted if requested.
361   DigitStore(event);
362   
363   if ( fDigitStore != 0x0 ) 
364   {
365     if ( sorted ) 
366     {
367       DumpSorted(*fDigitStore);
368     }
369     else
370     {
371       fDigitStore->Print();
372     }  
373   }
374 }
375
376 //_____________________________________________________________________________
377 void
378 AliMUONMCDataInterface::DumpHits(Int_t event)
379 {
380   /// Dump all the hits for one event
381   
382   Int_t ntracks = NumberOfTracks(event);
383   
384   for ( Int_t i = 0; i < ntracks; ++i ) 
385   {
386     cout << ">> Track " << i << endl;
387     HitStore(event,i);
388     if ( fHitStore )
389     {
390       fHitStore->Print("","full");
391     }
392   }
393 }
394
395 //_____________________________________________________________________________
396 void
397 AliMUONMCDataInterface::DumpKine(Int_t event)
398 {
399   /// Dump all generated particles for one event
400   AliStack* stack = Stack(event);
401   
402   if ( stack != 0x0 ) 
403   {
404     Int_t nparticles = (Int_t) stack->GetNtrack();
405   
406     for (Int_t iparticle=0; iparticle<nparticles; ++iparticle) 
407     {
408       stack->Particle(iparticle)->Print("");  
409     }
410   }
411   else
412   {
413     AliError("Could not get stack");
414   }
415 }
416
417 //_____________________________________________________________________________
418 void
419 AliMUONMCDataInterface::DumpSDigits(Int_t event, Bool_t sorted)
420 {
421   /// Dump the SDigits for a given event, sorted if requested
422   SDigitStore(event);
423   
424   if ( fSDigitStore != 0x0 ) 
425   {
426     if ( sorted ) 
427     {
428       DumpSorted(*fSDigitStore);
429     }
430     else
431     {
432       fSDigitStore->Print();
433     }
434   }
435 }
436
437 //_____________________________________________________________________________
438 void
439 AliMUONMCDataInterface::DumpSorted(const AliMUONVStore& store) const
440 {
441   /// Dump the given store in sorted order
442   
443   TIter next(store.CreateIterator());
444   TObject* object;
445   TList list;
446   list.SetOwner(kFALSE);
447   
448   while ( ( object = next() ) )
449   {
450     list.Add(object);
451   }
452   
453   list.Sort();
454   
455   list.Print();
456 }
457
458 //_____________________________________________________________________________
459 void
460 AliMUONMCDataInterface::DumpTrackRefs(Int_t event)
461 {
462   /// Dump track references for one event
463   Int_t ntrackrefs = NumberOfTrackRefs(event);
464   
465   for ( Int_t i = 0; i < ntrackrefs; ++i ) 
466   {
467     TrackRefs(event,i);
468     if ( fTrackRefs != 0x0 ) 
469     {
470       fTrackRefs->Print("","*");
471     }
472   }
473 }
474
475 //_____________________________________________________________________________
476 void
477 AliMUONMCDataInterface::DumpTrigger(Int_t event)
478 {
479   /// Dump trigger for a given event (trigger is read from TreeD)
480   
481   TriggerStore(event);
482
483   if ( fTriggerStore != 0x0 ) 
484   {
485     fTriggerStore->Print();
486   }
487 }
488
489 //_____________________________________________________________________________
490 Bool_t
491 AliMUONMCDataInterface::LoadEvent(Int_t event)
492 {
493   /// Load event if different from the current one.
494   /// Returns kFALSE on error and kTRUE if the event was loaded.
495   
496   assert( IsValid() );
497   
498   AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
499   if (fLoader->GetRunLoader()->GetEvent(event) == 0)
500   {
501     fCurrentEvent = event;
502     return kTRUE;
503   }
504   else
505     return kFALSE;
506 }
507
508
509 //_____________________________________________________________________________
510 Int_t 
511 AliMUONMCDataInterface::NumberOfEvents() const
512 {
513   /// Number of events in the file we're connected to
514   if (not IsValid()) return -1;
515   return fLoader->GetRunLoader()->GetNumberOfEvents();
516 }
517
518 //_____________________________________________________________________________
519 Int_t 
520 AliMUONMCDataInterface::NumberOfTracks(Int_t event)
521 {
522   /// Number of tracks in the event
523   if ( not IsValid()) return -1;
524   
525   if (event != fCurrentEvent)
526   {
527     ResetStores();
528     if ( not LoadEvent(event) ) return -1;
529   }
530   
531   fLoader->LoadHits();
532   
533   Int_t rv(-1);
534   
535   TTree* treeH = fLoader->TreeH();
536   if (treeH != 0x0)
537   {
538     rv = static_cast<Int_t>(treeH->GetEntries());
539   }
540   else
541   {
542     AliError("Could not get TreeH");
543   }
544
545   fLoader->UnloadHits();
546   
547   return rv;
548 }
549
550 //_____________________________________________________________________________
551 Int_t 
552 AliMUONMCDataInterface::NumberOfTrackRefs(Int_t event)
553 {
554   /// Number of track references in the event
555   if ( not IsValid()) return -1;
556   
557   if (event != fCurrentEvent)
558   {
559     ResetStores();
560     if ( not LoadEvent(event) ) return -1;
561   }
562
563   fLoader->GetRunLoader()->LoadTrackRefs();
564   
565   Int_t rv(-1);
566   
567   TTree* treeTR = fLoader->GetRunLoader()->TreeTR();
568   if (treeTR != 0x0)
569   {
570     rv = static_cast<Int_t>(treeTR->GetEntries());
571   }
572   else
573   {
574     AliError("Could not get TreeTR");
575   }
576   
577   fLoader->GetRunLoader()->UnloadTrackRefs();
578   
579   return rv;
580 }
581
582 //_____________________________________________________________________________
583 void
584 AliMUONMCDataInterface::Open(const char* filename)
585 {
586   /// Connect to a given galice.root file
587   
588   ResetStores();
589   
590   fCurrentEvent=-1;
591
592   if ( fLoader != 0x0 )
593   {
594     delete fLoader->GetRunLoader();
595   }
596   
597   fLoader = 0x0;
598   
599   fIsValid = kTRUE;
600   
601   TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
602   
603   while (AliRunLoader::GetRunLoader(foldername)) 
604   {
605     delete AliRunLoader::GetRunLoader(foldername);
606   }
607   
608   AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
609   if (runLoader == 0x0)
610   {
611     AliError(Form("Cannot open file %s",filename));    
612     fIsValid = kFALSE;
613   }
614   
615   // Get run number and set it to CDB manager
616   runLoader->LoadHeader();
617   if ( ! runLoader->GetHeader() ) {
618     AliError("Cannot load header.");    
619     fIsValid = kFALSE;
620   }
621   else {
622     Int_t runNumber = runLoader->GetHeader()->GetRun();
623     AliCDBManager::Instance()->SetRun(runNumber);
624   }  
625   runLoader->UnloadHeader(); 
626
627   fLoader = runLoader->GetDetectorLoader("MUON");
628   if (fLoader == 0x0)
629   {
630     AliError("Cannot get AliMUONLoader");
631     fIsValid = kFALSE;
632   }
633   
634   if (not IsValid())
635   {
636     AliError(Form("Could not access %s filename. Object is unuseable",filename));
637   }
638 }
639
640 //_____________________________________________________________________________
641 Bool_t AliMUONMCDataInterface::GetEvent(Int_t event)
642 {
643 /// Loads all simulated data for the given event.
644
645   if (HitStore(event, 0) == 0x0) return kFALSE;
646   if (SDigitStore(event) == 0x0) return kFALSE;
647   if (DigitStore(event) == 0x0) return kFALSE;
648   if (TriggerStore(event) == 0x0) return kFALSE;
649   if (TrackRefs(event, 0) == 0x0) return kFALSE;
650   return kTRUE;
651 }
652
653 //_____________________________________________________________________________
654 Int_t AliMUONMCDataInterface::NumberOfParticles()
655 {
656 /// Returns the total number of particles in the kinematics tree.
657
658   AliStack* stack = Stack(fCurrentEvent);
659   if ( stack == 0x0 ) return -1;
660   return (Int_t) stack->GetNtrack();
661 }
662
663 //_____________________________________________________________________________
664 TParticle* AliMUONMCDataInterface::Particle(Int_t index)
665 {
666 /// Returns the index'th particle in the kinematics tree.
667 /// @param index  The index number of the particle in the range [0 ... N-1]
668 ///               where N = NumberOfParticles()
669
670   AliStack* stack = Stack(fCurrentEvent);
671   if ( stack == 0x0 ) return 0x0;
672   return static_cast<TParticle*>( stack->Particle(index) );
673 }
674
675 //_____________________________________________________________________________
676 Int_t AliMUONMCDataInterface::NumberOfTracks()
677 {
678 /// Returns the number of primary tracks (from primary particles) in the current event.
679
680   return NumberOfTracks(fCurrentEvent);
681 }
682
683 //_____________________________________________________________________________
684 Int_t AliMUONMCDataInterface::NumberOfHits(Int_t track)
685 {
686 /// Returns the number of hits for a given primary track/particle.
687 /// @param track  The track number in the range [0 .. N-1]
688 ///               where N = NumberOfTracks()
689
690   TIterator* iter = GetIterator(kHitIterator, track);
691   return CountObjects(iter);
692 }
693
694 //_____________________________________________________________________________
695 AliMUONHit* 
696 AliMUONMCDataInterface::Hit(Int_t track, Int_t index)
697 {
698 /// Returns a pointer to the index'th hit object.
699 /// @param track  The track number in the range [0 .. N-1]
700 ///               where N = NumberOfTracks()
701 /// @param index  The index number of the hit in the range [0 ... M-1]
702 ///               where M = NumberOfHits(track)
703
704   TIterator* iter = GetIterator(kHitIterator, track);
705   return static_cast<AliMUONHit*>( FetchObject(iter, index) );
706 }
707
708 //_____________________________________________________________________________
709 Int_t AliMUONMCDataInterface::NumberOfSDigits(Int_t detElemId)
710 {
711 /// Returns the number of summable digits to be found on a given detector element.
712 /// @param detElemId  The detector element ID number to search on.
713
714   TIterator* iter = GetIterator(kSDigitIteratorByDetectorElement, detElemId);
715   return CountObjects(iter);
716 }
717
718 //_____________________________________________________________________________
719 AliMUONVDigit* AliMUONMCDataInterface::SDigit(Int_t detElemId, Int_t index)
720 {
721 /// Returns the a pointer to the index'th summable digit on the specified detector element.
722 /// @param detElemId  The detector element ID number to search on.
723 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
724 ///   where N = NumberOfDigits(detElemId)
725
726   TIterator* iter = GetIterator(kSDigitIteratorByDetectorElement, detElemId);
727   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
728 }
729
730 //_____________________________________________________________________________
731 Int_t AliMUONMCDataInterface::NumberOfSDigits(Int_t chamber, Int_t cathode)
732 {
733 /// Returns the number of summable digits to be found on a specific chamber and cathode.
734 /// @param chamber  The chamber number in the range [0 .. 13].
735 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
736 ///   1 is the non-bending plane.
737
738   TIterator* iter = GetIterator(kSDigitIteratorByChamberAndCathode, chamber, cathode);
739   return CountObjects(iter);
740 }
741
742 //_____________________________________________________________________________
743 AliMUONVDigit* AliMUONMCDataInterface::SDigit(Int_t chamber, Int_t cathode, Int_t index)
744 {
745 /// Returns the a pointer to the index'th summable digit on the specified chamber and cathode.
746 /// @param chamber  The chamber number in the range [0 .. 13].
747 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
748 ///   1 is the non-bending plane.
749 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
750 ///   where N = NumberOfDigits(chamber, cathode)
751
752   TIterator* iter = GetIterator(kSDigitIteratorByChamberAndCathode, chamber, cathode);
753   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
754 }
755
756 //_____________________________________________________________________________
757 Int_t AliMUONMCDataInterface::NumberOfDigits(Int_t detElemId)
758 {
759 /// Returns the number of simulated digits to be found on a given detector element.
760 /// @param detElemId  The detector element ID number to search on.
761
762   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
763   return CountObjects(iter);
764 }
765
766 //_____________________________________________________________________________
767 AliMUONVDigit* AliMUONMCDataInterface::Digit(Int_t detElemId, Int_t index)
768 {
769 /// Returns the a pointer to the index'th simulated digit on the specified detector element.
770 /// @param detElemId  The detector element ID number to search on.
771 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
772 ///   where N = NumberOfDigits(detElemId)
773
774   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
775   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
776 }
777
778 //_____________________________________________________________________________
779 Int_t AliMUONMCDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
780 {
781 /// Returns the number of simulated digits to be found on a specific chamber and cathode.
782 /// @param chamber  The chamber number in the range [0 .. 13].
783 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
784 ///   1 is the non-bending plane.
785
786   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
787   return CountObjects(iter);
788 }
789
790 //_____________________________________________________________________________
791 AliMUONVDigit* AliMUONMCDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
792 {
793 /// Returns the a pointer to the index'th simulated digit on the specified chamber and cathode.
794 /// @param chamber  The chamber number in the range [0 .. 13].
795 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
796 ///   1 is the non-bending plane.
797 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
798 ///   where N = NumberOfDigits(chamber, cathode)
799
800   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
801   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
802 }
803
804 //_____________________________________________________________________________
805 Int_t AliMUONMCDataInterface::NumberOfLocalTriggers()
806 {
807 /// Returns the number of simulated local trigger objects.
808
809   TIterator* iter = GetIterator(kLocalTriggerIterator);
810   return CountObjects(iter);
811 }
812
813 //_____________________________________________________________________________
814 AliMUONLocalTrigger* AliMUONMCDataInterface::LocalTrigger(Int_t index)
815 {
816 /// Returns a pointer to the index'th simulated local trigger object.
817 /// @param index  The index number of the local trigger object to fetch in the range [0 .. N-1],
818 ///   where N = NumberOfLocalTriggers()
819
820   TIterator* iter = GetIterator(kLocalTriggerIterator);
821   return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
822 }
823
824 //_____________________________________________________________________________
825 Int_t AliMUONMCDataInterface::NumberOfRegionalTriggers()
826 {
827 /// Returns the number of simulated regional trigger objects.
828
829   TIterator* iter = GetIterator(kRegionalTriggerIterator);
830   return CountObjects(iter);
831 }
832
833 //_____________________________________________________________________________
834 AliMUONRegionalTrigger* AliMUONMCDataInterface::RegionalTrigger(Int_t index)
835 {
836 /// Returns a pointer to the index'th simulated regional trigger object.
837 /// @param index  The index number of the regional trigger object to fetch in the range [0 .. N-1],
838 ///   where N = NumberOfRegionalTriggers()
839
840   TIterator* iter = GetIterator(kRegionalTriggerIterator);
841   return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
842 }
843
844 //_____________________________________________________________________________
845 AliMUONGlobalTrigger* AliMUONMCDataInterface::GlobalTrigger()
846 {
847 /// Returns a pointer to the simulated global trigger object for the event.
848
849   AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
850   if (store == 0x0) return 0x0;
851   return store->Global();
852 }
853
854 //_____________________________________________________________________________
855 Int_t AliMUONMCDataInterface::NumberOfTrackRefs()
856 {
857 /// Number of track references in the currently selected event.
858
859   return NumberOfTrackRefs(fCurrentEvent);
860 }
861
862 //_____________________________________________________________________________
863 TClonesArray* AliMUONMCDataInterface::TrackRefs(Int_t track)
864 {
865 /// Returns the track references for a given track in the current event.
866 /// @param track  The track to returns track references for. In the range [0 .. N-1]
867 ///               where N = NumberOfTrackRefs()
868
869   return TrackRefs(fCurrentEvent, track);
870 }
871
872 //_____________________________________________________________________________
873 void AliMUONMCDataInterface::ResetStores()
874 {
875 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
876 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
877
878   ResetIterator();
879   if (fHitStore != 0x0)
880   {
881     delete fHitStore;
882     fHitStore = 0x0;
883   }
884   if (fSDigitStore != 0x0)
885   {
886     delete fSDigitStore;
887     fSDigitStore = 0x0;
888   }
889   if (fDigitStore != 0x0)
890   {
891     delete fDigitStore;
892     fDigitStore = 0x0;
893   }
894   if (fTrackRefs != 0x0)
895   {
896     delete fTrackRefs;
897     fTrackRefs = 0x0;
898   }
899   if (fTriggerStore != 0x0)
900   {
901     delete fTriggerStore;
902     fTriggerStore = 0x0;
903   }
904 }
905
906 //_____________________________________________________________________________
907 TIterator* AliMUONMCDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
908 {
909 /// Creates an appropriate iterator object and returns it.
910 /// If the iterator has already been created then that one is returned otherwise
911 /// a new object is created.
912 /// Depending on the value of 'type' the semantics of parameters x and y can change.
913 /// @param type  The type of iterator to create.
914 /// @param x  This is the detector element ID if type equals kDigitIteratorByDetectorElement
915 ///           or kSDigitIteratorByDetectorElement.
916 ///           If type equals kDigitIteratorByChamberAndCathode or
917 ///           kSDigitIteratorByChamberAndCathode then this is the chamber number.
918 ///           For type == kHitIterator the parameter x is the track number.
919 ///           In all other cases this parameter is ignored.
920 /// @param y  If type equals kDigitIteratorByChamberAndCathode or
921 ///           kSDigitIteratorByChamberAndCathode then this parameter is the cathode
922 ///           number. In all other cases this parameter is ignored.
923
924   if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
925         return fIterator;
926   
927   if (fCurrentEvent == -1)
928   {
929     AliError("No event was selected. Try first using GetEvent().");
930     return 0x0;
931   }
932   
933   ResetIterator();
934   
935   switch (type)
936   {
937   case kHitIterator:
938     {
939       Int_t track = x;
940       AliMUONVHitStore* store = HitStore(fCurrentEvent, track);
941       if (store == 0x0) return 0x0;
942       fIterator = store->CreateIterator();
943       if (fIterator == 0x0) return 0x0;
944       fCurrentIteratorType = kHitIterator;
945       return fIterator;
946     }
947     
948   case kSDigitIteratorByDetectorElement:
949     {
950       Int_t detElem = x;
951       AliMUONVDigitStore* store = SDigitStore(fCurrentEvent);
952       if (store == 0x0) return 0x0;
953       fIterator = store->CreateIterator(detElem, detElem, 2);
954       if (fIterator == 0x0) return 0x0;
955       fCurrentIteratorType = kSDigitIteratorByDetectorElement;
956       fDataX = detElem;
957       return fIterator;
958     }
959     
960   case kSDigitIteratorByChamberAndCathode:
961     {
962       Int_t chamber = x;
963       Int_t cathode = y;
964       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
965       {
966         AliError(Form(
967           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
968           AliMpConstants::NofChambers() - 1,
969           chamber
970         ));
971         return 0x0;
972       }
973       if (cathode < 0 or 1 < cathode)
974       {
975         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
976         return 0x0;
977       }
978       
979       AliMUONVDigitStore* store = SDigitStore(fCurrentEvent);
980       if (store == 0x0) return 0x0;
981       AliMpIntPair pair = AliMpDEManager::GetDetElemIdRange(chamber);
982       fIterator = store->CreateIterator(pair.GetFirst(), pair.GetSecond(), cathode);
983       if (fIterator == 0x0) return 0x0;
984       fCurrentIteratorType = kSDigitIteratorByChamberAndCathode;
985       fDataX = chamber;
986       fDataY = cathode;
987       return fIterator;
988     }
989     
990   case kDigitIteratorByDetectorElement:
991     {
992       Int_t detElem = x;
993       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
994       if (store == 0x0) return 0x0;
995       fIterator = store->CreateIterator(detElem, detElem, 2);
996       if (fIterator == 0x0) return 0x0;
997       fCurrentIteratorType = kDigitIteratorByDetectorElement;
998       fDataX = detElem;
999       return fIterator;
1000     }
1001     
1002   case kDigitIteratorByChamberAndCathode:
1003     {
1004       Int_t chamber = x;
1005       Int_t cathode = y;
1006       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
1007       {
1008         AliError(Form(
1009           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
1010           AliMpConstants::NofChambers() - 1,
1011           chamber
1012         ));
1013         return 0x0;
1014       }
1015       if (cathode < 0 or 1 < cathode)
1016       {
1017         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
1018         return 0x0;
1019       }
1020       
1021       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
1022       if (store == 0x0) return 0x0;
1023       AliMpIntPair pair = AliMpDEManager::GetDetElemIdRange(chamber);
1024       fIterator = store->CreateIterator(pair.GetFirst(), pair.GetSecond(), cathode);
1025       if (fIterator == 0x0) return 0x0;
1026       fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
1027       fDataX = chamber;
1028       fDataY = cathode;
1029       return fIterator;
1030     }
1031     
1032   case kLocalTriggerIterator:
1033     {
1034       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
1035       if (store == 0x0) return 0x0;
1036       fIterator = store->CreateLocalIterator();
1037       if (fIterator == 0x0) return 0x0;
1038       fCurrentIteratorType = kLocalTriggerIterator;
1039       return fIterator;
1040     }
1041     
1042   case kRegionalTriggerIterator:
1043     {
1044       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
1045       if (store == 0x0) return 0x0;
1046       fIterator = store->CreateRegionalIterator();
1047       if (fIterator == 0x0) return 0x0;
1048       fCurrentIteratorType = kRegionalTriggerIterator;
1049       return fIterator;
1050     }
1051     
1052   default:
1053     return 0x0;
1054   }
1055 }
1056
1057 //_____________________________________________________________________________
1058 void AliMUONMCDataInterface::ResetIterator()
1059 {
1060 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
1061 /// The iterator type and temporary data indicating the state of the iterator are
1062 /// also reset.
1063
1064   if (fIterator != 0x0) delete fIterator;
1065   fCurrentIteratorType = kNoIterator;
1066   fCurrentIndex = fDataX = fDataY = -1;
1067   fIterator = 0x0;
1068 }
1069
1070 //_____________________________________________________________________________
1071 Int_t AliMUONMCDataInterface::CountObjects(TIterator* iter)
1072 {
1073 /// Counts the number of objects in the iterator and resets it.
1074 /// @return The number of objects in 'iter'.
1075
1076   if (iter == 0x0) return -1;
1077   Int_t count = 0;
1078   iter->Reset();
1079   while ( iter->Next() != 0x0 ) count++;
1080   iter->Reset();
1081   fCurrentIndex = -1;
1082   return count;
1083 }
1084
1085 //_____________________________________________________________________________
1086 TObject* AliMUONMCDataInterface::FetchObject(TIterator* iter, Int_t index)
1087 {
1088 /// Fetches the index'th object from the iterator counting the first object
1089 /// returned by iterator after it is reset as index == 0. The next object
1090 /// has index == 1 and so on where the last object returned by the iterator
1091 /// has index == N-1 where N = CountObjects(iter)
1092 /// This method will only reset the iterator if index is smaller than
1093 /// fCurrentIndex, which is used to track the iteration progress and is
1094 /// updated when a new object if returned by this method.
1095 /// @param iter  The iterator to fetch an object from.
1096 /// @param index The index number of the object to fetch in the range [0 .. N-1]
1097 ///        where N = CountObjects(iter)
1098
1099   if (index < 0)
1100   {
1101     AliError(Form("Index is out of bounds. Got a value of %d.", index));
1102     return 0x0;
1103   }
1104
1105   if (iter == 0x0) return 0x0;
1106   if (index <= fCurrentIndex)
1107   {
1108     iter->Reset();
1109     fCurrentIndex = -1;
1110   }
1111   
1112   TObject* object = 0x0;
1113   while (fCurrentIndex < index)
1114   {
1115     object = iter->Next();
1116     if (object == 0x0)
1117     {
1118       AliError(Form("Index is out of bounds. Got a value of %d.", index));
1119       iter->Reset();
1120       fCurrentIndex = -1;
1121       return 0x0;
1122     }
1123     fCurrentIndex++;
1124   }
1125   return object;
1126 }