1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
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"
31 #include "AliMpIntPair.h"
32 #include "AliMpDEManager.h"
33 #include "AliMpConstants.h"
36 #include "AliLoader.h"
38 #include "AliRunLoader.h"
41 #include <TParticle.h>
42 #include <Riostream.h>
47 #include <TIterator.h>
51 //-----------------------------------------------------------------------------
52 /// \class AliMUONDataInterface
54 /// An easy to use interface to the MUON data data stored in
55 /// TreeS, TreeD and TreeR.
57 /// For MC related information (i.e. TreeH, TreeK, TreeTR), see
58 /// AliMUONMCDataInterface.
61 /// This interface in not necessarily the fastest way to fetch the data but
62 /// it is the easiest.
64 /// \author Laurent Aphecetche, Subatech & Artur Szostak <artursz@iafrica.com> (University of Cape Town)
65 //-----------------------------------------------------------------------------
68 ClassImp(AliMUONDataInterface)
72 Int_t AliMUONDataInterface::fgInstanceCounter(0);
74 //______________________________________________________________________________
75 AliMUONDataInterface::AliMUONDataInterface(const char* filename)
83 fCurrentIteratorType(kNoIterator),
90 /// @param filename should be the full path to a valid galice.root file
97 if ( ! AliMpCDB::LoadDDLStore() ) {
98 AliFatal("Could not access mapping from OCDB !");
102 //______________________________________________________________________________
103 AliMUONDataInterface::~AliMUONDataInterface()
107 if ( fLoader != 0x0 )
109 delete fLoader->GetRunLoader();
114 //______________________________________________________________________________
116 AliMUONDataInterface::DigitStore(Int_t event)
118 /// Return digitStore for a given event.
119 /// Return 0x0 if event not found.
120 /// Returned pointer should not be deleted
122 if (not IsValid()) return 0x0;
123 if (event == fCurrentEvent and fDigitStore != 0x0) return fDigitStore;
126 if (not LoadEvent(event)) return 0x0;
128 fLoader->LoadDigits();
130 TTree* treeD = fLoader->TreeD();
133 AliError("Could not get treeD");
137 fDigitStore = AliMUONVDigitStore::Create(*treeD);
138 if ( fDigitStore != 0x0 )
140 fDigitStore->Clear();
141 fDigitStore->Connect(*treeD);
145 fLoader->UnloadDigits();
150 //______________________________________________________________________________
151 AliMUONVClusterStore*
152 AliMUONDataInterface::ClusterStore(Int_t event)
154 /// Return clusterStore for a given event.
155 /// Return 0x0 if event not found.
156 /// Returned pointer should not be deleted
158 if (not IsValid()) return 0x0;
159 if (event == fCurrentEvent and fClusterStore != 0x0) return fClusterStore;
162 if (not LoadEvent(event)) return 0x0;
164 fLoader->LoadRecPoints();
166 TTree* treeR = fLoader->TreeR();
169 AliError("Could not get treeR");
173 fClusterStore = AliMUONVClusterStore::Create(*treeR);
174 if ( fClusterStore != 0x0 )
176 fClusterStore->Clear();
177 fClusterStore->Connect(*treeR);
181 fLoader->UnloadRecPoints();
183 return fClusterStore;
186 //_____________________________________________________________________________
187 AliMUONVTriggerStore*
188 AliMUONDataInterface::TriggerStore(Int_t event, const char* treeLetter)
190 /// Return the triggerStore for a given event.
191 /// Return 0x0 if event not found.
192 /// Returned pointer should not be deleted
193 /// treeLetter can be R or D to tell from which tree to read the information
195 if (not IsValid()) return 0x0;
196 if (event == fCurrentEvent and fTriggerStore != 0x0) return fTriggerStore;
199 if (not LoadEvent(event)) return 0x0;
203 TString stree(treeLetter);
208 fLoader->LoadDigits();
209 tree = fLoader->TreeD();
211 else if ( stree == "R" )
213 fLoader->LoadRecPoints();
214 tree = fLoader->TreeR();
219 AliError(Form("Could not get tree%s",treeLetter));
223 fTriggerStore = AliMUONVTriggerStore::Create(*tree);
224 if ( fTriggerStore != 0x0 )
226 fTriggerStore->Clear();
227 fTriggerStore->Connect(*tree);
233 fLoader->UnloadDigits();
235 else if ( stree == "R" )
237 fLoader->UnloadRecPoints();
240 return fTriggerStore;
243 //______________________________________________________________________________
245 AliMUONDataInterface::DumpDigits(Int_t event, Bool_t sorted)
247 /// Dump the digits for a given event, sorted if so required
249 if ( fDigitStore != 0x0 )
253 DumpSorted(*fDigitStore);
257 fDigitStore->Print();
262 //______________________________________________________________________________
264 AliMUONDataInterface::DumpRecPoints(Int_t event, Bool_t sorted)
266 /// Dump the recpoints for a given event, sorted if so required
268 if ( fClusterStore != 0x0 )
272 DumpSorted(*fClusterStore);
276 fClusterStore->Print();
281 //_____________________________________________________________________________
283 AliMUONDataInterface::DumpSorted(const AliMUONVStore& store) const
285 /// Dump the given store, in sorted order
287 TIter next(store.CreateIterator());
290 list.SetOwner(kFALSE);
292 while ( ( object = next() ) )
302 //_____________________________________________________________________________
304 AliMUONDataInterface::DumpTrigger(Int_t event, const char* treeLetter)
306 /// Dump trigger for a given event from a given tree (if event>=0)
307 /// or loop over all events and build a trigger ntuple if event<0
308 /// treeLetter can be R or D to tell from which tree to read the information
312 NtupleTrigger(treeLetter);
316 TriggerStore(event,treeLetter);
318 if ( fTriggerStore != 0x0 )
320 fTriggerStore->Print();
325 //_____________________________________________________________________________
327 AliMUONDataInterface::NtupleTrigger(const char* treeLetter)
329 //// Loop over events to build trigger ntuples
332 TString sTreeLetter(treeLetter);
333 sTreeLetter.ToUpper();
335 if ( sTreeLetter != "R" && sTreeLetter != "D" )
337 AliError(Form("Cannot handle tree%s. Use D or R",treeLetter));
342 TNtuple tupleGlo("TgtupleGlo","Global Trigger Ntuple",
343 "ev:slpt:shpt:uplpt:uphpt:lplpt:lplpt");
344 TNtuple tupleLoc("TgtupleLoc","Local Trigger Ntuple",
345 "ev:LoCircuit:LoStripX:LoDev:StripY:LoLpt:LoHpt:y11:y21:x11");
347 // initialize counters
355 AliMUONGeometryTransformer transformer;
356 transformer.LoadGeometryData(Form("%s/geometry.root",
357 gSystem->DirName(fLoader->GetRunLoader()->GetFileName())));
358 AliMUONTriggerCircuit triggerCircuit(&transformer);
360 // select output file name from selected Tree
361 Char_t fileNameOut[30];
362 if (sTreeLetter == "D")
364 AliInfo(Form("reading from Digits\n"));
365 sprintf(fileNameOut,"TriggerCheckFromDigits.root");
367 else if (sTreeLetter == "R")
369 AliInfo(Form("reading from RecPoints\n"));
370 sprintf(fileNameOut,"TriggerCheckFromRP.root");
374 Int_t nevents = NumberOfEvents();
376 for (Int_t ievent=0; ievent<nevents; ++ievent)
378 if (ievent%100==0) AliInfo(Form("Processing event %d\n",ievent));
380 AliMUONVTriggerStore* triggerStore = TriggerStore(ievent,treeLetter);
384 AliError(Form("Could not read %s from tree%s","Trigger",treeLetter));
388 // get global trigger info
389 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
390 sLowpt+=gloTrg->SingleLpt();
391 sHighpt+=gloTrg->SingleHpt();
392 uSLowpt+=gloTrg->PairUnlikeLpt();
393 uSHighpt+=gloTrg->PairUnlikeHpt();
394 lSLowpt+=gloTrg->PairLikeLpt();
395 lSHighpt+=gloTrg->PairLikeHpt();
397 // loop on local triggers
398 TIter next(triggerStore->CreateIterator());
399 AliMUONLocalTrigger* locTrg(0x0);
400 while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
405 if ( locTrg->LoSdev()==1 && locTrg->LoDev()==0 &&
406 locTrg->LoStripX()==0) xTrig=kFALSE; // no trigger in X
407 else xTrig=kTRUE; // trigger in X
408 if (locTrg->LoTrigY()==1 &&
409 locTrg->LoStripY()==15 ) yTrig = kFALSE; // no trigger in Y
410 else yTrig = kTRUE; // trigger in Y
413 { // fill ntuple if trigger in X and Y
414 tupleLoc.Fill(ievent,locTrg->LoCircuit(),
420 triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
421 triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
422 triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
424 tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
425 gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
426 gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
427 } // end of loop on local triggers
428 } // end of loop on events
430 // print info and store ntuples
432 printf("=============================================\n");
433 printf("================ SUMMARY ==================\n");
435 printf("Total number of events processed %d \n",nevents);
437 printf(" Global Trigger output Low pt High pt\n");
438 printf(" number of Single :\t");
439 printf("%i\t%i\t",sLowpt,sHighpt);
441 printf(" number of UnlikeSign pair :\t");
442 printf("%i\t%i\t",uSLowpt,uSHighpt);
444 printf(" number of LikeSign pair :\t");
445 printf("%i\t%i\t",lSLowpt,lSHighpt);
447 printf("=============================================\n");
450 TFile myFile(fileNameOut, "RECREATE");
456 //_____________________________________________________________________________
458 AliMUONDataInterface::LoadEvent(Int_t event)
460 /// Load event if different from the current one.
461 /// Returns kFALSE on error and kTRUE if the event was loaded.
465 AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
466 if (fLoader->GetRunLoader()->GetEvent(event) == 0)
468 fCurrentEvent = event;
475 //______________________________________________________________________________
477 AliMUONDataInterface::NumberOfEvents() const
479 /// Number of events in the current galice.root file we're attached to
480 if (not IsValid()) return -1;
481 return fLoader->GetRunLoader()->GetNumberOfEvents();
484 //_____________________________________________________________________________
486 AliMUONDataInterface::Open(const char* filename)
488 /// Connect to a given galice.root file
494 if ( fLoader != 0x0 )
496 delete fLoader->GetRunLoader();
503 TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
505 while (AliRunLoader::GetRunLoader(foldername) != 0x0)
507 delete AliRunLoader::GetRunLoader(foldername);
510 AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
511 if (runLoader == 0x0)
513 AliError(Form("Cannot open file %s",filename));
516 fLoader = runLoader->GetDetectorLoader("MUON");
519 AliError("Cannot get AliMUONLoader");
525 AliError(Form("Could not access %s filename. Object is unuseable",filename));
529 //_____________________________________________________________________________
530 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
532 /// Loads all reconstructed data for the given event.
534 if (DigitStore(event) == 0x0) return kFALSE;
535 if (ClusterStore(event) == 0x0) return kFALSE;
536 if (TriggerStore(event) == 0x0) return kFALSE;
540 //_____________________________________________________________________________
541 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
543 /// Returns the number of digits to be found on a given detector element.
544 /// @param detElemId The detector element ID number to search on.
546 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
547 return CountObjects(iter);
550 //_____________________________________________________________________________
551 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
553 /// Returns the a pointer to the index'th digit on the specified detector element.
554 /// @param detElemId The detector element ID number to search on.
555 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
556 /// where N = NumberOfDigits(detElemId)
558 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
559 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
562 //_____________________________________________________________________________
563 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
565 /// Returns the number of digits to be found on a specific chamber and cathode.
566 /// @param chamber The chamber number in the range [0 .. 13].
567 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
568 /// 1 is the non-bending plane.
570 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
571 return CountObjects(iter);
574 //_____________________________________________________________________________
575 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
577 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
578 /// @param chamber The chamber number in the range [0 .. 13].
579 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
580 /// 1 is the non-bending plane.
581 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
582 /// where N = NumberOfDigits(chamber, cathode)
584 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
585 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
588 //_____________________________________________________________________________
589 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
591 /// Returns the number of reconstructed raw clusters on the specified chamber.
592 /// @param chamber The chamber number in the range [0 .. 13].
594 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
595 return CountObjects(iter);
598 //_____________________________________________________________________________
599 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
601 /// Returns a pointer to the index'th raw cluster on the specified chamber.
602 /// @param chamber The chamber number in the range [0 .. 13].
603 /// @param index The index number of the raw cluster to fetch in the range [0 .. N-1],
604 /// where N = NumberOfRawClusters(chamber)
606 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
607 return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
610 //_____________________________________________________________________________
611 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
613 /// Returns the number of reconstructed local trigger objects.
615 TIterator* iter = GetIterator(kLocalTriggerIterator);
616 return CountObjects(iter);
619 //_____________________________________________________________________________
620 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
622 /// Returns a pointer to the index'th local trigger object.
623 /// @param index The index number of the local trigger object to fetch in the range [0 .. N-1],
624 /// where N = NumberOfLocalTriggers()
626 TIterator* iter = GetIterator(kLocalTriggerIterator);
627 return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
630 //_____________________________________________________________________________
631 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
633 /// Returns the number of regional trigger objects reconstructed.
635 TIterator* iter = GetIterator(kRegionalTriggerIterator);
636 return CountObjects(iter);
639 //_____________________________________________________________________________
640 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
642 /// Returns a pointer to the index'th regional trigger object.
643 /// @param index The index number of the regional trigger object to fetch in the range [0 .. N-1],
644 /// where N = NumberOfRegionalTriggers()
646 TIterator* iter = GetIterator(kRegionalTriggerIterator);
647 return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
650 //_____________________________________________________________________________
651 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
653 /// Returns a pointer to the reconstructed global trigger object for the event.
655 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
656 if (store == 0x0) return 0x0;
657 return store->Global();
660 //_____________________________________________________________________________
661 void AliMUONDataInterface::ResetStores()
663 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
664 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
667 if (fDigitStore != 0x0)
672 if (fTriggerStore != 0x0)
674 delete fTriggerStore;
677 if (fClusterStore != 0x0)
679 delete fClusterStore;
684 //_____________________________________________________________________________
685 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
687 /// Creates an appropriate iterator object and returns it.
688 /// If the iterator has already been created then that one is returned otherwise
689 /// a new object is created.
690 /// Depending on the value of 'type' the semantics of parameters x and y can change.
691 /// @param type The type of iterator to create.
692 /// @param x This is the detector element ID if type == kDigitIteratorByDetectorElement
693 /// If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
694 /// then this is the chamber number. In all other cases this parameter is
696 /// @param y If type == kDigitIteratorByChamberAndCathode then this parameter is the
697 /// cathode number. In all other cases this parameter is
700 if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
703 if (fCurrentEvent == -1)
705 AliError("No event was selected. Try first using GetEvent().");
713 case kDigitIteratorByDetectorElement:
716 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
717 if (store == 0x0) return 0x0;
718 fIterator = store->CreateIterator(detElem, detElem, 2);
719 if (fIterator == 0x0) return 0x0;
720 fCurrentIteratorType = kDigitIteratorByDetectorElement;
725 case kDigitIteratorByChamberAndCathode:
729 if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
732 "Must have give a chamber value in the range [0..%d], but got a value of: %d",
733 AliMpConstants::NofChambers() - 1,
738 if (cathode < 0 or 1 < cathode)
740 AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
744 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
745 if (store == 0x0) return 0x0;
746 AliMpIntPair pair = AliMpDEManager::GetDetElemIdRange(chamber);
747 fIterator = store->CreateIterator(pair.GetFirst(), pair.GetSecond(), cathode);
748 if (fIterator == 0x0) return 0x0;
749 fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
755 case kRawClusterIterator:
758 AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
759 if (store == 0x0) return 0x0;
760 fIterator = store->CreateChamberIterator(chamber, chamber);
761 if (fIterator == 0x0) return 0x0;
762 fCurrentIteratorType = kRawClusterIterator;
767 case kLocalTriggerIterator:
769 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
770 if (store == 0x0) return 0x0;
771 fIterator = store->CreateLocalIterator();
772 if (fIterator == 0x0) return 0x0;
773 fCurrentIteratorType = kLocalTriggerIterator;
777 case kRegionalTriggerIterator:
779 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
780 if (store == 0x0) return 0x0;
781 fIterator = store->CreateRegionalIterator();
782 if (fIterator == 0x0) return 0x0;
783 fCurrentIteratorType = kRegionalTriggerIterator;
792 //_____________________________________________________________________________
793 void AliMUONDataInterface::ResetIterator()
795 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
796 /// The iterator type and temporary data indicating the state of the iterator are
799 if (fIterator != 0x0) delete fIterator;
800 fCurrentIteratorType = kNoIterator;
801 fCurrentIndex = fDataX = fDataY = -1;
805 //_____________________________________________________________________________
806 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
808 /// Counts the number of objects in the iterator and resets it.
809 /// @return The number of objects in 'iter'.
811 if (iter == 0x0) return -1;
814 while ( iter->Next() != 0x0 ) count++;
820 //_____________________________________________________________________________
821 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
823 /// Fetches the index'th object from the iterator counting the first object
824 /// returned by iterator after it is reset as index == 0. The next object
825 /// has index == 1 and so on where the last object returned by the iterator
826 /// has index == N-1 where N = CountObjects(iter)
827 /// This method will only reset the iterator if index is smaller than
828 /// fCurrentIndex, which is used to track the iteration progress and is
829 /// updated when a new object if returned by this method.
830 /// @param iter The iterator to fetch an object from.
831 /// @param index The index number of the object to fetch in the range [0 .. N-1]
832 /// where N = CountObjects(iter)
836 AliError(Form("Index is out of bounds. Got a value of %d.", index));
840 if (iter == 0x0) return 0x0;
841 if (index <= fCurrentIndex)
847 TObject* object = 0x0;
848 while (fCurrentIndex < index)
850 object = iter->Next();
853 AliError(Form("Index is out of bounds. Got a value of %d.", index));