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"
39 #include "AliHeader.h"
40 #include "AliCDBManager.h"
43 #include <TParticle.h>
44 #include <Riostream.h>
49 #include <TIterator.h>
53 //-----------------------------------------------------------------------------
54 /// \class AliMUONDataInterface
56 /// An easy to use interface to the MUON data data stored in
57 /// TreeS, TreeD and TreeR.
59 /// For MC related information (i.e. TreeH, TreeK, TreeTR), see
60 /// AliMUONMCDataInterface.
63 /// This interface in not necessarily the fastest way to fetch the data but
64 /// it is the easiest.
66 /// \author Laurent Aphecetche, Subatech & Artur Szostak <artursz@iafrica.com> (University of Cape Town)
67 //-----------------------------------------------------------------------------
70 ClassImp(AliMUONDataInterface)
74 Int_t AliMUONDataInterface::fgInstanceCounter(0);
76 //______________________________________________________________________________
77 AliMUONDataInterface::AliMUONDataInterface(const char* filename)
86 fCurrentIteratorType(kNoIterator),
93 /// @param filename should be the full path to a valid galice.root file
97 if ( AliCDBManager::Instance() != NULL &&
98 AliCDBManager::Instance()->GetDefaultStorage() == NULL ) {
99 AliFatal("CDB default storage not defined.");
105 if ( ! AliMpCDB::LoadDDLStore() ) {
106 AliFatal("Could not access mapping from OCDB !");
110 //______________________________________________________________________________
111 AliMUONDataInterface::~AliMUONDataInterface()
115 if ( fLoader != 0x0 )
117 delete fLoader->GetRunLoader();
122 //______________________________________________________________________________
124 AliMUONDataInterface::DigitStore(Int_t event)
126 /// Return digitStore for a given event.
127 /// Return 0x0 if event not found.
128 /// Returned pointer should not be deleted
130 /// \note If a previous store has been retrieved by one of the methods of
131 /// this class, but for a different event number, then those stores will
132 /// be deleted and no longer valid.
133 /// If you require access to the data for the earlier retrieved store,
134 /// but for different events, then you should deep copy / clone the object.
136 if (not IsValid()) return 0x0;
138 if (event == fCurrentEvent)
140 if (fDigitStore != 0x0)
146 if ( not LoadEvent(event) ) return 0x0;
149 fLoader->LoadDigits();
151 TTree* treeD = fLoader->TreeD();
154 AliError("Could not get treeD");
158 fDigitStore = AliMUONVDigitStore::Create(*treeD);
159 if ( fDigitStore != 0x0 )
161 fDigitStore->Clear();
162 fDigitStore->Connect(*treeD);
166 fLoader->UnloadDigits();
171 //______________________________________________________________________________
172 AliMUONVClusterStore*
173 AliMUONDataInterface::ClusterStore(Int_t event)
175 /// Return clusterStore for a given event.
176 /// Return 0x0 if event not found.
177 /// Returned pointer should not be deleted
179 /// \note If a previous store has been retrieved by one of the methods of
180 /// this class, but for a different event number, then those stores will
181 /// be deleted and no longer valid.
182 /// If you require access to the data for the earlier retrieved store,
183 /// but for different events, then you should deep copy / clone the object.
185 if (not IsValid()) return 0x0;
187 if (event == fCurrentEvent)
189 if (fClusterStore != 0x0)
190 return fClusterStore;
195 if ( not LoadEvent(event) ) return 0x0;
198 fLoader->LoadRecPoints();
200 TTree* treeR = fLoader->TreeR();
203 AliError("Could not get treeR");
207 fClusterStore = AliMUONVClusterStore::Create(*treeR);
208 if ( fClusterStore != 0x0 )
210 fClusterStore->Clear();
211 fClusterStore->Connect(*treeR);
215 fLoader->UnloadRecPoints();
217 return fClusterStore;
220 //_____________________________________________________________________________
221 AliMUONVTriggerStore*
222 AliMUONDataInterface::TriggerStore(Int_t event, const char* treeLetter)
224 /// Return the triggerStore for a given event.
225 /// Return 0x0 if event not found.
226 /// Returned pointer should not be deleted
227 /// treeLetter can be R or D to tell from which tree to read the information
229 /// \note If a previous store has been retrieved by one of the methods of
230 /// this class, but for a different event number, then those stores will
231 /// be deleted and no longer valid.
232 /// If you require access to the data for the earlier retrieved store,
233 /// but for different events, then you should deep copy / clone the object.
235 if (not IsValid()) return 0x0;
237 if (event == fCurrentEvent)
239 if (fTreeLetter == treeLetter)
241 if (fTriggerStore != 0x0)
242 return fTriggerStore;
246 // Reset only the fTriggerStore since the others might still be valid
247 // for the same event.
248 if (fTriggerStore != 0x0)
250 delete fTriggerStore;
257 // Event has changed so reset all the stores.
259 if ( not LoadEvent(event) ) return 0x0;
264 TString stree(treeLetter);
269 fLoader->LoadDigits();
270 tree = fLoader->TreeD();
272 else if ( stree == "R" )
274 fLoader->LoadRecPoints();
275 tree = fLoader->TreeR();
280 AliError(Form("Could not get tree%s",treeLetter));
284 fTriggerStore = AliMUONVTriggerStore::Create(*tree);
285 if ( fTriggerStore != 0x0 )
287 fTriggerStore->Clear();
288 fTriggerStore->Connect(*tree);
294 fLoader->UnloadDigits();
296 else if ( stree == "R" )
298 fLoader->UnloadRecPoints();
302 return fTriggerStore;
305 //______________________________________________________________________________
307 AliMUONDataInterface::DumpDigits(Int_t event, Bool_t sorted)
309 /// Dump the digits for a given event, sorted if so required
311 if ( fDigitStore != 0x0 )
315 DumpSorted(*fDigitStore);
319 fDigitStore->Print();
324 //______________________________________________________________________________
326 AliMUONDataInterface::DumpRecPoints(Int_t event, Bool_t sorted)
328 /// Dump the recpoints for a given event, sorted if so required
330 if ( fClusterStore != 0x0 )
334 DumpSorted(*fClusterStore);
338 fClusterStore->Print();
343 //_____________________________________________________________________________
345 AliMUONDataInterface::DumpSorted(const AliMUONVStore& store) const
347 /// Dump the given store, in sorted order
349 TIter next(store.CreateIterator());
352 list.SetOwner(kFALSE);
354 while ( ( object = next() ) )
364 //_____________________________________________________________________________
366 AliMUONDataInterface::DumpTrigger(Int_t event, const char* treeLetter)
368 /// Dump trigger for a given event from a given tree (if event>=0)
369 /// or loop over all events and build a trigger ntuple if event<0
370 /// treeLetter can be R or D to tell from which tree to read the information
374 NtupleTrigger(treeLetter);
378 TriggerStore(event,treeLetter);
380 if ( fTriggerStore != 0x0 )
382 fTriggerStore->Print();
387 //_____________________________________________________________________________
389 AliMUONDataInterface::NtupleTrigger(const char* treeLetter)
391 //// Loop over events to build trigger ntuples
394 TString sTreeLetter(treeLetter);
395 sTreeLetter.ToUpper();
397 if ( sTreeLetter != "R" && sTreeLetter != "D" )
399 AliError(Form("Cannot handle tree%s. Use D or R",treeLetter));
404 TNtuple tupleGlo("TgtupleGlo","Global Trigger Ntuple",
405 "ev:slpt:shpt:uplpt:uphpt:lplpt:lplpt");
406 TNtuple tupleLoc("TgtupleLoc","Local Trigger Ntuple",
407 "ev:LoCircuit:LoStripX:LoDev:StripY:LoLpt:LoHpt:y11:y21:x11");
409 // initialize counters
417 AliMUONGeometryTransformer transformer;
418 transformer.LoadGeometryData(Form("%s/geometry.root",
419 gSystem->DirName(fLoader->GetRunLoader()->GetFileName())));
420 AliMUONTriggerCircuit triggerCircuit(&transformer);
422 // select output file name from selected Tree
423 Char_t fileNameOut[30];
424 if (sTreeLetter == "D")
426 AliInfo(Form("reading from Digits\n"));
427 sprintf(fileNameOut,"TriggerCheckFromDigits.root");
429 else if (sTreeLetter == "R")
431 AliInfo(Form("reading from RecPoints\n"));
432 sprintf(fileNameOut,"TriggerCheckFromRP.root");
436 Int_t nevents = NumberOfEvents();
438 for (Int_t ievent=0; ievent<nevents; ++ievent)
440 if (ievent%100==0) AliInfo(Form("Processing event %d\n",ievent));
442 AliMUONVTriggerStore* triggerStore = TriggerStore(ievent,treeLetter);
446 AliError(Form("Could not read %s from tree%s","Trigger",treeLetter));
450 // get global trigger info
451 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
452 sLowpt+=gloTrg->SingleLpt();
453 sHighpt+=gloTrg->SingleHpt();
454 uSLowpt+=gloTrg->PairUnlikeLpt();
455 uSHighpt+=gloTrg->PairUnlikeHpt();
456 lSLowpt+=gloTrg->PairLikeLpt();
457 lSHighpt+=gloTrg->PairLikeHpt();
459 // loop on local triggers
460 TIter next(triggerStore->CreateIterator());
461 AliMUONLocalTrigger* locTrg(0x0);
462 while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
464 Bool_t xTrig=locTrg->IsTrigX();
465 Bool_t yTrig=locTrg->IsTrigY();
468 { // fill ntuple if trigger in X and Y
469 tupleLoc.Fill(ievent,locTrg->LoCircuit(),
475 triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
476 triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
477 triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
479 tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
480 gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
481 gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
482 } // end of loop on local triggers
483 } // end of loop on events
485 // print info and store ntuples
487 printf("=============================================\n");
488 printf("================ SUMMARY ==================\n");
490 printf("Total number of events processed %d \n",nevents);
492 printf(" Global Trigger output Low pt High pt\n");
493 printf(" number of Single :\t");
494 printf("%i\t%i\t",sLowpt,sHighpt);
496 printf(" number of UnlikeSign pair :\t");
497 printf("%i\t%i\t",uSLowpt,uSHighpt);
499 printf(" number of LikeSign pair :\t");
500 printf("%i\t%i\t",lSLowpt,lSHighpt);
502 printf("=============================================\n");
505 TFile myFile(fileNameOut, "RECREATE");
511 //_____________________________________________________________________________
513 AliMUONDataInterface::LoadEvent(Int_t event)
515 /// Load event if different from the current one.
516 /// Returns kFALSE on error and kTRUE if the event was loaded.
520 AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
521 if (fLoader->GetRunLoader()->GetEvent(event) == 0)
523 fCurrentEvent = event;
530 //______________________________________________________________________________
532 AliMUONDataInterface::NumberOfEvents() const
534 /// Number of events in the current galice.root file we're attached to
535 if (not IsValid()) return -1;
536 return fLoader->GetRunLoader()->GetNumberOfEvents();
539 //_____________________________________________________________________________
541 AliMUONDataInterface::Open(const char* filename)
543 /// Connect to a given galice.root file
549 if ( fLoader != 0x0 )
551 delete fLoader->GetRunLoader();
558 TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
560 while (AliRunLoader::GetRunLoader(foldername) != 0x0)
562 delete AliRunLoader::GetRunLoader(foldername);
565 AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
566 if (runLoader == 0x0)
568 AliError(Form("Cannot open file %s",filename));
572 runLoader->LoadHeader();
573 if ( ! runLoader->GetHeader() ) {
574 AliError("Cannot load header.");
578 Int_t runNumber = runLoader->GetHeader()->GetRun();
579 AliCDBManager::Instance()->SetRun(runNumber);
581 runLoader->UnloadHeader();
583 fLoader = runLoader->GetDetectorLoader("MUON");
586 AliError("Cannot get AliMUONLoader");
592 AliError(Form("Could not access %s filename. Object is unuseable",filename));
596 //_____________________________________________________________________________
597 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
599 /// Loads all reconstructed data for the given event.
601 if (DigitStore(event) == 0x0) return kFALSE;
602 if (ClusterStore(event) == 0x0) return kFALSE;
603 if (TriggerStore(event) == 0x0) return kFALSE;
607 //_____________________________________________________________________________
608 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
610 /// Returns the number of digits to be found on a given detector element.
611 /// @param detElemId The detector element ID number to search on.
613 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
614 return CountObjects(iter);
617 //_____________________________________________________________________________
618 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
620 /// Returns the a pointer to the index'th digit on the specified detector element.
621 /// @param detElemId The detector element ID number to search on.
622 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
623 /// where N = NumberOfDigits(detElemId)
625 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
626 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
629 //_____________________________________________________________________________
630 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
632 /// Returns the number of digits to be found on a specific chamber and cathode.
633 /// @param chamber The chamber number in the range [0 .. 13].
634 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
635 /// 1 is the non-bending plane.
637 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
638 return CountObjects(iter);
641 //_____________________________________________________________________________
642 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
644 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
645 /// @param chamber The chamber number in the range [0 .. 13].
646 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
647 /// 1 is the non-bending plane.
648 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
649 /// where N = NumberOfDigits(chamber, cathode)
651 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
652 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
655 //_____________________________________________________________________________
656 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
658 /// Returns the number of reconstructed raw clusters on the specified chamber.
659 /// @param chamber The chamber number in the range [0 .. 13].
661 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
662 return CountObjects(iter);
665 //_____________________________________________________________________________
666 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
668 /// Returns a pointer to the index'th raw cluster on the specified chamber.
669 /// @param chamber The chamber number in the range [0 .. 13].
670 /// @param index The index number of the raw cluster to fetch in the range [0 .. N-1],
671 /// where N = NumberOfRawClusters(chamber)
673 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
674 return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
677 //_____________________________________________________________________________
678 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
680 /// Returns the number of reconstructed local trigger objects.
682 TIterator* iter = GetIterator(kLocalTriggerIterator);
683 return CountObjects(iter);
686 //_____________________________________________________________________________
687 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
689 /// Returns a pointer to the index'th local trigger object.
690 /// @param index The index number of the local trigger object to fetch in the range [0 .. N-1],
691 /// where N = NumberOfLocalTriggers()
693 TIterator* iter = GetIterator(kLocalTriggerIterator);
694 return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
697 //_____________________________________________________________________________
698 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
700 /// Returns the number of regional trigger objects reconstructed.
702 TIterator* iter = GetIterator(kRegionalTriggerIterator);
703 return CountObjects(iter);
706 //_____________________________________________________________________________
707 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
709 /// Returns a pointer to the index'th regional trigger object.
710 /// @param index The index number of the regional trigger object to fetch in the range [0 .. N-1],
711 /// where N = NumberOfRegionalTriggers()
713 TIterator* iter = GetIterator(kRegionalTriggerIterator);
714 return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
717 //_____________________________________________________________________________
718 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
720 /// Returns a pointer to the reconstructed global trigger object for the event.
722 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
723 if (store == 0x0) return 0x0;
724 return store->Global();
727 //_____________________________________________________________________________
728 void AliMUONDataInterface::ResetStores()
730 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
731 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
734 if (fDigitStore != 0x0)
739 if (fTriggerStore != 0x0)
741 delete fTriggerStore;
744 if (fClusterStore != 0x0)
746 delete fClusterStore;
751 //_____________________________________________________________________________
752 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
754 /// Creates an appropriate iterator object and returns it.
755 /// If the iterator has already been created then that one is returned otherwise
756 /// a new object is created.
757 /// Depending on the value of 'type' the semantics of parameters x and y can change.
758 /// @param type The type of iterator to create.
759 /// @param x This is the detector element ID if type == kDigitIteratorByDetectorElement
760 /// If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
761 /// then this is the chamber number. In all other cases this parameter is
763 /// @param y If type == kDigitIteratorByChamberAndCathode then this parameter is the
764 /// cathode number. In all other cases this parameter is
767 if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
770 if (fCurrentEvent == -1)
772 AliError("No event was selected. Try first using GetEvent().");
780 case kDigitIteratorByDetectorElement:
783 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
784 if (store == 0x0) return 0x0;
785 fIterator = store->CreateIterator(detElem, detElem, 2);
786 if (fIterator == 0x0) return 0x0;
787 fCurrentIteratorType = kDigitIteratorByDetectorElement;
792 case kDigitIteratorByChamberAndCathode:
796 if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
799 "Must have give a chamber value in the range [0..%d], but got a value of: %d",
800 AliMpConstants::NofChambers() - 1,
805 if (cathode < 0 or 1 < cathode)
807 AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
811 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
812 if (store == 0x0) return 0x0;
813 AliMpIntPair pair = AliMpDEManager::GetDetElemIdRange(chamber);
814 fIterator = store->CreateIterator(pair.GetFirst(), pair.GetSecond(), cathode);
815 if (fIterator == 0x0) return 0x0;
816 fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
822 case kRawClusterIterator:
825 AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
826 if (store == 0x0) return 0x0;
827 fIterator = store->CreateChamberIterator(chamber, chamber);
828 if (fIterator == 0x0) return 0x0;
829 fCurrentIteratorType = kRawClusterIterator;
834 case kLocalTriggerIterator:
836 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
837 if (store == 0x0) return 0x0;
838 fIterator = store->CreateLocalIterator();
839 if (fIterator == 0x0) return 0x0;
840 fCurrentIteratorType = kLocalTriggerIterator;
844 case kRegionalTriggerIterator:
846 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
847 if (store == 0x0) return 0x0;
848 fIterator = store->CreateRegionalIterator();
849 if (fIterator == 0x0) return 0x0;
850 fCurrentIteratorType = kRegionalTriggerIterator;
859 //_____________________________________________________________________________
860 void AliMUONDataInterface::ResetIterator()
862 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
863 /// The iterator type and temporary data indicating the state of the iterator are
866 if (fIterator != 0x0) delete fIterator;
867 fCurrentIteratorType = kNoIterator;
868 fCurrentIndex = fDataX = fDataY = -1;
872 //_____________________________________________________________________________
873 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
875 /// Counts the number of objects in the iterator and resets it.
876 /// @return The number of objects in 'iter'.
878 if (iter == 0x0) return -1;
881 while ( iter->Next() != 0x0 ) count++;
887 //_____________________________________________________________________________
888 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
890 /// Fetches the index'th object from the iterator counting the first object
891 /// returned by iterator after it is reset as index == 0. The next object
892 /// has index == 1 and so on where the last object returned by the iterator
893 /// has index == N-1 where N = CountObjects(iter)
894 /// This method will only reset the iterator if index is smaller than
895 /// fCurrentIndex, which is used to track the iteration progress and is
896 /// updated when a new object if returned by this method.
897 /// @param iter The iterator to fetch an object from.
898 /// @param index The index number of the object to fetch in the range [0 .. N-1]
899 /// where N = CountObjects(iter)
903 AliError(Form("Index is out of bounds. Got a value of %d.", index));
907 if (iter == 0x0) return 0x0;
908 if (index <= fCurrentIndex)
914 TObject* object = 0x0;
915 while (fCurrentIndex < index)
917 object = iter->Next();
920 AliError(Form("Index is out of bounds. Got a value of %d.", index));