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