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"
41 #include <Riostream.h>
46 #include <TIterator.h>
50 //-----------------------------------------------------------------------------
51 /// \class AliMUONDataInterface
53 /// An easy to use interface to the MUON data data stored in
54 /// TreeS, TreeD and TreeR.
56 /// For MC related information (i.e. TreeH, TreeK, TreeTR), see
57 /// AliMUONMCDataInterface.
60 /// This interface in not necessarily the fastest way to fetch the data but
61 /// it is the easiest.
63 /// \author Laurent Aphecetche, Subatech & Artur Szostak <artursz@iafrica.com> (University of Cape Town)
64 //-----------------------------------------------------------------------------
67 ClassImp(AliMUONDataInterface)
71 Int_t AliMUONDataInterface::fgInstanceCounter(0);
73 //______________________________________________________________________________
74 AliMUONDataInterface::AliMUONDataInterface(const char* filename)
83 fCurrentIteratorType(kNoIterator),
90 /// @param filename should be the full path to a valid galice.root file
94 if ( AliCDBManager::Instance() != NULL &&
95 AliCDBManager::Instance()->GetDefaultStorage() == NULL ) {
96 AliFatal("CDB default storage not defined.");
102 if ( ! AliMpCDB::LoadDDLStore() ) {
103 AliFatal("Could not access mapping from OCDB !");
107 //______________________________________________________________________________
108 AliMUONDataInterface::~AliMUONDataInterface()
112 if ( fLoader != 0x0 )
114 delete fLoader->GetRunLoader();
119 //______________________________________________________________________________
121 AliMUONDataInterface::DigitStore(Int_t event)
123 /// Return digitStore for a given event.
124 /// Return 0x0 if event not found.
125 /// Returned pointer should not be deleted
127 /// \note If a previous store has been retrieved by one of the methods of
128 /// this class, but for a different event number, then those stores will
129 /// be deleted and no longer valid.
130 /// If you require access to the data for the earlier retrieved store,
131 /// but for different events, then you should deep copy / clone the object.
133 if (not IsValid()) return 0x0;
135 if (event == fCurrentEvent)
137 if (fDigitStore != 0x0)
143 if ( not LoadEvent(event) ) return 0x0;
146 fLoader->LoadDigits();
148 TTree* treeD = fLoader->TreeD();
151 AliError("Could not get treeD");
155 fDigitStore = AliMUONVDigitStore::Create(*treeD);
156 if ( fDigitStore != 0x0 )
158 fDigitStore->Clear();
159 fDigitStore->Connect(*treeD);
163 fLoader->UnloadDigits();
168 //______________________________________________________________________________
169 AliMUONVClusterStore*
170 AliMUONDataInterface::ClusterStore(Int_t event)
172 /// Return clusterStore for a given event.
173 /// Return 0x0 if event not found.
174 /// Returned pointer should not be deleted
176 /// \note If a previous store has been retrieved by one of the methods of
177 /// this class, but for a different event number, then those stores will
178 /// be deleted and no longer valid.
179 /// If you require access to the data for the earlier retrieved store,
180 /// but for different events, then you should deep copy / clone the object.
182 if (not IsValid()) return 0x0;
184 if (event == fCurrentEvent)
186 if (fClusterStore != 0x0)
187 return fClusterStore;
192 if ( not LoadEvent(event) ) return 0x0;
195 fLoader->LoadRecPoints();
197 TTree* treeR = fLoader->TreeR();
200 AliError("Could not get treeR");
204 fClusterStore = AliMUONVClusterStore::Create(*treeR);
205 if ( fClusterStore != 0x0 )
207 fClusterStore->Clear();
208 fClusterStore->Connect(*treeR);
212 fLoader->UnloadRecPoints();
214 return fClusterStore;
217 //_____________________________________________________________________________
218 AliMUONVTriggerStore*
219 AliMUONDataInterface::TriggerStore(Int_t event, const char* treeLetter)
221 /// Return the triggerStore for a given event.
222 /// Return 0x0 if event not found.
223 /// Returned pointer should not be deleted
224 /// treeLetter can be R or D to tell from which tree to read the information
226 /// \note If a previous store has been retrieved by one of the methods of
227 /// this class, but for a different event number, then those stores will
228 /// be deleted and no longer valid.
229 /// If you require access to the data for the earlier retrieved store,
230 /// but for different events, then you should deep copy / clone the object.
232 if (not IsValid()) return 0x0;
234 if (event == fCurrentEvent)
236 if (fTreeLetter == treeLetter)
238 if (fTriggerStore != 0x0)
239 return fTriggerStore;
243 // Reset only the fTriggerStore since the others might still be valid
244 // for the same event.
245 if (fTriggerStore != 0x0)
247 delete fTriggerStore;
254 // Event has changed so reset all the stores.
256 if ( not LoadEvent(event) ) return 0x0;
261 TString stree(treeLetter);
266 fLoader->LoadDigits();
267 tree = fLoader->TreeD();
269 else if ( stree == "R" )
271 fLoader->LoadRecPoints();
272 tree = fLoader->TreeR();
277 AliError(Form("Could not get tree%s",treeLetter));
281 fTriggerStore = AliMUONVTriggerStore::Create(*tree);
282 if ( fTriggerStore != 0x0 )
284 fTriggerStore->Clear();
285 fTriggerStore->Connect(*tree);
291 fLoader->UnloadDigits();
293 else if ( stree == "R" )
295 fLoader->UnloadRecPoints();
299 return fTriggerStore;
302 //______________________________________________________________________________
304 AliMUONDataInterface::DumpDigits(Int_t event, Bool_t sorted)
306 /// Dump the digits for a given event, sorted if so required
308 if ( fDigitStore != 0x0 )
312 DumpSorted(*fDigitStore);
316 fDigitStore->Print();
321 //______________________________________________________________________________
323 AliMUONDataInterface::DumpRecPoints(Int_t event, Bool_t sorted)
325 /// Dump the recpoints for a given event, sorted if so required
327 if ( fClusterStore != 0x0 )
331 DumpSorted(*fClusterStore);
335 fClusterStore->Print();
340 //_____________________________________________________________________________
342 AliMUONDataInterface::DumpSorted(const AliMUONVStore& store) const
344 /// Dump the given store, in sorted order
346 TIter next(store.CreateIterator());
349 list.SetOwner(kFALSE);
351 while ( ( object = next() ) )
361 //_____________________________________________________________________________
363 AliMUONDataInterface::DumpTrigger(Int_t event, const char* treeLetter)
365 /// Dump trigger for a given event from a given tree (if event>=0)
366 /// or loop over all events and build a trigger ntuple if event<0
367 /// treeLetter can be R or D to tell from which tree to read the information
371 NtupleTrigger(treeLetter);
375 TriggerStore(event,treeLetter);
377 if ( fTriggerStore != 0x0 )
379 fTriggerStore->Print();
384 //_____________________________________________________________________________
386 AliMUONDataInterface::NtupleTrigger(const char* treeLetter)
388 //// Loop over events to build trigger ntuples
391 TString sTreeLetter(treeLetter);
392 sTreeLetter.ToUpper();
394 if ( sTreeLetter != "R" && sTreeLetter != "D" )
396 AliError(Form("Cannot handle tree%s. Use D or R",treeLetter));
401 TNtuple tupleGlo("TgtupleGlo","Global Trigger Ntuple",
402 "ev:slpt:shpt:uplpt:uphpt:lplpt:lplpt");
403 TNtuple tupleLoc("TgtupleLoc","Local Trigger Ntuple",
404 "ev:LoCircuit:LoStripX:LoDev:StripY:LoLpt:LoHpt:y11:y21:x11");
406 // initialize counters
414 AliMUONGeometryTransformer transformer;
415 transformer.LoadGeometryData(Form("%s/geometry.root",
416 gSystem->DirName(fLoader->GetRunLoader()->GetFileName())));
417 AliMUONTriggerCircuit triggerCircuit(&transformer);
419 // select output file name from selected Tree
420 Char_t fileNameOut[30];
421 if (sTreeLetter == "D")
423 AliInfo(Form("reading from Digits\n"));
424 sprintf(fileNameOut,"TriggerCheckFromDigits.root");
426 else if (sTreeLetter == "R")
428 AliInfo(Form("reading from RecPoints\n"));
429 sprintf(fileNameOut,"TriggerCheckFromRP.root");
433 Int_t nevents = NumberOfEvents();
435 for (Int_t ievent=0; ievent<nevents; ++ievent)
437 if (ievent%100==0) AliInfo(Form("Processing event %d\n",ievent));
439 AliMUONVTriggerStore* triggerStore = TriggerStore(ievent,treeLetter);
443 AliError(Form("Could not read %s from tree%s","Trigger",treeLetter));
447 // get global trigger info
448 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
449 sLowpt+=gloTrg->SingleLpt();
450 sHighpt+=gloTrg->SingleHpt();
451 uSLowpt+=gloTrg->PairUnlikeLpt();
452 uSHighpt+=gloTrg->PairUnlikeHpt();
453 lSLowpt+=gloTrg->PairLikeLpt();
454 lSHighpt+=gloTrg->PairLikeHpt();
456 // loop on local triggers
457 TIter next(triggerStore->CreateIterator());
458 AliMUONLocalTrigger* locTrg(0x0);
459 while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
461 Bool_t xTrig=locTrg->IsTrigX();
462 Bool_t yTrig=locTrg->IsTrigY();
465 { // fill ntuple if trigger in X and Y
466 tupleLoc.Fill(ievent,locTrg->LoCircuit(),
472 triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
473 triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
474 triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
476 tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
477 gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
478 gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
479 } // end of loop on local triggers
480 } // end of loop on events
482 // print info and store ntuples
484 printf("=============================================\n");
485 printf("================ SUMMARY ==================\n");
487 printf("Total number of events processed %d \n",nevents);
489 printf(" Global Trigger output Low pt High pt\n");
490 printf(" number of Single :\t");
491 printf("%i\t%i\t",sLowpt,sHighpt);
493 printf(" number of UnlikeSign pair :\t");
494 printf("%i\t%i\t",uSLowpt,uSHighpt);
496 printf(" number of LikeSign pair :\t");
497 printf("%i\t%i\t",lSLowpt,lSHighpt);
499 printf("=============================================\n");
502 TFile myFile(fileNameOut, "RECREATE");
508 //_____________________________________________________________________________
510 AliMUONDataInterface::LoadEvent(Int_t event)
512 /// Load event if different from the current one.
513 /// Returns kFALSE on error and kTRUE if the event was loaded.
517 AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
518 if (fLoader->GetRunLoader()->GetEvent(event) == 0)
520 fCurrentEvent = event;
527 //______________________________________________________________________________
529 AliMUONDataInterface::NumberOfEvents() const
531 /// Number of events in the current galice.root file we're attached to
532 if (not IsValid()) return -1;
533 return fLoader->GetRunLoader()->GetNumberOfEvents();
536 //_____________________________________________________________________________
538 AliMUONDataInterface::Open(const char* filename)
540 /// Connect to a given galice.root file
546 if ( fLoader != 0x0 )
548 delete fLoader->GetRunLoader();
555 TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
557 while (AliRunLoader::GetRunLoader(foldername) != 0x0)
559 delete AliRunLoader::GetRunLoader(foldername);
562 AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
563 if (runLoader == 0x0)
565 AliError(Form("Cannot open file %s",filename));
570 runLoader->LoadHeader();
571 if ( ! runLoader->GetHeader() ) {
572 AliError("Cannot load header.");
576 Int_t runNumber = runLoader->GetHeader()->GetRun();
577 AliCDBManager::Instance()->SetRun(runNumber);
579 runLoader->UnloadHeader();
581 fLoader = runLoader->GetDetectorLoader("MUON");
584 AliError("Cannot get AliMUONLoader");
590 AliError(Form("Could not access %s filename. Object is unuseable",filename));
594 //_____________________________________________________________________________
595 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
597 /// Loads all reconstructed data for the given event.
599 if (DigitStore(event) == 0x0) return kFALSE;
600 if (ClusterStore(event) == 0x0) return kFALSE;
601 if (TriggerStore(event) == 0x0) return kFALSE;
605 //_____________________________________________________________________________
606 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
608 /// Returns the number of digits to be found on a given detector element.
609 /// @param detElemId The detector element ID number to search on.
611 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
612 return CountObjects(iter);
615 //_____________________________________________________________________________
616 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
618 /// Returns the a pointer to the index'th digit on the specified detector element.
619 /// @param detElemId The detector element ID number to search on.
620 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
621 /// where N = NumberOfDigits(detElemId)
623 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
624 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
627 //_____________________________________________________________________________
628 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
630 /// Returns the number of digits to be found on a specific chamber and cathode.
631 /// @param chamber The chamber number in the range [0 .. 13].
632 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
633 /// 1 is the non-bending plane.
635 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
636 return CountObjects(iter);
639 //_____________________________________________________________________________
640 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
642 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
643 /// @param chamber The chamber number in the range [0 .. 13].
644 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
645 /// 1 is the non-bending plane.
646 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
647 /// where N = NumberOfDigits(chamber, cathode)
649 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
650 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
653 //_____________________________________________________________________________
654 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
656 /// Returns the number of reconstructed raw clusters on the specified chamber.
657 /// @param chamber The chamber number in the range [0 .. 13].
659 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
660 return CountObjects(iter);
663 //_____________________________________________________________________________
664 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
666 /// Returns a pointer to the index'th raw cluster on the specified chamber.
667 /// @param chamber The chamber number in the range [0 .. 13].
668 /// @param index The index number of the raw cluster to fetch in the range [0 .. N-1],
669 /// where N = NumberOfRawClusters(chamber)
671 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
672 return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
675 //_____________________________________________________________________________
676 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
678 /// Returns the number of reconstructed local trigger objects.
680 TIterator* iter = GetIterator(kLocalTriggerIterator);
681 return CountObjects(iter);
684 //_____________________________________________________________________________
685 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
687 /// Returns a pointer to the index'th local trigger object.
688 /// @param index The index number of the local trigger object to fetch in the range [0 .. N-1],
689 /// where N = NumberOfLocalTriggers()
691 TIterator* iter = GetIterator(kLocalTriggerIterator);
692 return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
695 //_____________________________________________________________________________
696 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
698 /// Returns the number of regional trigger objects reconstructed.
700 TIterator* iter = GetIterator(kRegionalTriggerIterator);
701 return CountObjects(iter);
704 //_____________________________________________________________________________
705 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
707 /// Returns a pointer to the index'th regional trigger object.
708 /// @param index The index number of the regional trigger object to fetch in the range [0 .. N-1],
709 /// where N = NumberOfRegionalTriggers()
711 TIterator* iter = GetIterator(kRegionalTriggerIterator);
712 return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
715 //_____________________________________________________________________________
716 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
718 /// Returns a pointer to the reconstructed global trigger object for the event.
720 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
721 if (store == 0x0) return 0x0;
722 return store->Global();
725 //_____________________________________________________________________________
726 void AliMUONDataInterface::ResetStores()
728 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
729 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
732 if (fDigitStore != 0x0)
737 if (fTriggerStore != 0x0)
739 delete fTriggerStore;
742 if (fClusterStore != 0x0)
744 delete fClusterStore;
749 //_____________________________________________________________________________
750 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
752 /// Creates an appropriate iterator object and returns it.
753 /// If the iterator has already been created then that one is returned otherwise
754 /// a new object is created.
755 /// Depending on the value of 'type' the semantics of parameters x and y can change.
756 /// @param type The type of iterator to create.
757 /// @param x This is the detector element ID if type == kDigitIteratorByDetectorElement
758 /// If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
759 /// then this is the chamber number. In all other cases this parameter is
761 /// @param y If type == kDigitIteratorByChamberAndCathode then this parameter is the
762 /// cathode number. In all other cases this parameter is
765 if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
768 if (fCurrentEvent == -1)
770 AliError("No event was selected. Try first using GetEvent().");
778 case kDigitIteratorByDetectorElement:
781 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
782 if (store == 0x0) return 0x0;
783 fIterator = store->CreateIterator(detElem, detElem, 2);
784 if (fIterator == 0x0) return 0x0;
785 fCurrentIteratorType = kDigitIteratorByDetectorElement;
790 case kDigitIteratorByChamberAndCathode:
794 if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
797 "Must have give a chamber value in the range [0..%d], but got a value of: %d",
798 AliMpConstants::NofChambers() - 1,
803 if (cathode < 0 or 1 < cathode)
805 AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
809 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
810 if (store == 0x0) return 0x0;
811 MpPair_t pair = AliMpDEManager::GetDetElemIdRange(chamber);
812 fIterator = store->CreateIterator(AliMp::PairFirst(pair), AliMp::PairSecond(pair), cathode);
813 if (fIterator == 0x0) return 0x0;
814 fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
820 case kRawClusterIterator:
823 AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
824 if (store == 0x0) return 0x0;
825 fIterator = store->CreateChamberIterator(chamber, chamber);
826 if (fIterator == 0x0) return 0x0;
827 fCurrentIteratorType = kRawClusterIterator;
832 case kLocalTriggerIterator:
834 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
835 if (store == 0x0) return 0x0;
836 fIterator = store->CreateLocalIterator();
837 if (fIterator == 0x0) return 0x0;
838 fCurrentIteratorType = kLocalTriggerIterator;
842 case kRegionalTriggerIterator:
844 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
845 if (store == 0x0) return 0x0;
846 fIterator = store->CreateRegionalIterator();
847 if (fIterator == 0x0) return 0x0;
848 fCurrentIteratorType = kRegionalTriggerIterator;
857 //_____________________________________________________________________________
858 void AliMUONDataInterface::ResetIterator()
860 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
861 /// The iterator type and temporary data indicating the state of the iterator are
864 if (fIterator != 0x0) delete fIterator;
865 fCurrentIteratorType = kNoIterator;
866 fCurrentIndex = fDataX = fDataY = -1;
870 //_____________________________________________________________________________
871 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
873 /// Counts the number of objects in the iterator and resets it.
874 /// @return The number of objects in 'iter'.
876 if (iter == 0x0) return -1;
879 while ( iter->Next() != 0x0 ) count++;
885 //_____________________________________________________________________________
886 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
888 /// Fetches the index'th object from the iterator counting the first object
889 /// returned by iterator after it is reset as index == 0. The next object
890 /// has index == 1 and so on where the last object returned by the iterator
891 /// has index == N-1 where N = CountObjects(iter)
892 /// This method will only reset the iterator if index is smaller than
893 /// fCurrentIndex, which is used to track the iteration progress and is
894 /// updated when a new object if returned by this method.
895 /// @param iter The iterator to fetch an object from.
896 /// @param index The index number of the object to fetch in the range [0 .. N-1]
897 /// where N = CountObjects(iter)
901 AliError(Form("Index is out of bounds. Got a value of %d.", index));
905 if (iter == 0x0) return 0x0;
906 if (index <= fCurrentIndex)
912 TObject* object = 0x0;
913 while (fCurrentIndex < index)
915 object = iter->Next();
918 AliError(Form("Index is out of bounds. Got a value of %d.", index));