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