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