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