]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONMCDataInterface.cxx
Fix coverity defects
[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     return;
646   }
647   
648   // Get run number and set it to CDB manager
649   runLoader->LoadHeader();
650   if ( ! runLoader->GetHeader() ) {
651     AliError("Cannot load header.");    
652     fIsValid = kFALSE;
653   }
654   else {
655     Int_t runNumber = runLoader->GetHeader()->GetRun();
656     AliCDBManager::Instance()->SetRun(runNumber);
657   }  
658   runLoader->UnloadHeader(); 
659
660   fLoader = runLoader->GetDetectorLoader("MUON");
661   if (fLoader == 0x0)
662   {
663     AliError("Cannot get AliMUONLoader");
664     fIsValid = kFALSE;
665   }
666   
667   if (not IsValid())
668   {
669     AliError(Form("Could not access %s filename. Object is unuseable",filename));
670   }
671 }
672
673 //_____________________________________________________________________________
674 Bool_t AliMUONMCDataInterface::GetEvent(Int_t event)
675 {
676 /// Loads all simulated data for the given event.
677
678   if (HitStore(event, 0) == 0x0) return kFALSE;
679   if (SDigitStore(event) == 0x0) return kFALSE;
680   if (DigitStore(event) == 0x0) return kFALSE;
681   if (TriggerStore(event) == 0x0) return kFALSE;
682   if (TrackRefs(event, 0) == 0x0) return kFALSE;
683   return kTRUE;
684 }
685
686 //_____________________________________________________________________________
687 Int_t AliMUONMCDataInterface::NumberOfParticles()
688 {
689 /// Returns the total number of particles in the kinematics tree.
690
691   AliStack* stack = Stack(fCurrentEvent);
692   if ( stack == 0x0 ) return -1;
693   return (Int_t) stack->GetNtrack();
694 }
695
696 //_____________________________________________________________________________
697 TParticle* AliMUONMCDataInterface::Particle(Int_t index)
698 {
699 /// Returns the index'th particle in the kinematics tree.
700 /// @param index  The index number of the particle in the range [0 ... N-1]
701 ///               where N = NumberOfParticles()
702
703   AliStack* stack = Stack(fCurrentEvent);
704   if ( stack == 0x0 ) return 0x0;
705   return static_cast<TParticle*>( stack->Particle(index) );
706 }
707
708 //_____________________________________________________________________________
709 Int_t AliMUONMCDataInterface::NumberOfTracks()
710 {
711 /// Returns the number of primary tracks (from primary particles) in the current event.
712
713   return NumberOfTracks(fCurrentEvent);
714 }
715
716 //_____________________________________________________________________________
717 Int_t AliMUONMCDataInterface::NumberOfHits(Int_t track)
718 {
719 /// Returns the number of hits for a given primary track/particle.
720 /// @param track  The track number in the range [0 .. N-1]
721 ///               where N = NumberOfTracks()
722
723   TIterator* iter = GetIterator(kHitIterator, track);
724   return CountObjects(iter);
725 }
726
727 //_____________________________________________________________________________
728 AliMUONHit* 
729 AliMUONMCDataInterface::Hit(Int_t track, Int_t index)
730 {
731 /// Returns a pointer to the index'th hit object.
732 /// @param track  The track number in the range [0 .. N-1]
733 ///               where N = NumberOfTracks()
734 /// @param index  The index number of the hit in the range [0 ... M-1]
735 ///               where M = NumberOfHits(track)
736
737   TIterator* iter = GetIterator(kHitIterator, track);
738   return static_cast<AliMUONHit*>( FetchObject(iter, index) );
739 }
740
741 //_____________________________________________________________________________
742 Int_t AliMUONMCDataInterface::NumberOfSDigits(Int_t detElemId)
743 {
744 /// Returns the number of summable digits to be found on a given detector element.
745 /// @param detElemId  The detector element ID number to search on.
746
747   TIterator* iter = GetIterator(kSDigitIteratorByDetectorElement, detElemId);
748   return CountObjects(iter);
749 }
750
751 //_____________________________________________________________________________
752 AliMUONVDigit* AliMUONMCDataInterface::SDigit(Int_t detElemId, Int_t index)
753 {
754 /// Returns the a pointer to the index'th summable digit on the specified detector element.
755 /// @param detElemId  The detector element ID number to search on.
756 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
757 ///   where N = NumberOfDigits(detElemId)
758
759   TIterator* iter = GetIterator(kSDigitIteratorByDetectorElement, detElemId);
760   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
761 }
762
763 //_____________________________________________________________________________
764 Int_t AliMUONMCDataInterface::NumberOfSDigits(Int_t chamber, Int_t cathode)
765 {
766 /// Returns the number of summable digits to be found on a specific chamber and cathode.
767 /// @param chamber  The chamber number in the range [0 .. 13].
768 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
769 ///   1 is the non-bending plane.
770
771   TIterator* iter = GetIterator(kSDigitIteratorByChamberAndCathode, chamber, cathode);
772   return CountObjects(iter);
773 }
774
775 //_____________________________________________________________________________
776 AliMUONVDigit* AliMUONMCDataInterface::SDigit(Int_t chamber, Int_t cathode, Int_t index)
777 {
778 /// Returns the a pointer to the index'th summable digit on the specified chamber and cathode.
779 /// @param chamber  The chamber number in the range [0 .. 13].
780 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
781 ///   1 is the non-bending plane.
782 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
783 ///   where N = NumberOfDigits(chamber, cathode)
784
785   TIterator* iter = GetIterator(kSDigitIteratorByChamberAndCathode, chamber, cathode);
786   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
787 }
788
789 //_____________________________________________________________________________
790 Int_t AliMUONMCDataInterface::NumberOfDigits(Int_t detElemId)
791 {
792 /// Returns the number of simulated digits to be found on a given detector element.
793 /// @param detElemId  The detector element ID number to search on.
794
795   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
796   return CountObjects(iter);
797 }
798
799 //_____________________________________________________________________________
800 AliMUONVDigit* AliMUONMCDataInterface::Digit(Int_t detElemId, Int_t index)
801 {
802 /// Returns the a pointer to the index'th simulated digit on the specified detector element.
803 /// @param detElemId  The detector element ID number to search on.
804 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
805 ///   where N = NumberOfDigits(detElemId)
806
807   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
808   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
809 }
810
811 //_____________________________________________________________________________
812 Int_t AliMUONMCDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
813 {
814 /// Returns the number of simulated digits to be found on a specific chamber and cathode.
815 /// @param chamber  The chamber number in the range [0 .. 13].
816 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
817 ///   1 is the non-bending plane.
818
819   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
820   return CountObjects(iter);
821 }
822
823 //_____________________________________________________________________________
824 AliMUONVDigit* AliMUONMCDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
825 {
826 /// Returns the a pointer to the index'th simulated digit on the specified chamber and cathode.
827 /// @param chamber  The chamber number in the range [0 .. 13].
828 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
829 ///   1 is the non-bending plane.
830 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
831 ///   where N = NumberOfDigits(chamber, cathode)
832
833   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
834   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
835 }
836
837 //_____________________________________________________________________________
838 Int_t AliMUONMCDataInterface::NumberOfLocalTriggers()
839 {
840 /// Returns the number of simulated local trigger objects.
841
842   TIterator* iter = GetIterator(kLocalTriggerIterator);
843   return CountObjects(iter);
844 }
845
846 //_____________________________________________________________________________
847 AliMUONLocalTrigger* AliMUONMCDataInterface::LocalTrigger(Int_t index)
848 {
849 /// Returns a pointer to the index'th simulated local trigger object.
850 /// @param index  The index number of the local trigger object to fetch in the range [0 .. N-1],
851 ///   where N = NumberOfLocalTriggers()
852
853   TIterator* iter = GetIterator(kLocalTriggerIterator);
854   return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
855 }
856
857 //_____________________________________________________________________________
858 Int_t AliMUONMCDataInterface::NumberOfRegionalTriggers()
859 {
860 /// Returns the number of simulated regional trigger objects.
861
862   TIterator* iter = GetIterator(kRegionalTriggerIterator);
863   return CountObjects(iter);
864 }
865
866 //_____________________________________________________________________________
867 AliMUONRegionalTrigger* AliMUONMCDataInterface::RegionalTrigger(Int_t index)
868 {
869 /// Returns a pointer to the index'th simulated regional trigger object.
870 /// @param index  The index number of the regional trigger object to fetch in the range [0 .. N-1],
871 ///   where N = NumberOfRegionalTriggers()
872
873   TIterator* iter = GetIterator(kRegionalTriggerIterator);
874   return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
875 }
876
877 //_____________________________________________________________________________
878 AliMUONGlobalTrigger* AliMUONMCDataInterface::GlobalTrigger()
879 {
880 /// Returns a pointer to the simulated global trigger object for the event.
881
882   AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
883   if (store == 0x0) return 0x0;
884   return store->Global();
885 }
886
887 //_____________________________________________________________________________
888 Int_t AliMUONMCDataInterface::NumberOfTrackRefs()
889 {
890 /// Number of track references in the currently selected event.
891
892   return NumberOfTrackRefs(fCurrentEvent);
893 }
894
895 //_____________________________________________________________________________
896 TClonesArray* AliMUONMCDataInterface::TrackRefs(Int_t track)
897 {
898 /// Returns the track references for a given track in the current event.
899 /// @param track  The track to returns track references for. In the range [0 .. N-1]
900 ///               where N = NumberOfTrackRefs()
901
902   return TrackRefs(fCurrentEvent, track);
903 }
904
905 //_____________________________________________________________________________
906 void AliMUONMCDataInterface::ResetStores()
907 {
908 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
909 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
910
911   ResetIterator();
912   if (fHitStore != 0x0)
913   {
914     delete fHitStore;
915     fHitStore = 0x0;
916   }
917   if (fSDigitStore != 0x0)
918   {
919     delete fSDigitStore;
920     fSDigitStore = 0x0;
921   }
922   if (fDigitStore != 0x0)
923   {
924     delete fDigitStore;
925     fDigitStore = 0x0;
926   }
927   if (fTrackRefs != 0x0)
928   {
929     delete fTrackRefs;
930     fTrackRefs = 0x0;
931   }
932   if (fTriggerStore != 0x0)
933   {
934     delete fTriggerStore;
935     fTriggerStore = 0x0;
936   }
937 }
938
939 //_____________________________________________________________________________
940 TIterator* AliMUONMCDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
941 {
942 /// Creates an appropriate iterator object and returns it.
943 /// If the iterator has already been created then that one is returned otherwise
944 /// a new object is created.
945 /// Depending on the value of 'type' the semantics of parameters x and y can change.
946 /// @param type  The type of iterator to create.
947 /// @param x  This is the detector element ID if type equals kDigitIteratorByDetectorElement
948 ///           or kSDigitIteratorByDetectorElement.
949 ///           If type equals kDigitIteratorByChamberAndCathode or
950 ///           kSDigitIteratorByChamberAndCathode then this is the chamber number.
951 ///           For type == kHitIterator the parameter x is the track number.
952 ///           In all other cases this parameter is ignored.
953 /// @param y  If type equals kDigitIteratorByChamberAndCathode or
954 ///           kSDigitIteratorByChamberAndCathode then this parameter is the cathode
955 ///           number. In all other cases this parameter is ignored.
956
957   if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
958         return fIterator;
959   
960   if (fCurrentEvent == -1)
961   {
962     AliError("No event was selected. Try first using GetEvent().");
963     return 0x0;
964   }
965   
966   ResetIterator();
967   
968   switch (type)
969   {
970   case kHitIterator:
971     {
972       Int_t track = x;
973       AliMUONVHitStore* store = HitStore(fCurrentEvent, track);
974       if (store == 0x0) return 0x0;
975       fIterator = store->CreateIterator();
976       if (fIterator == 0x0) return 0x0;
977       fCurrentIteratorType = kHitIterator;
978       return fIterator;
979     }
980     
981   case kSDigitIteratorByDetectorElement:
982     {
983       Int_t detElem = x;
984       AliMUONVDigitStore* store = SDigitStore(fCurrentEvent);
985       if (store == 0x0) return 0x0;
986       fIterator = store->CreateIterator(detElem, detElem, 2);
987       if (fIterator == 0x0) return 0x0;
988       fCurrentIteratorType = kSDigitIteratorByDetectorElement;
989       fDataX = detElem;
990       return fIterator;
991     }
992     
993   case kSDigitIteratorByChamberAndCathode:
994     {
995       Int_t chamber = x;
996       Int_t cathode = y;
997       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
998       {
999         AliError(Form(
1000           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
1001           AliMpConstants::NofChambers() - 1,
1002           chamber
1003         ));
1004         return 0x0;
1005       }
1006       if (cathode < 0 or 1 < cathode)
1007       {
1008         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
1009         return 0x0;
1010       }
1011       
1012       AliMUONVDigitStore* store = SDigitStore(fCurrentEvent);
1013       if (store == 0x0) return 0x0;
1014       MpPair_t pair = AliMpDEManager::GetDetElemIdRange(chamber);
1015       fIterator = store->CreateIterator(AliMp::PairFirst(pair), AliMp::PairSecond(pair), cathode);
1016       if (fIterator == 0x0) return 0x0;
1017       fCurrentIteratorType = kSDigitIteratorByChamberAndCathode;
1018       fDataX = chamber;
1019       fDataY = cathode;
1020       return fIterator;
1021     }
1022     
1023   case kDigitIteratorByDetectorElement:
1024     {
1025       Int_t detElem = x;
1026       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
1027       if (store == 0x0) return 0x0;
1028       fIterator = store->CreateIterator(detElem, detElem, 2);
1029       if (fIterator == 0x0) return 0x0;
1030       fCurrentIteratorType = kDigitIteratorByDetectorElement;
1031       fDataX = detElem;
1032       return fIterator;
1033     }
1034     
1035   case kDigitIteratorByChamberAndCathode:
1036     {
1037       Int_t chamber = x;
1038       Int_t cathode = y;
1039       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
1040       {
1041         AliError(Form(
1042           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
1043           AliMpConstants::NofChambers() - 1,
1044           chamber
1045         ));
1046         return 0x0;
1047       }
1048       if (cathode < 0 or 1 < cathode)
1049       {
1050         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
1051         return 0x0;
1052       }
1053       
1054       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
1055       if (store == 0x0) return 0x0;
1056       MpPair_t pair = AliMpDEManager::GetDetElemIdRange(chamber);
1057       fIterator = store->CreateIterator(AliMp::PairFirst(pair), AliMp::PairSecond(pair), cathode);
1058       if (fIterator == 0x0) return 0x0;
1059       fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
1060       fDataX = chamber;
1061       fDataY = cathode;
1062       return fIterator;
1063     }
1064     
1065   case kLocalTriggerIterator:
1066     {
1067       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
1068       if (store == 0x0) return 0x0;
1069       fIterator = store->CreateLocalIterator();
1070       if (fIterator == 0x0) return 0x0;
1071       fCurrentIteratorType = kLocalTriggerIterator;
1072       return fIterator;
1073     }
1074     
1075   case kRegionalTriggerIterator:
1076     {
1077       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
1078       if (store == 0x0) return 0x0;
1079       fIterator = store->CreateRegionalIterator();
1080       if (fIterator == 0x0) return 0x0;
1081       fCurrentIteratorType = kRegionalTriggerIterator;
1082       return fIterator;
1083     }
1084     
1085   default:
1086     return 0x0;
1087   }
1088 }
1089
1090 //_____________________________________________________________________________
1091 void AliMUONMCDataInterface::ResetIterator()
1092 {
1093 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
1094 /// The iterator type and temporary data indicating the state of the iterator are
1095 /// also reset.
1096
1097   if (fIterator != 0x0) delete fIterator;
1098   fCurrentIteratorType = kNoIterator;
1099   fCurrentIndex = fDataX = fDataY = -1;
1100   fIterator = 0x0;
1101 }
1102
1103 //_____________________________________________________________________________
1104 Int_t AliMUONMCDataInterface::CountObjects(TIterator* iter)
1105 {
1106 /// Counts the number of objects in the iterator and resets it.
1107 /// @return The number of objects in 'iter'.
1108
1109   if (iter == 0x0) return -1;
1110   Int_t count = 0;
1111   iter->Reset();
1112   while ( iter->Next() != 0x0 ) count++;
1113   iter->Reset();
1114   fCurrentIndex = -1;
1115   return count;
1116 }
1117
1118 //_____________________________________________________________________________
1119 TObject* AliMUONMCDataInterface::FetchObject(TIterator* iter, Int_t index)
1120 {
1121 /// Fetches the index'th object from the iterator counting the first object
1122 /// returned by iterator after it is reset as index == 0. The next object
1123 /// has index == 1 and so on where the last object returned by the iterator
1124 /// has index == N-1 where N = CountObjects(iter)
1125 /// This method will only reset the iterator if index is smaller than
1126 /// fCurrentIndex, which is used to track the iteration progress and is
1127 /// updated when a new object if returned by this method.
1128 /// @param iter  The iterator to fetch an object from.
1129 /// @param index The index number of the object to fetch in the range [0 .. N-1]
1130 ///        where N = CountObjects(iter)
1131
1132   if (index < 0)
1133   {
1134     AliError(Form("Index is out of bounds. Got a value of %d.", index));
1135     return 0x0;
1136   }
1137
1138   if (iter == 0x0) return 0x0;
1139   if (index <= fCurrentIndex)
1140   {
1141     iter->Reset();
1142     fCurrentIndex = -1;
1143   }
1144   
1145   TObject* object = 0x0;
1146   while (fCurrentIndex < index)
1147   {
1148     object = iter->Next();
1149     if (object == 0x0)
1150     {
1151       AliError(Form("Index is out of bounds. Got a value of %d.", index));
1152       iter->Reset();
1153       fCurrentIndex = -1;
1154       return 0x0;
1155     }
1156     fCurrentIndex++;
1157   }
1158   return object;
1159 }