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