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