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