]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONDataInterface.cxx
Fixing compiler warnings
[u/mrichter/AliRoot.git] / MUON / AliMUONDataInterface.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 #include "AliMUONDataInterface.h"
19 #include "AliMUONGeometryTransformer.h"
20 #include "AliMUONVDigit.h"
21 #include "AliMUONVCluster.h"
22 #include "AliMUONLocalTrigger.h"
23 #include "AliMUONRegionalTrigger.h"
24 #include "AliMUONGlobalTrigger.h"
25 #include "AliMUONTriggerCircuit.h"
26 #include "AliMUONVClusterStore.h"
27 #include "AliMUONVDigitStore.h"
28 #include "AliMUONVTriggerStore.h"
29 #include "AliMpCDB.h"
30
31 #include "AliMpEncodePair.h"
32 #include "AliMpDEManager.h"
33 #include "AliMpConstants.h"
34 #include "AliMpCDB.h"
35
36 #include "AliLoader.h"
37 #include "AliRunLoader.h"
38 #include "AliHeader.h"
39 #include "AliCDBManager.h"
40
41 #include <Riostream.h>
42 #include <TFile.h>
43 #include <TList.h>
44 #include <TNtuple.h>
45 #include <TSystem.h>
46 #include <TIterator.h>
47 #include <cstdlib>
48 #include <cassert>
49
50 //-----------------------------------------------------------------------------
51 /// \class AliMUONDataInterface
52 ///
53 /// An easy to use interface to the MUON data data stored in
54 /// TreeS, TreeD and TreeR.
55 ///
56 /// For MC related information (i.e. TreeH, TreeK, TreeTR), see
57 /// AliMUONMCDataInterface.
58 ///
59 ///
60 /// This interface in not necessarily the fastest way to fetch the data but
61 /// it is the easiest.
62 ///
63 /// \author Laurent Aphecetche, Subatech & Artur Szostak <artursz@iafrica.com> (University of Cape Town)
64 //-----------------------------------------------------------------------------
65
66 /// \cond CLASSIMP
67 ClassImp(AliMUONDataInterface)
68 /// \endcond
69
70
71 Int_t AliMUONDataInterface::fgInstanceCounter(0);
72
73 //______________________________________________________________________________
74 AliMUONDataInterface::AliMUONDataInterface(const char* filename)
75 : TObject(), 
76 fLoader(0x0),
77 fDigitStore(0x0),
78 fTriggerStore(0x0),
79 fClusterStore(0x0),
80 fCurrentEvent(-1),
81 fTreeLetter(""),
82 fIsValid(kFALSE),
83 fCurrentIteratorType(kNoIterator),
84 fCurrentIndex(-1),
85 fDataX(-1),
86 fDataY(-1),
87 fIterator(0x0)
88 {
89   /// ctor
90   /// @param filename should be the full path to a valid galice.root file
91   
92   ++fgInstanceCounter;
93   
94   if ( AliCDBManager::Instance() != NULL &&
95        AliCDBManager::Instance()->GetDefaultStorage() == NULL ) {
96       AliFatal("CDB default storage not defined.");
97   }
98   
99   Open(filename);
100
101   // Load mapping
102   if ( ! AliMpCDB::LoadDDLStore() ) {
103     AliFatal("Could not access mapping from OCDB !");
104   }
105 }
106
107 //______________________________________________________________________________
108 AliMUONDataInterface::~AliMUONDataInterface()
109 {
110   /// dtor
111   ResetStores();
112   if ( fLoader != 0x0 ) 
113   {
114     delete fLoader->GetRunLoader();
115   }
116   --fgInstanceCounter;  
117 }
118
119 //______________________________________________________________________________
120 AliMUONVDigitStore*
121 AliMUONDataInterface::DigitStore(Int_t event)
122 {
123   /// Return digitStore for a given event.
124   /// Return 0x0 if event not found.
125   /// Returned pointer should not be deleted
126   ///
127   /// \note If a previous store has been retrieved by one of the methods of
128   /// this class, but for a different event number, then those stores will
129   /// be deleted and no longer valid.
130   /// If you require access to the data for the earlier retrieved store,
131   /// but for different events, then you should deep copy / clone the object.
132   
133   if (not IsValid()) return 0x0;
134   
135   if (event == fCurrentEvent)
136   {
137     if (fDigitStore != 0x0)
138       return fDigitStore;
139   }
140   else
141   {
142     ResetStores();
143     if ( not LoadEvent(event) ) return 0x0;
144   }
145   
146   fLoader->LoadDigits();
147   
148   TTree* treeD = fLoader->TreeD();
149   if (treeD == 0x0)
150   {
151     AliError("Could not get treeD");
152     return 0x0;
153   }
154   
155   fDigitStore = AliMUONVDigitStore::Create(*treeD);
156   if ( fDigitStore != 0x0 ) 
157   {
158     fDigitStore->Clear();
159     fDigitStore->Connect(*treeD);
160     treeD->GetEvent(0);
161   }
162   
163   fLoader->UnloadDigits();
164   
165   return fDigitStore;
166 }
167
168 //______________________________________________________________________________
169 AliMUONVClusterStore*
170 AliMUONDataInterface::ClusterStore(Int_t event)
171 {
172   /// Return clusterStore for a given event.
173   /// Return 0x0 if event not found.
174   /// Returned pointer should not be deleted
175   ///
176   /// \note If a previous store has been retrieved by one of the methods of
177   /// this class, but for a different event number, then those stores will
178   /// be deleted and no longer valid.
179   /// If you require access to the data for the earlier retrieved store,
180   /// but for different events, then you should deep copy / clone the object.
181   
182   if (not IsValid()) return 0x0;
183   
184   if (event == fCurrentEvent)
185   {
186     if (fClusterStore != 0x0)
187       return fClusterStore;
188   }
189   else
190   {
191     ResetStores();
192     if ( not LoadEvent(event) ) return 0x0;
193   }
194   
195   fLoader->LoadRecPoints();
196   
197   TTree* treeR = fLoader->TreeR();
198   if (treeR == 0x0)
199   {
200     AliError("Could not get treeR");
201     return 0x0;
202   }
203   
204   fClusterStore = AliMUONVClusterStore::Create(*treeR);
205   if ( fClusterStore != 0x0 ) 
206   {
207     fClusterStore->Clear();
208     fClusterStore->Connect(*treeR);
209     treeR->GetEvent(0);
210   }
211   
212   fLoader->UnloadRecPoints();
213   
214   return fClusterStore;
215 }
216
217 //_____________________________________________________________________________
218 AliMUONVTriggerStore*
219 AliMUONDataInterface::TriggerStore(Int_t event, const char* treeLetter)
220 {
221   /// Return the triggerStore for a given event.
222   /// Return 0x0 if event not found.
223   /// Returned pointer should not be deleted
224   /// treeLetter can be R or D to tell from which tree to read the information
225   ///
226   /// \note If a previous store has been retrieved by one of the methods of
227   /// this class, but for a different event number, then those stores will
228   /// be deleted and no longer valid.
229   /// If you require access to the data for the earlier retrieved store,
230   /// but for different events, then you should deep copy / clone the object.
231   
232   if (not IsValid()) return 0x0;
233   
234   if (event == fCurrentEvent)
235   {
236     if (fTreeLetter == treeLetter)
237     {
238       if (fTriggerStore != 0x0)
239         return fTriggerStore;
240     }
241     else
242     {
243       // Reset only the fTriggerStore since the others might still be valid
244       // for the same event.
245       if (fTriggerStore != 0x0)
246       {
247         delete fTriggerStore;
248         fTriggerStore = 0x0;
249       }
250     }
251   }
252   else
253   {
254     // Event has changed so reset all the stores.
255     ResetStores();
256     if ( not LoadEvent(event) ) return 0x0;
257   }
258   
259   TTree* tree(0x0);
260   
261   TString stree(treeLetter);
262   stree.ToUpper();
263   
264   if ( stree == "D" )
265   {
266     fLoader->LoadDigits();    
267     tree = fLoader->TreeD();
268   }
269   else if ( stree == "R" )
270   {
271     fLoader->LoadRecPoints();
272     tree = fLoader->TreeR();
273   }
274   
275   if ( tree == 0x0 ) 
276   {
277     AliError(Form("Could not get tree%s",treeLetter));
278     return 0x0;
279   }
280   
281   fTriggerStore = AliMUONVTriggerStore::Create(*tree);
282   if ( fTriggerStore != 0x0 ) 
283   {
284     fTriggerStore->Clear();
285     fTriggerStore->Connect(*tree);
286     tree->GetEvent(0);
287   }
288   
289   if ( stree == "D" )
290   {
291     fLoader->UnloadDigits();    
292   }
293   else if ( stree == "R" )
294   {
295     fLoader->UnloadRecPoints();
296   }
297   fTreeLetter = stree;
298   
299   return fTriggerStore;
300 }
301
302 //______________________________________________________________________________
303 void
304 AliMUONDataInterface::DumpDigits(Int_t event, Bool_t sorted)
305 {
306   /// Dump the digits for a given event, sorted if so required
307   DigitStore(event);
308   if ( fDigitStore != 0x0 ) 
309   {
310     if ( sorted ) 
311     {
312       DumpSorted(*fDigitStore);
313     }
314     else
315     {
316       fDigitStore->Print();
317     }
318   }
319 }
320
321 //______________________________________________________________________________
322 void
323 AliMUONDataInterface::DumpRecPoints(Int_t event, Bool_t sorted)
324 {
325   /// Dump the recpoints for a given event, sorted if so required
326   ClusterStore(event);
327   if ( fClusterStore != 0x0 ) 
328   {
329     if ( sorted ) 
330     {
331       DumpSorted(*fClusterStore);
332     }
333     else
334     {
335       fClusterStore->Print();
336     }
337   }
338 }
339
340 //_____________________________________________________________________________
341 void
342 AliMUONDataInterface::DumpSorted(const AliMUONVStore& store) const
343 {
344   /// Dump the given store, in sorted order
345   
346   TIter next(store.CreateIterator());
347   TObject* object;
348   TList list;
349   list.SetOwner(kFALSE);
350   
351   while ( ( object = next() ) )
352   {
353     list.Add(object);
354   }
355   
356   list.Sort();
357   
358   list.Print();
359 }
360
361 //_____________________________________________________________________________
362 void
363 AliMUONDataInterface::DumpTrigger(Int_t event, const char* treeLetter)
364 {
365   /// Dump trigger for a given event from a given tree (if event>=0)
366   /// or loop over all events and build a trigger ntuple if event<0
367   /// treeLetter can be R or D to tell from which tree to read the information
368   
369   if ( event < 0 ) 
370   {
371     NtupleTrigger(treeLetter);
372   }
373   else
374   {
375     TriggerStore(event,treeLetter);
376   
377     if ( fTriggerStore != 0x0 ) 
378     {
379       fTriggerStore->Print();
380     }
381   }
382 }
383
384 //_____________________________________________________________________________
385 void
386 AliMUONDataInterface::NtupleTrigger(const char* treeLetter)
387 {
388   //// Loop over events to build trigger ntuples
389   ///
390   
391   TString sTreeLetter(treeLetter);
392   sTreeLetter.ToUpper();
393   
394   if ( sTreeLetter != "R" && sTreeLetter != "D" ) 
395   {
396     AliError(Form("Cannot handle tree%s. Use D or R",treeLetter));
397     return;
398   }
399   
400   // book ntuples
401   TNtuple tupleGlo("TgtupleGlo","Global Trigger Ntuple",
402                    "ev:slpt:shpt:uplpt:uphpt:lplpt:lplpt");
403   TNtuple tupleLoc("TgtupleLoc","Local Trigger Ntuple",
404                    "ev:LoCircuit:LoStripX:LoDev:StripY:LoLpt:LoHpt:y11:y21:x11");
405   
406   // initialize counters
407   Int_t sLowpt=0;
408   Int_t sHighpt=0;
409   Int_t uSLowpt=0;
410   Int_t uSHighpt=0;
411   Int_t lSLowpt=0;
412   Int_t lSHighpt=0;
413   
414   AliMUONGeometryTransformer transformer;
415   transformer.LoadGeometryData(Form("%s/geometry.root",
416                                     gSystem->DirName(fLoader->GetRunLoader()->GetFileName())));
417     AliMUONTriggerCircuit triggerCircuit(&transformer);
418
419   // select output file name from selected Tree
420   Char_t fileNameOut[30];
421   if (sTreeLetter == "D") 
422   {
423     AliInfo(Form("reading from Digits\n"));
424     sprintf(fileNameOut,"TriggerCheckFromDigits.root");
425   } 
426   else if (sTreeLetter == "R") 
427   {
428     AliInfo(Form("reading from RecPoints\n"));
429     sprintf(fileNameOut,"TriggerCheckFromRP.root");
430   }
431   
432   // loop on events
433   Int_t nevents = NumberOfEvents();
434
435   for (Int_t ievent=0; ievent<nevents; ++ievent) 
436   {
437     if (ievent%100==0) AliInfo(Form("Processing event %d\n",ievent));
438     
439     AliMUONVTriggerStore* triggerStore = TriggerStore(ievent,treeLetter);
440     
441     if (!triggerStore)
442     {
443       AliError(Form("Could not read %s from tree%s","Trigger",treeLetter));
444       return;
445     }
446     
447     // get global trigger info
448     AliMUONGlobalTrigger* gloTrg = triggerStore->Global();      
449     sLowpt+=gloTrg->SingleLpt();
450     sHighpt+=gloTrg->SingleHpt();
451     uSLowpt+=gloTrg->PairUnlikeLpt(); 
452     uSHighpt+=gloTrg->PairUnlikeHpt();
453     lSLowpt+=gloTrg->PairLikeLpt(); 
454     lSHighpt+=gloTrg->PairLikeHpt();
455     
456     // loop on local triggers   
457     TIter next(triggerStore->CreateIterator());
458     AliMUONLocalTrigger* locTrg(0x0);
459     while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
460     {
461       Bool_t xTrig=locTrg->IsTrigX();
462       Bool_t yTrig=locTrg->IsTrigY();
463       
464       if (xTrig && yTrig) 
465       { // fill ntuple if trigger in X and Y                    
466         tupleLoc.Fill(ievent,locTrg->LoCircuit(),
467                        locTrg->LoStripX(),
468                        locTrg->LoDev(),
469                        locTrg->LoStripY(),
470                        locTrg->LoLpt(),
471                        locTrg->LoHpt(),
472                        triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
473                        triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
474                        triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
475       }
476       tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
477                      gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
478                      gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
479     } // end of loop on local triggers
480   } // end of loop on events
481   
482   // print info and store ntuples
483   printf("\n");
484   printf("=============================================\n");
485   printf("================  SUMMARY  ==================\n");
486   printf("\n");
487   printf("Total number of events processed %d \n",nevents);
488   printf("\n");
489   printf(" Global Trigger output       Low pt  High pt\n");
490   printf(" number of Single           :\t");
491   printf("%i\t%i\t",sLowpt,sHighpt);
492   printf("\n");
493   printf(" number of UnlikeSign pair  :\t"); 
494   printf("%i\t%i\t",uSLowpt,uSHighpt);
495   printf("\n");
496   printf(" number of LikeSign pair    :\t");  
497   printf("%i\t%i\t",lSLowpt,lSHighpt);
498   printf("\n");
499   printf("=============================================\n");
500   fflush(stdout);    
501   
502   TFile myFile(fileNameOut, "RECREATE");
503   tupleGlo.Write();
504   tupleLoc.Write();
505   myFile.Close();
506 }
507
508 //_____________________________________________________________________________
509 Bool_t
510 AliMUONDataInterface::LoadEvent(Int_t event)
511 {
512   /// Load event if different from the current one.
513   /// Returns kFALSE on error and kTRUE if the event was loaded.
514   
515   assert( IsValid() );
516   
517   AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
518   if (fLoader->GetRunLoader()->GetEvent(event) == 0)
519   {
520     fCurrentEvent = event;
521     return kTRUE;
522   }
523   else
524     return kFALSE;
525 }
526
527 //______________________________________________________________________________
528 Int_t
529 AliMUONDataInterface::NumberOfEvents() const
530 {
531   /// Number of events in the current galice.root file we're attached to 
532   if (not IsValid()) return -1;
533   return fLoader->GetRunLoader()->GetNumberOfEvents();
534 }
535
536 //_____________________________________________________________________________
537 void
538 AliMUONDataInterface::Open(const char* filename)
539 {
540   /// Connect to a given galice.root file
541   
542   ResetStores();
543   
544   fCurrentEvent=-1;
545   
546   if ( fLoader != 0x0 ) 
547   {
548     delete fLoader->GetRunLoader();
549   }
550   
551   fLoader = 0x0;
552   
553   fIsValid = kTRUE;
554   
555   TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
556   
557   while (AliRunLoader::GetRunLoader(foldername) != 0x0) 
558   {
559     delete AliRunLoader::GetRunLoader(foldername);
560   }
561   
562   AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
563   if (runLoader == 0x0) 
564   {
565     AliError(Form("Cannot open file %s",filename));    
566     fIsValid = kFALSE;
567   }
568
569   runLoader->LoadHeader();
570   if ( ! runLoader->GetHeader() ) {
571     AliError("Cannot load header.");    
572     fIsValid = kFALSE;
573   }
574   else {
575     Int_t runNumber = runLoader->GetHeader()->GetRun();
576     AliCDBManager::Instance()->SetRun(runNumber);
577   }  
578   runLoader->UnloadHeader(); 
579
580   fLoader = runLoader->GetDetectorLoader("MUON");
581   if (fLoader == 0x0) 
582   {
583     AliError("Cannot get AliMUONLoader");
584     fIsValid = kFALSE;
585   }
586   
587   if (not IsValid())
588   {
589     AliError(Form("Could not access %s filename. Object is unuseable",filename));
590   }
591 }
592
593 //_____________________________________________________________________________
594 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
595 {
596 /// Loads all reconstructed data for the given event.
597
598   if (DigitStore(event) == 0x0) return kFALSE;
599   if (ClusterStore(event) == 0x0) return kFALSE;
600   if (TriggerStore(event) == 0x0) return kFALSE;
601   return kTRUE;
602 }
603
604 //_____________________________________________________________________________
605 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
606 {
607 /// Returns the number of digits to be found on a given detector element.
608 /// @param detElemId  The detector element ID number to search on.
609
610   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
611   return CountObjects(iter);
612 }
613
614 //_____________________________________________________________________________
615 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
616 {
617 /// Returns the a pointer to the index'th digit on the specified detector element.
618 /// @param detElemId  The detector element ID number to search on.
619 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
620 ///   where N = NumberOfDigits(detElemId)
621
622   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
623   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
624 }
625
626 //_____________________________________________________________________________
627 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
628 {
629 /// Returns the number of digits to be found on a specific chamber and cathode.
630 /// @param chamber  The chamber number in the range [0 .. 13].
631 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
632 ///   1 is the non-bending plane.
633
634   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
635   return CountObjects(iter);
636 }
637
638 //_____________________________________________________________________________
639 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
640 {
641 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
642 /// @param chamber  The chamber number in the range [0 .. 13].
643 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
644 ///   1 is the non-bending plane.
645 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
646 ///   where N = NumberOfDigits(chamber, cathode)
647
648   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
649   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
650 }
651
652 //_____________________________________________________________________________
653 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
654 {
655 /// Returns the number of reconstructed raw clusters on the specified chamber.
656 /// @param chamber  The chamber number in the range [0 .. 13].
657
658   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
659   return CountObjects(iter);
660 }
661
662 //_____________________________________________________________________________
663 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
664 {
665 /// Returns a pointer to the index'th raw cluster on the specified chamber.
666 /// @param chamber  The chamber number in the range [0 .. 13].
667 /// @param index  The index number of the raw cluster to fetch in the range [0 .. N-1],
668 ///   where N = NumberOfRawClusters(chamber)
669
670   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
671   return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
672 }
673
674 //_____________________________________________________________________________
675 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
676 {
677 /// Returns the number of reconstructed local trigger objects.
678
679   TIterator* iter = GetIterator(kLocalTriggerIterator);
680   return CountObjects(iter);
681 }
682
683 //_____________________________________________________________________________
684 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
685 {
686 /// Returns a pointer to the index'th local trigger object.
687 /// @param index  The index number of the local trigger object to fetch in the range [0 .. N-1],
688 ///   where N = NumberOfLocalTriggers()
689
690   TIterator* iter = GetIterator(kLocalTriggerIterator);
691   return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
692 }
693
694 //_____________________________________________________________________________
695 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
696 {
697 /// Returns the number of regional trigger objects reconstructed.
698
699   TIterator* iter = GetIterator(kRegionalTriggerIterator);
700   return CountObjects(iter);
701 }
702
703 //_____________________________________________________________________________
704 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
705 {
706 /// Returns a pointer to the index'th regional trigger object.
707 /// @param index  The index number of the regional trigger object to fetch in the range [0 .. N-1],
708 ///   where N = NumberOfRegionalTriggers()
709
710   TIterator* iter = GetIterator(kRegionalTriggerIterator);
711   return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
712 }
713
714 //_____________________________________________________________________________
715 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
716 {
717 /// Returns a pointer to the reconstructed global trigger object for the event.
718
719   AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
720   if (store == 0x0) return 0x0;
721   return store->Global();
722 }
723
724 //_____________________________________________________________________________
725 void AliMUONDataInterface::ResetStores()
726 {
727 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
728 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
729
730   ResetIterator();
731   if (fDigitStore != 0x0)
732   {
733     delete fDigitStore;
734     fDigitStore = 0x0;
735   }
736   if (fTriggerStore != 0x0)
737   {
738     delete fTriggerStore;
739     fTriggerStore = 0x0;
740   }
741   if (fClusterStore != 0x0)
742   {
743     delete fClusterStore;
744     fClusterStore = 0x0;
745   }
746 }
747
748 //_____________________________________________________________________________
749 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
750 {
751 /// Creates an appropriate iterator object and returns it.
752 /// If the iterator has already been created then that one is returned otherwise
753 /// a new object is created.
754 /// Depending on the value of 'type' the semantics of parameters x and y can change.
755 /// @param type  The type of iterator to create.
756 /// @param x  This is the detector element ID if type == kDigitIteratorByDetectorElement
757 ///           If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
758 ///           then this is the chamber number. In all other cases this parameter is
759 ///           ignored.
760 /// @param y  If type == kDigitIteratorByChamberAndCathode then this parameter is the
761 ///           cathode number. In all other cases this parameter is
762 ///           ignored.
763
764   if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
765         return fIterator;
766   
767   if (fCurrentEvent == -1)
768   {
769     AliError("No event was selected. Try first using GetEvent().");
770     return 0x0;
771   }
772   
773   ResetIterator();
774   
775   switch (type)
776   {
777   case kDigitIteratorByDetectorElement:
778     {
779       Int_t detElem = x;
780       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
781       if (store == 0x0) return 0x0;
782       fIterator = store->CreateIterator(detElem, detElem, 2);
783       if (fIterator == 0x0) return 0x0;
784       fCurrentIteratorType = kDigitIteratorByDetectorElement;
785       fDataX = detElem;
786       return fIterator;
787     }
788     
789   case kDigitIteratorByChamberAndCathode:
790     {
791       Int_t chamber = x;
792       Int_t cathode = y;
793       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
794       {
795         AliError(Form(
796           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
797           AliMpConstants::NofChambers() - 1,
798           chamber
799         ));
800         return 0x0;
801       }
802       if (cathode < 0 or 1 < cathode)
803       {
804         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
805         return 0x0;
806       }
807       
808       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
809       if (store == 0x0) return 0x0;
810       MpPair_t pair = AliMpDEManager::GetDetElemIdRange(chamber);
811       fIterator = store->CreateIterator(AliMp::PairFirst(pair), AliMp::PairSecond(pair), cathode);
812       if (fIterator == 0x0) return 0x0;
813       fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
814       fDataX = chamber;
815       fDataY = cathode;
816       return fIterator;
817     }
818     
819   case kRawClusterIterator:
820     {
821       Int_t chamber = x;
822       AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
823       if (store == 0x0) return 0x0;
824       fIterator = store->CreateChamberIterator(chamber, chamber);
825       if (fIterator == 0x0) return 0x0;
826       fCurrentIteratorType = kRawClusterIterator;
827       fDataX = chamber;
828       return fIterator;
829     }
830     
831   case kLocalTriggerIterator:
832     {
833       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
834       if (store == 0x0) return 0x0;
835       fIterator = store->CreateLocalIterator();
836       if (fIterator == 0x0) return 0x0;
837       fCurrentIteratorType = kLocalTriggerIterator;
838       return fIterator;
839     }
840     
841   case kRegionalTriggerIterator:
842     {
843       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
844       if (store == 0x0) return 0x0;
845       fIterator = store->CreateRegionalIterator();
846       if (fIterator == 0x0) return 0x0;
847       fCurrentIteratorType = kRegionalTriggerIterator;
848       return fIterator;
849     }
850     
851   default:
852     return 0x0;
853   }
854 }
855
856 //_____________________________________________________________________________
857 void AliMUONDataInterface::ResetIterator()
858 {
859 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
860 /// The iterator type and temporary data indicating the state of the iterator are
861 /// also reset.
862
863   if (fIterator != 0x0) delete fIterator;
864   fCurrentIteratorType = kNoIterator;
865   fCurrentIndex = fDataX = fDataY = -1;
866   fIterator = 0x0;
867 }
868
869 //_____________________________________________________________________________
870 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
871 {
872 /// Counts the number of objects in the iterator and resets it.
873 /// @return The number of objects in 'iter'.
874
875   if (iter == 0x0) return -1;
876   Int_t count = 0;
877   iter->Reset();
878   while ( iter->Next() != 0x0 ) count++;
879   iter->Reset();
880   fCurrentIndex = -1;
881   return count;
882 }
883
884 //_____________________________________________________________________________
885 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
886 {
887 /// Fetches the index'th object from the iterator counting the first object
888 /// returned by iterator after it is reset as index == 0. The next object
889 /// has index == 1 and so on where the last object returned by the iterator
890 /// has index == N-1 where N = CountObjects(iter)
891 /// This method will only reset the iterator if index is smaller than
892 /// fCurrentIndex, which is used to track the iteration progress and is
893 /// updated when a new object if returned by this method.
894 /// @param iter  The iterator to fetch an object from.
895 /// @param index The index number of the object to fetch in the range [0 .. N-1]
896 ///        where N = CountObjects(iter)
897
898   if (index < 0)
899   {
900     AliError(Form("Index is out of bounds. Got a value of %d.", index));
901     return 0x0;
902   }
903
904   if (iter == 0x0) return 0x0;
905   if (index <= fCurrentIndex)
906   {
907     iter->Reset();
908     fCurrentIndex = -1;
909   }
910   
911   TObject* object = 0x0;
912   while (fCurrentIndex < index)
913   {
914     object = iter->Next();
915     if (object == 0x0)
916     {
917       AliError(Form("Index is out of bounds. Got a value of %d.", index));
918       iter->Reset();
919       fCurrentIndex = -1;
920       return 0x0;
921     }
922     fCurrentIndex++;
923   }
924   return object;
925 }