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)
85 fCurrentIteratorType(kNoIterator),
92 /// @param filename should be the full path to a valid galice.root file
99 if ( ! AliMpCDB::LoadDDLStore() ) {
100 AliFatal("Could not access mapping from OCDB !");
104 //______________________________________________________________________________
105 AliMUONDataInterface::~AliMUONDataInterface()
109 if ( fLoader != 0x0 )
111 delete fLoader->GetRunLoader();
116 //______________________________________________________________________________
118 AliMUONDataInterface::DigitStore(Int_t event)
120 /// Return digitStore for a given event.
121 /// Return 0x0 if event not found.
122 /// Returned pointer should not be deleted
124 if (not IsValid()) return 0x0;
125 if (event == fCurrentEvent and fDigitStore != 0x0) return fDigitStore;
128 if (not LoadEvent(event)) return 0x0;
130 fLoader->LoadDigits();
132 TTree* treeD = fLoader->TreeD();
135 AliError("Could not get treeD");
139 fDigitStore = AliMUONVDigitStore::Create(*treeD);
140 if ( fDigitStore != 0x0 )
142 fDigitStore->Clear();
143 fDigitStore->Connect(*treeD);
147 fLoader->UnloadDigits();
152 //______________________________________________________________________________
153 AliMUONVClusterStore*
154 AliMUONDataInterface::ClusterStore(Int_t event)
156 /// Return clusterStore for a given event.
157 /// Return 0x0 if event not found.
158 /// Returned pointer should not be deleted
160 if (not IsValid()) return 0x0;
161 if (event == fCurrentEvent and fClusterStore != 0x0) return fClusterStore;
164 if (not LoadEvent(event)) return 0x0;
166 fLoader->LoadRecPoints();
168 TTree* treeR = fLoader->TreeR();
171 AliError("Could not get treeR");
175 fClusterStore = AliMUONVClusterStore::Create(*treeR);
176 if ( fClusterStore != 0x0 )
178 fClusterStore->Clear();
179 fClusterStore->Connect(*treeR);
183 fLoader->UnloadRecPoints();
185 return fClusterStore;
188 //_____________________________________________________________________________
189 AliMUONVTriggerStore*
190 AliMUONDataInterface::TriggerStore(Int_t event, const char* treeLetter)
192 /// Return the triggerStore for a given event.
193 /// Return 0x0 if event not found.
194 /// Returned pointer should not be deleted
195 /// treeLetter can be R or D to tell from which tree to read the information
197 if (not IsValid()) return 0x0;
198 if (event == fCurrentEvent and fTriggerStore != 0x0) return fTriggerStore;
201 if (not LoadEvent(event)) return 0x0;
205 TString stree(treeLetter);
210 fLoader->LoadDigits();
211 tree = fLoader->TreeD();
213 else if ( stree == "R" )
215 fLoader->LoadRecPoints();
216 tree = fLoader->TreeR();
221 AliError(Form("Could not get tree%s",treeLetter));
225 fTriggerStore = AliMUONVTriggerStore::Create(*tree);
226 if ( fTriggerStore != 0x0 )
228 fTriggerStore->Clear();
229 fTriggerStore->Connect(*tree);
235 fLoader->UnloadDigits();
237 else if ( stree == "R" )
239 fLoader->UnloadRecPoints();
242 return fTriggerStore;
245 //______________________________________________________________________________
247 AliMUONDataInterface::DumpDigits(Int_t event, Bool_t sorted)
249 /// Dump the digits for a given event, sorted if so required
251 if ( fDigitStore != 0x0 )
255 DumpSorted(*fDigitStore);
259 fDigitStore->Print();
264 //______________________________________________________________________________
266 AliMUONDataInterface::DumpRecPoints(Int_t event, Bool_t sorted)
268 /// Dump the recpoints for a given event, sorted if so required
270 if ( fClusterStore != 0x0 )
274 DumpSorted(*fClusterStore);
278 fClusterStore->Print();
283 //_____________________________________________________________________________
285 AliMUONDataInterface::DumpSorted(const AliMUONVStore& store) const
287 /// Dump the given store, in sorted order
289 TIter next(store.CreateIterator());
292 list.SetOwner(kFALSE);
294 while ( ( object = next() ) )
304 //_____________________________________________________________________________
306 AliMUONDataInterface::DumpTrigger(Int_t event, const char* treeLetter)
308 /// Dump trigger for a given event from a given tree (if event>=0)
309 /// or loop over all events and build a trigger ntuple if event<0
310 /// treeLetter can be R or D to tell from which tree to read the information
314 NtupleTrigger(treeLetter);
318 TriggerStore(event,treeLetter);
320 if ( fTriggerStore != 0x0 )
322 fTriggerStore->Print();
327 //_____________________________________________________________________________
329 AliMUONDataInterface::NtupleTrigger(const char* treeLetter)
331 //// Loop over events to build trigger ntuples
334 TString sTreeLetter(treeLetter);
335 sTreeLetter.ToUpper();
337 if ( sTreeLetter != "R" && sTreeLetter != "D" )
339 AliError(Form("Cannot handle tree%s. Use D or R",treeLetter));
344 TNtuple tupleGlo("TgtupleGlo","Global Trigger Ntuple",
345 "ev:slpt:shpt:uplpt:uphpt:lplpt:lplpt");
346 TNtuple tupleLoc("TgtupleLoc","Local Trigger Ntuple",
347 "ev:LoCircuit:LoStripX:LoDev:StripY:LoLpt:LoHpt:y11:y21:x11");
349 // initialize counters
357 AliMUONGeometryTransformer transformer;
358 transformer.LoadGeometryData(Form("%s/geometry.root",
359 gSystem->DirName(fLoader->GetRunLoader()->GetFileName())));
360 AliMUONTriggerCircuit triggerCircuit(&transformer);
362 // select output file name from selected Tree
363 Char_t fileNameOut[30];
364 if (sTreeLetter == "D")
366 AliInfo(Form("reading from Digits\n"));
367 sprintf(fileNameOut,"TriggerCheckFromDigits.root");
369 else if (sTreeLetter == "R")
371 AliInfo(Form("reading from RecPoints\n"));
372 sprintf(fileNameOut,"TriggerCheckFromRP.root");
376 Int_t nevents = NumberOfEvents();
378 for (Int_t ievent=0; ievent<nevents; ++ievent)
380 if (ievent%100==0) AliInfo(Form("Processing event %d\n",ievent));
382 AliMUONVTriggerStore* triggerStore = TriggerStore(ievent,treeLetter);
386 AliError(Form("Could not read %s from tree%s","Trigger",treeLetter));
390 // get global trigger info
391 AliMUONGlobalTrigger* gloTrg = triggerStore->Global();
392 sLowpt+=gloTrg->SingleLpt();
393 sHighpt+=gloTrg->SingleHpt();
394 uSLowpt+=gloTrg->PairUnlikeLpt();
395 uSHighpt+=gloTrg->PairUnlikeHpt();
396 lSLowpt+=gloTrg->PairLikeLpt();
397 lSHighpt+=gloTrg->PairLikeHpt();
399 // loop on local triggers
400 TIter next(triggerStore->CreateIterator());
401 AliMUONLocalTrigger* locTrg(0x0);
402 while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
407 if ( locTrg->LoSdev()==1 && locTrg->LoDev()==0 &&
408 locTrg->LoStripX()==0) xTrig=kFALSE; // no trigger in X
409 else xTrig=kTRUE; // trigger in X
410 if (locTrg->LoTrigY()==1 &&
411 locTrg->LoStripY()==15 ) yTrig = kFALSE; // no trigger in Y
412 else yTrig = kTRUE; // trigger in Y
415 { // fill ntuple if trigger in X and Y
416 tupleLoc.Fill(ievent,locTrg->LoCircuit(),
422 triggerCircuit.GetY11Pos(locTrg->LoCircuit(),locTrg->LoStripX()),
423 triggerCircuit.GetY21Pos(locTrg->LoCircuit(),locTrg->LoStripX()+locTrg->LoDev()+1),
424 triggerCircuit.GetX11Pos(locTrg->LoCircuit(),locTrg->LoStripY()));
426 tupleGlo.Fill(ievent,gloTrg->SingleLpt(),gloTrg->SingleHpt(),
427 gloTrg->PairUnlikeLpt(),gloTrg->PairUnlikeHpt(),
428 gloTrg->PairLikeLpt(),gloTrg->PairLikeHpt());
429 } // end of loop on local triggers
430 } // end of loop on events
432 // print info and store ntuples
434 printf("=============================================\n");
435 printf("================ SUMMARY ==================\n");
437 printf("Total number of events processed %d \n",nevents);
439 printf(" Global Trigger output Low pt High pt\n");
440 printf(" number of Single :\t");
441 printf("%i\t%i\t",sLowpt,sHighpt);
443 printf(" number of UnlikeSign pair :\t");
444 printf("%i\t%i\t",uSLowpt,uSHighpt);
446 printf(" number of LikeSign pair :\t");
447 printf("%i\t%i\t",lSLowpt,lSHighpt);
449 printf("=============================================\n");
452 TFile myFile(fileNameOut, "RECREATE");
458 //_____________________________________________________________________________
460 AliMUONDataInterface::LoadEvent(Int_t event)
462 /// Load event if different from the current one.
463 /// Returns kFALSE on error and kTRUE if the event was loaded.
467 AliDebug(1,Form("Loading event %d using runLoader %p",event,fLoader->GetRunLoader()));
468 if (fLoader->GetRunLoader()->GetEvent(event) == 0)
470 fCurrentEvent = event;
477 //______________________________________________________________________________
479 AliMUONDataInterface::NumberOfEvents() const
481 /// Number of events in the current galice.root file we're attached to
482 if (not IsValid()) return -1;
483 return fLoader->GetRunLoader()->GetNumberOfEvents();
486 //_____________________________________________________________________________
488 AliMUONDataInterface::Open(const char* filename)
490 /// Connect to a given galice.root file
496 if ( fLoader != 0x0 )
498 delete fLoader->GetRunLoader();
505 TString foldername(Form("%s-%d",ClassName(),fgInstanceCounter));
507 while (AliRunLoader::GetRunLoader(foldername) != 0x0)
509 delete AliRunLoader::GetRunLoader(foldername);
512 AliRunLoader* runLoader = AliRunLoader::Open(filename,foldername);
513 if (runLoader == 0x0)
515 AliError(Form("Cannot open file %s",filename));
519 runLoader->LoadHeader();
520 if ( ! runLoader->GetHeader() ) {
521 AliError("Cannot load header.");
525 Int_t runNumber = runLoader->GetHeader()->GetRun();
526 AliCDBManager::Instance()->SetRun(runNumber);
528 runLoader->UnloadHeader();
530 fLoader = runLoader->GetDetectorLoader("MUON");
533 AliError("Cannot get AliMUONLoader");
539 AliError(Form("Could not access %s filename. Object is unuseable",filename));
543 //_____________________________________________________________________________
544 Bool_t AliMUONDataInterface::GetEvent(Int_t event)
546 /// Loads all reconstructed data for the given event.
548 if (DigitStore(event) == 0x0) return kFALSE;
549 if (ClusterStore(event) == 0x0) return kFALSE;
550 if (TriggerStore(event) == 0x0) return kFALSE;
554 //_____________________________________________________________________________
555 Int_t AliMUONDataInterface::NumberOfDigits(Int_t detElemId)
557 /// Returns the number of digits to be found on a given detector element.
558 /// @param detElemId The detector element ID number to search on.
560 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
561 return CountObjects(iter);
564 //_____________________________________________________________________________
565 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t detElemId, Int_t index)
567 /// Returns the a pointer to the index'th digit on the specified detector element.
568 /// @param detElemId The detector element ID number to search on.
569 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
570 /// where N = NumberOfDigits(detElemId)
572 TIterator* iter = GetIterator(kDigitIteratorByDetectorElement, detElemId);
573 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
576 //_____________________________________________________________________________
577 Int_t AliMUONDataInterface::NumberOfDigits(Int_t chamber, Int_t cathode)
579 /// Returns the number of digits to be found on a specific chamber and cathode.
580 /// @param chamber The chamber number in the range [0 .. 13].
581 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
582 /// 1 is the non-bending plane.
584 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
585 return CountObjects(iter);
588 //_____________________________________________________________________________
589 AliMUONVDigit* AliMUONDataInterface::Digit(Int_t chamber, Int_t cathode, Int_t index)
591 /// Returns the a pointer to the index'th digit on the specified chamber and cathode.
592 /// @param chamber The chamber number in the range [0 .. 13].
593 /// @param cathode The cathode in the range [0 .. 1], where 0 is the bending and
594 /// 1 is the non-bending plane.
595 /// @param index The index number of the digit to fetch in the range [0 .. N-1],
596 /// where N = NumberOfDigits(chamber, cathode)
598 TIterator* iter = GetIterator(kDigitIteratorByChamberAndCathode, chamber, cathode);
599 return static_cast<AliMUONVDigit*>( FetchObject(iter, index) );
602 //_____________________________________________________________________________
603 Int_t AliMUONDataInterface::NumberOfRawClusters(Int_t chamber)
605 /// Returns the number of reconstructed raw clusters on the specified chamber.
606 /// @param chamber The chamber number in the range [0 .. 13].
608 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
609 return CountObjects(iter);
612 //_____________________________________________________________________________
613 AliMUONVCluster* AliMUONDataInterface::RawCluster(Int_t chamber, Int_t index)
615 /// Returns a pointer to the index'th raw cluster on the specified chamber.
616 /// @param chamber The chamber number in the range [0 .. 13].
617 /// @param index The index number of the raw cluster to fetch in the range [0 .. N-1],
618 /// where N = NumberOfRawClusters(chamber)
620 TIterator* iter = GetIterator(kRawClusterIterator, chamber);
621 return static_cast<AliMUONVCluster*>( FetchObject(iter, index) );
624 //_____________________________________________________________________________
625 Int_t AliMUONDataInterface::NumberOfLocalTriggers()
627 /// Returns the number of reconstructed local trigger objects.
629 TIterator* iter = GetIterator(kLocalTriggerIterator);
630 return CountObjects(iter);
633 //_____________________________________________________________________________
634 AliMUONLocalTrigger* AliMUONDataInterface::LocalTrigger(Int_t index)
636 /// Returns a pointer to the index'th local trigger object.
637 /// @param index The index number of the local trigger object to fetch in the range [0 .. N-1],
638 /// where N = NumberOfLocalTriggers()
640 TIterator* iter = GetIterator(kLocalTriggerIterator);
641 return static_cast<AliMUONLocalTrigger*>( FetchObject(iter, index) );
644 //_____________________________________________________________________________
645 Int_t AliMUONDataInterface::NumberOfRegionalTriggers()
647 /// Returns the number of regional trigger objects reconstructed.
649 TIterator* iter = GetIterator(kRegionalTriggerIterator);
650 return CountObjects(iter);
653 //_____________________________________________________________________________
654 AliMUONRegionalTrigger* AliMUONDataInterface::RegionalTrigger(Int_t index)
656 /// Returns a pointer to the index'th regional trigger object.
657 /// @param index The index number of the regional trigger object to fetch in the range [0 .. N-1],
658 /// where N = NumberOfRegionalTriggers()
660 TIterator* iter = GetIterator(kRegionalTriggerIterator);
661 return static_cast<AliMUONRegionalTrigger*>( FetchObject(iter, index) );
664 //_____________________________________________________________________________
665 AliMUONGlobalTrigger* AliMUONDataInterface::GlobalTrigger()
667 /// Returns a pointer to the reconstructed global trigger object for the event.
669 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
670 if (store == 0x0) return 0x0;
671 return store->Global();
674 //_____________________________________________________________________________
675 void AliMUONDataInterface::ResetStores()
677 /// Deletes all the store objects that have been created and resets the pointers to 0x0.
678 /// The temporary iterator object is automatically reset. See ResetIterator for more details.
681 if (fDigitStore != 0x0)
686 if (fTriggerStore != 0x0)
688 delete fTriggerStore;
691 if (fClusterStore != 0x0)
693 delete fClusterStore;
698 //_____________________________________________________________________________
699 TIterator* AliMUONDataInterface::GetIterator(IteratorType type, Int_t x, Int_t y)
701 /// Creates an appropriate iterator object and returns it.
702 /// If the iterator has already been created then that one is returned otherwise
703 /// a new object is created.
704 /// Depending on the value of 'type' the semantics of parameters x and y can change.
705 /// @param type The type of iterator to create.
706 /// @param x This is the detector element ID if type == kDigitIteratorByDetectorElement
707 /// If type equals kDigitIteratorByChamberAndCathode or kRawClusterIterator
708 /// then this is the chamber number. In all other cases this parameter is
710 /// @param y If type == kDigitIteratorByChamberAndCathode then this parameter is the
711 /// cathode number. In all other cases this parameter is
714 if (type == fCurrentIteratorType and fDataX == x and fDataY == y)
717 if (fCurrentEvent == -1)
719 AliError("No event was selected. Try first using GetEvent().");
727 case kDigitIteratorByDetectorElement:
730 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
731 if (store == 0x0) return 0x0;
732 fIterator = store->CreateIterator(detElem, detElem, 2);
733 if (fIterator == 0x0) return 0x0;
734 fCurrentIteratorType = kDigitIteratorByDetectorElement;
739 case kDigitIteratorByChamberAndCathode:
743 if (chamber < 0 or AliMpConstants::NofChambers() <= chamber)
746 "Must have give a chamber value in the range [0..%d], but got a value of: %d",
747 AliMpConstants::NofChambers() - 1,
752 if (cathode < 0 or 1 < cathode)
754 AliError(Form("Must have give a cathode value in the range [0..1], but got a value of: %d", cathode));
758 AliMUONVDigitStore* store = DigitStore(fCurrentEvent);
759 if (store == 0x0) return 0x0;
760 AliMpIntPair pair = AliMpDEManager::GetDetElemIdRange(chamber);
761 fIterator = store->CreateIterator(pair.GetFirst(), pair.GetSecond(), cathode);
762 if (fIterator == 0x0) return 0x0;
763 fCurrentIteratorType = kDigitIteratorByChamberAndCathode;
769 case kRawClusterIterator:
772 AliMUONVClusterStore* store = ClusterStore(fCurrentEvent);
773 if (store == 0x0) return 0x0;
774 fIterator = store->CreateChamberIterator(chamber, chamber);
775 if (fIterator == 0x0) return 0x0;
776 fCurrentIteratorType = kRawClusterIterator;
781 case kLocalTriggerIterator:
783 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
784 if (store == 0x0) return 0x0;
785 fIterator = store->CreateLocalIterator();
786 if (fIterator == 0x0) return 0x0;
787 fCurrentIteratorType = kLocalTriggerIterator;
791 case kRegionalTriggerIterator:
793 AliMUONVTriggerStore* store = TriggerStore(fCurrentEvent);
794 if (store == 0x0) return 0x0;
795 fIterator = store->CreateRegionalIterator();
796 if (fIterator == 0x0) return 0x0;
797 fCurrentIteratorType = kRegionalTriggerIterator;
806 //_____________________________________________________________________________
807 void AliMUONDataInterface::ResetIterator()
809 /// The temporary iterator object is deleted if it exists and the pointer reset to 0x0.
810 /// The iterator type and temporary data indicating the state of the iterator are
813 if (fIterator != 0x0) delete fIterator;
814 fCurrentIteratorType = kNoIterator;
815 fCurrentIndex = fDataX = fDataY = -1;
819 //_____________________________________________________________________________
820 Int_t AliMUONDataInterface::CountObjects(TIterator* iter)
822 /// Counts the number of objects in the iterator and resets it.
823 /// @return The number of objects in 'iter'.
825 if (iter == 0x0) return -1;
828 while ( iter->Next() != 0x0 ) count++;
834 //_____________________________________________________________________________
835 TObject* AliMUONDataInterface::FetchObject(TIterator* iter, Int_t index)
837 /// Fetches the index'th object from the iterator counting the first object
838 /// returned by iterator after it is reset as index == 0. The next object
839 /// has index == 1 and so on where the last object returned by the iterator
840 /// has index == N-1 where N = CountObjects(iter)
841 /// This method will only reset the iterator if index is smaller than
842 /// fCurrentIndex, which is used to track the iteration progress and is
843 /// updated when a new object if returned by this method.
844 /// @param iter The iterator to fetch an object from.
845 /// @param index The index number of the object to fetch in the range [0 .. N-1]
846 /// where N = CountObjects(iter)
850 AliError(Form("Index is out of bounds. Got a value of %d.", index));
854 if (iter == 0x0) return 0x0;
855 if (index <= fCurrentIndex)
861 TObject* object = 0x0;
862 while (fCurrentIndex < index)
864 object = iter->Next();
867 AliError(Form("Index is out of bounds. Got a value of %d.", index));