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 "AliMpEncodePair.h"
32 #include "AliMpDEManager.h"
33 #include "AliMpConstants.h"
36 #include "AliLoader.h"
37 #include "AliRunLoader.h"
38 #include "AliHeader.h"
39 #include "AliCDBManager.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)
84 fCurrentIteratorType(kNoIterator),
91 /// @param filename should be the full path to a valid galice.root file
95 if ( AliCDBManager::Instance() != NULL &&
96 AliCDBManager::Instance()->GetDefaultStorage() == NULL ) {
97 AliFatal("CDB default storage not defined.");
103 if ( ! AliMpCDB::LoadDDLStore() ) {
104 AliFatal("Could not access mapping from OCDB !");
108 //______________________________________________________________________________
109 AliMUONDataInterface::~AliMUONDataInterface()
113 if ( fLoader != 0x0 )
115 delete fLoader->GetRunLoader();
120 //______________________________________________________________________________
122 AliMUONDataInterface::DigitStore(Int_t event)
124 /// Return digitStore for a given event.
125 /// Return 0x0 if event not found.
126 /// Returned pointer should not be deleted
128 /// \note If a previous store has been retrieved by one of the methods of
129 /// this class, but for a different event number, then those stores will
130 /// be deleted and no longer valid.
131 /// If you require access to the data for the earlier retrieved store,
132 /// but for different events, then you should deep copy / clone the object.
134 if (not IsValid()) return 0x0;
136 if (event == fCurrentEvent)
138 if (fDigitStore != 0x0)
144 if ( not LoadEvent(event) ) return 0x0;
147 fLoader->LoadDigits();
149 TTree* treeD = fLoader->TreeD();
152 AliError("Could not get treeD");
156 fDigitStore = AliMUONVDigitStore::Create(*treeD);
157 if ( fDigitStore != 0x0 )
159 fDigitStore->Clear();
160 fDigitStore->Connect(*treeD);
164 fLoader->UnloadDigits();
169 //______________________________________________________________________________
170 AliMUONVClusterStore*
171 AliMUONDataInterface::ClusterStore(Int_t event)
173 /// Return clusterStore for a given event.
174 /// Return 0x0 if event not found.
175 /// Returned pointer should not be deleted
177 /// \note If a previous store has been retrieved by one of the methods of
178 /// this class, but for a different event number, then those stores will
179 /// be deleted and no longer valid.
180 /// If you require access to the data for the earlier retrieved store,
181 /// but for different events, then you should deep copy / clone the object.
183 if (not IsValid()) return 0x0;
185 if (event == fCurrentEvent)
187 if (fClusterStore != 0x0)
188 return fClusterStore;
193 if ( not LoadEvent(event) ) return 0x0;
196 fLoader->LoadRecPoints();
198 TTree* treeR = fLoader->TreeR();
201 AliError("Could not get treeR");
205 fClusterStore = AliMUONVClusterStore::Create(*treeR);
206 if ( fClusterStore != 0x0 )
208 fClusterStore->Clear();
209 fClusterStore->Connect(*treeR);
213 fLoader->UnloadRecPoints();
215 return fClusterStore;
218 //_____________________________________________________________________________
219 AliMUONVTriggerStore*
220 AliMUONDataInterface::TriggerStore(Int_t event, const char* treeLetter)
222 /// Return the triggerStore for a given event.
223 /// Return 0x0 if event not found.
224 /// Returned pointer should not be deleted
225 /// treeLetter can be R or D to tell from which tree to read the information
227 /// \note If a previous store has been retrieved by one of the methods of
228 /// this class, but for a different event number, then those stores will
229 /// be deleted and no longer valid.
230 /// If you require access to the data for the earlier retrieved store,
231 /// but for different events, then you should deep copy / clone the object.
233 if (not IsValid()) return 0x0;
235 if (event == fCurrentEvent)
237 if (fTreeLetter == treeLetter)
239 if (fTriggerStore != 0x0)
240 return fTriggerStore;
244 // Reset only the fTriggerStore since the others might still be valid
245 // for the same event.
246 if (fTriggerStore != 0x0)
248 delete fTriggerStore;
255 // Event has changed so reset all the stores.
257 if ( not LoadEvent(event) ) return 0x0;
262 TString stree(treeLetter);
267 fLoader->LoadDigits();
268 tree = fLoader->TreeD();
270 else if ( stree == "R" )
272 fLoader->LoadRecPoints();
273 tree = fLoader->TreeR();
278 AliError(Form("Could not get tree%s",treeLetter));
282 fTriggerStore = AliMUONVTriggerStore::Create(*tree);
283 if ( fTriggerStore != 0x0 )
285 fTriggerStore->Clear();
286 fTriggerStore->Connect(*tree);
292 fLoader->UnloadDigits();
294 else if ( stree == "R" )
296 fLoader->UnloadRecPoints();
300 return fTriggerStore;
303 //______________________________________________________________________________
305 AliMUONDataInterface::DumpDigits(Int_t event, Bool_t sorted)
307 /// Dump the digits for a given event, sorted if so required
309 if ( fDigitStore != 0x0 )
313 DumpSorted(*fDigitStore);
317 fDigitStore->Print();
322 //______________________________________________________________________________
324 AliMUONDataInterface::DumpRecPoints(Int_t event, Bool_t sorted)
326 /// Dump the recpoints for a given event, sorted if so required
328 if ( fClusterStore != 0x0 )
332 DumpSorted(*fClusterStore);
336 fClusterStore->Print();
341 //_____________________________________________________________________________
343 AliMUONDataInterface::DumpSorted(const AliMUONVStore& store) const
345 /// Dump the given store, in sorted order
347 TIter next(store.CreateIterator());
350 list.SetOwner(kFALSE);
352 while ( ( object = next() ) )
362 //_____________________________________________________________________________
364 AliMUONDataInterface::DumpTrigger(Int_t event, const char* treeLetter)
366 /// Dump trigger for a given event from a given tree (if event>=0)
367 /// or loop over all events and build a trigger ntuple if event<0
368 /// treeLetter can be R or D to tell from which tree to read the information
372 NtupleTrigger(treeLetter);
376 TriggerStore(event,treeLetter);
378 if ( fTriggerStore != 0x0 )
380 fTriggerStore->Print();
385 //_____________________________________________________________________________
387 AliMUONDataInterface::NtupleTrigger(const char* treeLetter)
389 //// Loop over events to build trigger ntuples
392 TString sTreeLetter(treeLetter);
393 sTreeLetter.ToUpper();
395 if ( sTreeLetter != "R" && sTreeLetter != "D" )
397 AliError(Form("Cannot handle tree%s. Use D or R",treeLetter));
402 TNtuple tupleGlo("TgtupleGlo","Global Trigger Ntuple",
403 "ev:slpt:shpt:uplpt:uphpt:lplpt:lplpt");
404 TNtuple tupleLoc("TgtupleLoc","Local Trigger Ntuple",
405 "ev:LoCircuit:LoStripX:LoDev:StripY:LoLpt:LoHpt:y11:y21:x11");
407 // initialize counters
415 AliMUONGeometryTransformer transformer;
416 transformer.LoadGeometryData(Form("%s/geometry.root",
417 gSystem->DirName(fLoader->GetRunLoader()->GetFileName())));
418 AliMUONTriggerCircuit triggerCircuit(&transformer);
420 // select output file name from selected Tree
421 Char_t fileNameOut[30];
422 if (sTreeLetter == "D")
424 AliInfo(Form("reading from Digits\n"));
425 sprintf(fileNameOut,"TriggerCheckFromDigits.root");
427 else if (sTreeLetter == "R")
429 AliInfo(Form("reading from RecPoints\n"));
430 sprintf(fileNameOut,"TriggerCheckFromRP.root");
434 Int_t nevents = NumberOfEvents();
436 for (Int_t ievent=0; ievent<nevents; ++ievent)
438 if (ievent%100==0) AliInfo(Form("Processing event %d\n",ievent));
440 AliMUONVTriggerStore* triggerStore = TriggerStore(ievent,treeLetter);
444 AliError(Form("Could not read %s from tree%s","Trigger",treeLetter));
448 // get global trigger info
449 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
450 sLowpt+=gloTrg->SingleLpt();
451 sHighpt+=gloTrg->SingleHpt();
452 uSLowpt+=gloTrg->PairUnlikeLpt();
453 uSHighpt+=gloTrg->PairUnlikeHpt();
454 lSLowpt+=gloTrg->PairLikeLpt();
455 lSHighpt+=gloTrg->PairLikeHpt();
457 // loop on local triggers
458 TIter next(triggerStore->CreateIterator());
459 AliMUONLocalTrigger* locTrg(0x0);
460 while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
462 Bool_t xTrig=locTrg->IsTrigX();
463 Bool_t yTrig=locTrg->IsTrigY();
466 { // fill ntuple if trigger in X and Y
467 tupleLoc.Fill(ievent,locTrg->LoCircuit(),
473 triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
474 triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
475 triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
477 tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
478 gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
479 gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
480 } // end of loop on local triggers
481 } // end of loop on events
483 // print info and store ntuples
485 printf("=============================================\n");
486 printf("================ SUMMARY ==================\n");
488 printf("Total number of events processed %d \n",nevents);
490 printf(" Global Trigger output Low pt High pt\n");
491 printf(" number of Single :\t");
492 printf("%i\t%i\t",sLowpt,sHighpt);
494 printf(" number of UnlikeSign pair :\t");
495 printf("%i\t%i\t",uSLowpt,uSHighpt);
497 printf(" number of LikeSign pair :\t");
498 printf("%i\t%i\t",lSLowpt,lSHighpt);
500 printf("=============================================\n");
503 TFile myFile(fileNameOut, "RECREATE");
509 //_____________________________________________________________________________
511 AliMUONDataInterface::LoadEvent(Int_t event)
513 /// Load event if different from the current one.
514 /// Returns kFALSE on error and kTRUE if the event was loaded.
518 AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
519 if (fLoader->GetRunLoader()->GetEvent(event) == 0)
521 fCurrentEvent = event;
528 //______________________________________________________________________________
530 AliMUONDataInterface::NumberOfEvents() const
532 /// Number of events in the current galice.root file we're attached to
533 if (not IsValid()) return -1;
534 return fLoader->GetRunLoader()->GetNumberOfEvents();
537 //_____________________________________________________________________________
539 AliMUONDataInterface::Open(const char* filename)
541 /// Connect to a given galice.root file
547 if ( fLoader != 0x0 )
549 delete fLoader->GetRunLoader();
556 TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
558 while (AliRunLoader::GetRunLoader(foldername) != 0x0)
560 delete AliRunLoader::GetRunLoader(foldername);
563 AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
564 if (runLoader == 0x0)
566 AliError(Form("Cannot open file %s",filename));
571 runLoader->LoadHeader();
572 if ( ! runLoader->GetHeader() ) {
573 AliError("Cannot load header.");
577 Int_t runNumber = runLoader->GetHeader()->GetRun();
578 AliCDBManager::Instance()->SetRun(runNumber);
580 runLoader->UnloadHeader();
582 fLoader = runLoader->GetDetectorLoader("MUON");
585 AliError("Cannot get AliMUONLoader");
591 AliError(Form("Could not access %s filename. Object is unuseable",filename));
595 //_____________________________________________________________________________
596 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
598 /// Loads all reconstructed data for the given event.
600 if (DigitStore(event) == 0x0) return kFALSE;
601 if (ClusterStore(event) == 0x0) return kFALSE;
602 if (TriggerStore(event) == 0x0) return kFALSE;
606 //_____________________________________________________________________________
607 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
609 /// Returns the number of digits to be found on a given detector element.
610 /// @param detElemId The detector element ID number to search on.
612 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
613 return CountObjects(iter);
616 //_____________________________________________________________________________
617 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
619 /// Returns the a pointer to the index'th digit on the specified detector element.
620 /// @param detElemId The detector element ID number to search on.
621 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
622 /// where N = NumberOfDigits(detElemId)
624 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
625 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
628 //_____________________________________________________________________________
629 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
631 /// Returns the number of digits to be found on a specific chamber and cathode.
632 /// @param chamber The chamber number in the range [0 .. 13].
633 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
634 /// 1 is the non-bending plane.
636 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
637 return CountObjects(iter);
640 //_____________________________________________________________________________
641 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
643 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
644 /// @param chamber The chamber number in the range [0 .. 13].
645 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
646 /// 1 is the non-bending plane.
647 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
648 /// where N = NumberOfDigits(chamber, cathode)
650 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
651 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
654 //_____________________________________________________________________________
655 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
657 /// Returns the number of reconstructed raw clusters on the specified chamber.
658 /// @param chamber The chamber number in the range [0 .. 13].
660 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
661 return CountObjects(iter);
664 //_____________________________________________________________________________
665 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
667 /// Returns a pointer to the index'th raw cluster on the specified chamber.
668 /// @param chamber The chamber number in the range [0 .. 13].
669 /// @param index The index number of the raw cluster to fetch in the range [0 .. N-1],
670 /// where N = NumberOfRawClusters(chamber)
672 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
673 return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
676 //_____________________________________________________________________________
677 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
679 /// Returns the number of reconstructed local trigger objects.
681 TIterator* iter = GetIterator(kLocalTriggerIterator);
682 return CountObjects(iter);
685 //_____________________________________________________________________________
686 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
688 /// Returns a pointer to the index'th local trigger object.
689 /// @param index The index number of the local trigger object to fetch in the range [0 .. N-1],
690 /// where N = NumberOfLocalTriggers()
692 TIterator* iter = GetIterator(kLocalTriggerIterator);
693 return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
696 //_____________________________________________________________________________
697 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
699 /// Returns the number of regional trigger objects reconstructed.
701 TIterator* iter = GetIterator(kRegionalTriggerIterator);
702 return CountObjects(iter);
705 //_____________________________________________________________________________
706 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
708 /// Returns a pointer to the index'th regional trigger object.
709 /// @param index The index number of the regional trigger object to fetch in the range [0 .. N-1],
710 /// where N = NumberOfRegionalTriggers()
712 TIterator* iter = GetIterator(kRegionalTriggerIterator);
713 return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
716 //_____________________________________________________________________________
717 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
719 /// Returns a pointer to the reconstructed global trigger object for the event.
721 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
722 if (store == 0x0) return 0x0;
723 return store->Global();
726 //_____________________________________________________________________________
727 void AliMUONDataInterface::ResetStores()
729 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
730 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
733 if (fDigitStore != 0x0)
738 if (fTriggerStore != 0x0)
740 delete fTriggerStore;
743 if (fClusterStore != 0x0)
745 delete fClusterStore;
750 //_____________________________________________________________________________
751 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
753 /// Creates an appropriate iterator object and returns it.
754 /// If the iterator has already been created then that one is returned otherwise
755 /// a new object is created.
756 /// Depending on the value of 'type' the semantics of parameters x and y can change.
757 /// @param type The type of iterator to create.
758 /// @param x This is the detector element ID if type == kDigitIteratorByDetectorElement
759 /// If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
760 /// then this is the chamber number. In all other cases this parameter is
762 /// @param y If type == kDigitIteratorByChamberAndCathode then this parameter is the
763 /// cathode number. In all other cases this parameter is
766 if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
769 if (fCurrentEvent == -1)
771 AliError("No event was selected. Try first using GetEvent().");
779 case kDigitIteratorByDetectorElement:
782 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
783 if (store == 0x0) return 0x0;
784 fIterator = store->CreateIterator(detElem, detElem, 2);
785 if (fIterator == 0x0) return 0x0;
786 fCurrentIteratorType = kDigitIteratorByDetectorElement;
791 case kDigitIteratorByChamberAndCathode:
795 if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
798 "Must have give a chamber value in the range [0..%d], but got a value of: %d",
799 AliMpConstants::NofChambers() - 1,
804 if (cathode < 0 or 1 < cathode)
806 AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
810 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
811 if (store == 0x0) return 0x0;
812 MpPair_t pair = AliMpDEManager::GetDetElemIdRange(chamber);
813 fIterator = store->CreateIterator(AliMp::PairFirst(pair), AliMp::PairSecond(pair), cathode);
814 if (fIterator == 0x0) return 0x0;
815 fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
821 case kRawClusterIterator:
824 AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
825 if (store == 0x0) return 0x0;
826 fIterator = store->CreateChamberIterator(chamber, chamber);
827 if (fIterator == 0x0) return 0x0;
828 fCurrentIteratorType = kRawClusterIterator;
833 case kLocalTriggerIterator:
835 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
836 if (store == 0x0) return 0x0;
837 fIterator = store->CreateLocalIterator();
838 if (fIterator == 0x0) return 0x0;
839 fCurrentIteratorType = kLocalTriggerIterator;
843 case kRegionalTriggerIterator:
845 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
846 if (store == 0x0) return 0x0;
847 fIterator = store->CreateRegionalIterator();
848 if (fIterator == 0x0) return 0x0;
849 fCurrentIteratorType = kRegionalTriggerIterator;
858 //_____________________________________________________________________________
859 void AliMUONDataInterface::ResetIterator()
861 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
862 /// The iterator type and temporary data indicating the state of the iterator are
865 if (fIterator != 0x0) delete fIterator;
866 fCurrentIteratorType = kNoIterator;
867 fCurrentIndex = fDataX = fDataY = -1;
871 //_____________________________________________________________________________
872 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
874 /// Counts the number of objects in the iterator and resets it.
875 /// @return The number of objects in 'iter'.
877 if (iter == 0x0) return -1;
880 while ( iter->Next() != 0x0 ) count++;
886 //_____________________________________________________________________________
887 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
889 /// Fetches the index'th object from the iterator counting the first object
890 /// returned by iterator after it is reset as index == 0. The next object
891 /// has index == 1 and so on where the last object returned by the iterator
892 /// has index == N-1 where N = CountObjects(iter)
893 /// This method will only reset the iterator if index is smaller than
894 /// fCurrentIndex, which is used to track the iteration progress and is
895 /// updated when a new object if returned by this method.
896 /// @param iter The iterator to fetch an object from.
897 /// @param index The index number of the object to fetch in the range [0 .. N-1]
898 /// where N = CountObjects(iter)
902 AliError(Form("Index is out of bounds. Got a value of %d.", index));
906 if (iter == 0x0) return 0x0;
907 if (index <= fCurrentIndex)
913 TObject* object = 0x0;
914 while (fCurrentIndex < index)
916 object = iter->Next();
919 AliError(Form("Index is out of bounds. Got a value of %d.", index));