]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONDataInterface.cxx
Fixing FORWARD_NULL defects reported by Coverity
[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     return;
568   }
569
570   runLoader->LoadHeader();
571   if ( ! runLoader->GetHeader() ) {
572     AliError("Cannot load header.");    
573     fIsValid = kFALSE;
574   }
575   else {
576     Int_t runNumber = runLoader->GetHeader()->GetRun();
577     AliCDBManager::Instance()->SetRun(runNumber);
578   }  
579   runLoader->UnloadHeader(); 
580
581   fLoader = runLoader->GetDetectorLoader("MUON");
582   if (fLoader == 0x0) 
583   {
584     AliError("Cannot get AliMUONLoader");
585     fIsValid = kFALSE;
586   }
587   
588   if (not IsValid())
589   {
590     AliError(Form("Could not access %s filename. Object is unuseable",filename));
591   }
592 }
593
594 //_____________________________________________________________________________
595 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
596 {
597 /// Loads all reconstructed data for the given event.
598
599   if (DigitStore(event) == 0x0) return kFALSE;
600   if (ClusterStore(event) == 0x0) return kFALSE;
601   if (TriggerStore(event) == 0x0) return kFALSE;
602   return kTRUE;
603 }
604
605 //_____________________________________________________________________________
606 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
607 {
608 /// Returns the number of digits to be found on a given detector element.
609 /// @param detElemId  The detector element ID number to search on.
610
611   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
612   return CountObjects(iter);
613 }
614
615 //_____________________________________________________________________________
616 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
617 {
618 /// Returns the a pointer to the index'th digit on the specified detector element.
619 /// @param detElemId  The detector element ID number to search on.
620 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
621 ///   where N = NumberOfDigits(detElemId)
622
623   TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
624   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
625 }
626
627 //_____________________________________________________________________________
628 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
629 {
630 /// Returns the number of digits to be found on a specific chamber and cathode.
631 /// @param chamber  The chamber number in the range [0 .. 13].
632 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
633 ///   1 is the non-bending plane.
634
635   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
636   return CountObjects(iter);
637 }
638
639 //_____________________________________________________________________________
640 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
641 {
642 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
643 /// @param chamber  The chamber number in the range [0 .. 13].
644 /// @param cathode  The cathode in the range [0 .. 1], where 0 is the bending and
645 ///   1 is the non-bending plane.
646 /// @param index  The index number of the digit to fetch in the range [0 .. N-1],
647 ///   where N = NumberOfDigits(chamber, cathode)
648
649   TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
650   return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
651 }
652
653 //_____________________________________________________________________________
654 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
655 {
656 /// Returns the number of reconstructed raw clusters on the specified chamber.
657 /// @param chamber  The chamber number in the range [0 .. 13].
658
659   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
660   return CountObjects(iter);
661 }
662
663 //_____________________________________________________________________________
664 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
665 {
666 /// Returns a pointer to the index'th raw cluster on the specified chamber.
667 /// @param chamber  The chamber number in the range [0 .. 13].
668 /// @param index  The index number of the raw cluster to fetch in the range [0 .. N-1],
669 ///   where N = NumberOfRawClusters(chamber)
670
671   TIterator* iter = GetIterator(kRawClusterIterator, chamber);
672   return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
673 }
674
675 //_____________________________________________________________________________
676 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
677 {
678 /// Returns the number of reconstructed local trigger objects.
679
680   TIterator* iter = GetIterator(kLocalTriggerIterator);
681   return CountObjects(iter);
682 }
683
684 //_____________________________________________________________________________
685 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
686 {
687 /// Returns a pointer to the index'th local trigger object.
688 /// @param index  The index number of the local trigger object to fetch in the range [0 .. N-1],
689 ///   where N = NumberOfLocalTriggers()
690
691   TIterator* iter = GetIterator(kLocalTriggerIterator);
692   return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
693 }
694
695 //_____________________________________________________________________________
696 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
697 {
698 /// Returns the number of regional trigger objects reconstructed.
699
700   TIterator* iter = GetIterator(kRegionalTriggerIterator);
701   return CountObjects(iter);
702 }
703
704 //_____________________________________________________________________________
705 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
706 {
707 /// Returns a pointer to the index'th regional trigger object.
708 /// @param index  The index number of the regional trigger object to fetch in the range [0 .. N-1],
709 ///   where N = NumberOfRegionalTriggers()
710
711   TIterator* iter = GetIterator(kRegionalTriggerIterator);
712   return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
713 }
714
715 //_____________________________________________________________________________
716 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
717 {
718 /// Returns a pointer to the reconstructed global trigger object for the event.
719
720   AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
721   if (store == 0x0) return 0x0;
722   return store->Global();
723 }
724
725 //_____________________________________________________________________________
726 void AliMUONDataInterface::ResetStores()
727 {
728 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
729 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
730
731   ResetIterator();
732   if (fDigitStore != 0x0)
733   {
734     delete fDigitStore;
735     fDigitStore = 0x0;
736   }
737   if (fTriggerStore != 0x0)
738   {
739     delete fTriggerStore;
740     fTriggerStore = 0x0;
741   }
742   if (fClusterStore != 0x0)
743   {
744     delete fClusterStore;
745     fClusterStore = 0x0;
746   }
747 }
748
749 //_____________________________________________________________________________
750 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
751 {
752 /// Creates an appropriate iterator object and returns it.
753 /// If the iterator has already been created then that one is returned otherwise
754 /// a new object is created.
755 /// Depending on the value of 'type' the semantics of parameters x and y can change.
756 /// @param type  The type of iterator to create.
757 /// @param x  This is the detector element ID if type == kDigitIteratorByDetectorElement
758 ///           If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
759 ///           then this is the chamber number. In all other cases this parameter is
760 ///           ignored.
761 /// @param y  If type == kDigitIteratorByChamberAndCathode then this parameter is the
762 ///           cathode number. In all other cases this parameter is
763 ///           ignored.
764
765   if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
766         return fIterator;
767   
768   if (fCurrentEvent == -1)
769   {
770     AliError("No event was selected. Try first using GetEvent().");
771     return 0x0;
772   }
773   
774   ResetIterator();
775   
776   switch (type)
777   {
778   case kDigitIteratorByDetectorElement:
779     {
780       Int_t detElem = x;
781       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
782       if (store == 0x0) return 0x0;
783       fIterator = store->CreateIterator(detElem, detElem, 2);
784       if (fIterator == 0x0) return 0x0;
785       fCurrentIteratorType = kDigitIteratorByDetectorElement;
786       fDataX = detElem;
787       return fIterator;
788     }
789     
790   case kDigitIteratorByChamberAndCathode:
791     {
792       Int_t chamber = x;
793       Int_t cathode = y;
794       if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
795       {
796         AliError(Form(
797           "Must have give a chamber value in the range [0..%d], but got a value of: %d",
798           AliMpConstants::NofChambers() - 1,
799           chamber
800         ));
801         return 0x0;
802       }
803       if (cathode < 0 or 1 < cathode)
804       {
805         AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
806         return 0x0;
807       }
808       
809       AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
810       if (store == 0x0) return 0x0;
811       MpPair_t pair = AliMpDEManager::GetDetElemIdRange(chamber);
812       fIterator = store->CreateIterator(AliMp::PairFirst(pair), AliMp::PairSecond(pair), cathode);
813       if (fIterator == 0x0) return 0x0;
814       fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
815       fDataX = chamber;
816       fDataY = cathode;
817       return fIterator;
818     }
819     
820   case kRawClusterIterator:
821     {
822       Int_t chamber = x;
823       AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
824       if (store == 0x0) return 0x0;
825       fIterator = store->CreateChamberIterator(chamber, chamber);
826       if (fIterator == 0x0) return 0x0;
827       fCurrentIteratorType = kRawClusterIterator;
828       fDataX = chamber;
829       return fIterator;
830     }
831     
832   case kLocalTriggerIterator:
833     {
834       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
835       if (store == 0x0) return 0x0;
836       fIterator = store->CreateLocalIterator();
837       if (fIterator == 0x0) return 0x0;
838       fCurrentIteratorType = kLocalTriggerIterator;
839       return fIterator;
840     }
841     
842   case kRegionalTriggerIterator:
843     {
844       AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
845       if (store == 0x0) return 0x0;
846       fIterator = store->CreateRegionalIterator();
847       if (fIterator == 0x0) return 0x0;
848       fCurrentIteratorType = kRegionalTriggerIterator;
849       return fIterator;
850     }
851     
852   default:
853     return 0x0;
854   }
855 }
856
857 //_____________________________________________________________________________
858 void AliMUONDataInterface::ResetIterator()
859 {
860 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
861 /// The iterator type and temporary data indicating the state of the iterator are
862 /// also reset.
863
864   if (fIterator != 0x0) delete fIterator;
865   fCurrentIteratorType = kNoIterator;
866   fCurrentIndex = fDataX = fDataY = -1;
867   fIterator = 0x0;
868 }
869
870 //_____________________________________________________________________________
871 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
872 {
873 /// Counts the number of objects in the iterator and resets it.
874 /// @return The number of objects in 'iter'.
875
876   if (iter == 0x0) return -1;
877   Int_t count = 0;
878   iter->Reset();
879   while ( iter->Next() != 0x0 ) count++;
880   iter->Reset();
881   fCurrentIndex = -1;
882   return count;
883 }
884
885 //_____________________________________________________________________________
886 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
887 {
888 /// Fetches the index'th object from the iterator counting the first object
889 /// returned by iterator after it is reset as index == 0. The next object
890 /// has index == 1 and so on where the last object returned by the iterator
891 /// has index == N-1 where N = CountObjects(iter)
892 /// This method will only reset the iterator if index is smaller than
893 /// fCurrentIndex, which is used to track the iteration progress and is
894 /// updated when a new object if returned by this method.
895 /// @param iter  The iterator to fetch an object from.
896 /// @param index The index number of the object to fetch in the range [0 .. N-1]
897 ///        where N = CountObjects(iter)
898
899   if (index < 0)
900   {
901     AliError(Form("Index is out of bounds. Got a value of %d.", index));
902     return 0x0;
903   }
904
905   if (iter == 0x0) return 0x0;
906   if (index <= fCurrentIndex)
907   {
908     iter->Reset();
909     fCurrentIndex = -1;
910   }
911   
912   TObject* object = 0x0;
913   while (fCurrentIndex < index)
914   {
915     object = iter->Next();
916     if (object == 0x0)
917     {
918       AliError(Form("Index is out of bounds. Got a value of %d.", index));
919       iter->Reset();
920       fCurrentIndex = -1;
921       return 0x0;
922     }
923     fCurrentIndex++;
924   }
925   return object;
926 }