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