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 //-----------------------------------------------------------------------------
19 /// \class AliMUONTriggerChamberEff
20 /// Implementation of the trigger chamber efficiency determination from
21 /// data, and returns the
22 /// efficiencyCells.dat with the calculated efficiencies
24 /// \author Diego Stocco (Torino)
25 //-----------------------------------------------------------------------------
27 #include "AliMUONTriggerChamberEff.h"
28 #include "AliMUONVDigit.h"
29 #include "AliMUONConstants.h"
30 #include "AliMUONTriggerTrack.h"
31 #include "AliMUONDigitMaker.h"
32 #include "AliMUONLocalTrigger.h"
33 #include "AliMUONGeometryTransformer.h"
35 #include "AliMUONTrack.h"
36 #include "AliMUONTrackParam.h"
37 #include "AliMUONTrackExtrap.h"
39 #include "AliMUONDigitStoreV1.h"
40 #include "AliMUONVDigitStore.h"
41 #include "AliMUONVTriggerStore.h"
42 #include "AliMUONVTriggerTrackStore.h"
43 #include "AliMUONVTrackStore.h"
44 #include "AliMUONTriggerEfficiencyCells.h"
46 #include "AliMpVSegmentation.h"
47 #include "AliMpSegmentation.h"
49 #include "AliMpDEIterator.h"
50 #include "AliMpPlaneType.h"
51 #include "AliMpDEManager.h"
52 #include "AliMpConstants.h"
56 //#include "AliESDEvent.h"
58 #include <Riostream.h>
63 #include <TSeqCollection.h>
70 ClassImp(AliMUONTriggerChamberEff)
73 //_____________________________________________________________________________
74 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff()
78 fReproduceTrigResponse(kFALSE),
84 /// Default constructor
91 //_____________________________________________________________________________
92 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const AliMUONGeometryTransformer* transformer,
93 const AliMUONDigitMaker* digitMaker,
96 fTransformer(transformer),
97 fDigitMaker(digitMaker),
98 fReproduceTrigResponse(kFALSE),
100 fWriteOnESD(writeOnESD),
102 fkMaxDistance(99999.)
104 /// Standard constructor
111 //_____________________________________________________________________________
112 AliMUONTriggerChamberEff::~AliMUONTriggerChamberEff()
115 Bool_t writeOnESD=fWriteOnESD;
117 if(writeOnESD) SaveInESDFile();
121 //_____________________________________________________________________________
122 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const AliMUONTriggerChamberEff& other)
126 fReproduceTrigResponse(other.fReproduceTrigResponse),
127 fPrintInfo(other.fPrintInfo),
128 fWriteOnESD(other.fWriteOnESD),
129 fDebugLevel(other.fDebugLevel),
130 fkMaxDistance(other.fkMaxDistance),
131 fTrigger44(other.fTrigger44),
132 fTrigger34(other.fTrigger34)
136 for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
137 fInefficientSlat[chCath] = other.fInefficientSlat[chCath];
138 fHitPerSlat[chCath] = other.fHitPerSlat[chCath];
139 fInefficientBoard[chCath] = other.fInefficientBoard[chCath];
140 fHitPerBoard[chCath] = other.fHitPerBoard[chCath];
145 //_____________________________________________________________________________
146 AliMUONTriggerChamberEff& AliMUONTriggerChamberEff::operator=(const AliMUONTriggerChamberEff& other)
148 /// Asignment operator
149 // check assignement to self
153 // base class assignement
154 TObject::operator=(other);
158 fReproduceTrigResponse = other.fReproduceTrigResponse;
159 fPrintInfo = other.fPrintInfo;
160 fWriteOnESD = other.fWriteOnESD;
161 fDebugLevel = other.fDebugLevel;
163 fTrigger44 = other.fTrigger44;
164 fTrigger34 = other.fTrigger34;
166 for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
167 fInefficientSlat[chCath] = other.fInefficientSlat[chCath];
168 fHitPerSlat[chCath] = other.fHitPerSlat[chCath];
169 fInefficientBoard[chCath] = other.fInefficientBoard[chCath];
170 fHitPerBoard[chCath] = other.fHitPerBoard[chCath];
176 //_____________________________________________________________________________
177 void AliMUONTriggerChamberEff::ResetArrays()
180 /// Sets the data member counters to 0.
183 fTrigger44.Set(fgkNcathodes);
184 fTrigger34.Set(fgkNplanes);
186 for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
187 fInefficientSlat[chCath].Set(fgkNslats);
188 fHitPerSlat[chCath].Set(fgkNslats);
189 fInefficientBoard[chCath].Set(AliMpConstants::NofLocalBoards());
190 fHitPerBoard[chCath].Set(AliMpConstants::NofLocalBoards());
196 for(Int_t chCath=0; chCath<fgkNplanes; chCath++){
197 fInefficientSlat[chCath].Reset();
198 fHitPerSlat[chCath].Reset();
199 fInefficientBoard[chCath].Reset();
200 fHitPerBoard[chCath].Reset();
205 //______________________________________________________________________________
207 AliMUONTriggerChamberEff::TriggerDigits(const AliMUONVTriggerStore& triggerStore,
208 AliMUONVDigitStore& digitStore) const
211 /// make (S)Digit for trigger
215 AliMUONLocalTrigger* locTrg;
216 TIter next(triggerStore.CreateLocalIterator());
218 while ( ( locTrg = static_cast<AliMUONLocalTrigger*>(next()) ) )
220 if (locTrg->IsNull()) continue;
222 TArrayS xyPattern[fgkNcathodes];
223 locTrg->GetXPattern(xyPattern[0]);
224 locTrg->GetYPattern(xyPattern[1]);
226 Int_t nBoard = locTrg->LoCircuit();
227 fDigitMaker->TriggerDigits(nBoard, xyPattern, digitStore);
233 //_____________________________________________________________________________
234 void AliMUONTriggerChamberEff::InfoDigit(AliMUONVDigitStore& digitStore)
237 /// Prints information on digits (for debugging)
239 TIter next(digitStore.CreateIterator());
240 AliMUONVDigit* mDigit=0x0;
242 while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
250 //_____________________________________________________________________________
251 Int_t AliMUONTriggerChamberEff::MatchingPad(AliMUONVDigitStore& digitStore, Int_t &detElemId,
252 Float_t coor[2], Bool_t isMatch[2],
253 TArrayI nboard[2], TArrayF &zRealMatch, Float_t y11)
256 /// Check slat and board number of digit matching track
259 enum {kBending, kNonBending};
261 Float_t minMatchDist[fgkNcathodes];
262 Int_t padsInCheckArea[fgkNcathodes];
264 for(Int_t cath=0; cath<fgkNcathodes; cath++){
265 isMatch[cath] = kFALSE;
266 minMatchDist[cath] = fkMaxDistance/10.;
267 padsInCheckArea[cath] = 0;
269 Int_t iChamber = AliMpDEManager::GetChamberId(detElemId);
270 Int_t ch = iChamber-10;
271 Float_t oldDeltaZ = AliMUONConstants::DefaultChamberZ(iChamber) - AliMUONConstants::DefaultChamberZ(10);
273 Int_t iSlat = detElemId%100;
274 Int_t trigDigitBendPlane = -1;
275 Int_t foundDetElemId = detElemId;
276 Float_t foundZmatch=999.;
277 Float_t yCoorAtPadZ=999.;
279 TIter next(digitStore.CreateIterator());
280 AliMUONVDigit* mDigit;
283 while ( ( mDigit = static_cast<AliMUONVDigit*>(next()) ) )
286 Int_t currDetElemId = mDigit->DetElemId();
287 Int_t currCh = AliMpDEManager::GetChamberId(currDetElemId);
288 if(currCh!=iChamber) continue;
289 Int_t currSlat = currDetElemId%100;
290 Int_t slatDiff = TMath::Abs(currSlat-iSlat);
291 if(slatDiff>1 && slatDiff<17) continue; // Check neighbour slats
292 Int_t cathode = mDigit->Cathode();
293 Int_t ix = mDigit->PadX();
294 Int_t iy = mDigit->PadY();
295 Float_t xpad, ypad, zpad;
296 const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
297 ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
299 AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE);
300 Float_t xlocal1 = pad.Position().X();
301 Float_t ylocal1 = pad.Position().Y();
302 Float_t dpx = pad.Dimensions().X();
303 Float_t dpy = pad.Dimensions().Y();
304 fTransformer->Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
305 if(fDebugLevel>2)printf("DetElemId = %i\tCathode = %i\t(x,y) Pad = (%i,%i) = (%.2f,%.2f)\tDim = (%.2f,%.2f)\tTrack = (%.2f,%.2f)\n",currDetElemId,cathode,ix,iy,xpad,ypad,dpx,dpy,coor[0],coor[1]);
306 // searching track intersection with chambers (second approximation)
309 Float_t deltaZ = zpad - zRealMatch[0];
310 y = (coor[1]-y11)*deltaZ/oldDeltaZ + y11;
311 if(fDebugLevel>=3 && TMath::Abs(y-coor[1])>0.1)printf("oldDeltaZ = %7.2f newDeltaZ = %7.2f\toldY = %7.2f new y = %7.2f\n",oldDeltaZ,deltaZ,coor[1],y);
313 Float_t matchDist = PadMatchTrack(xpad, ypad, dpx, dpy, coor[0], y, ch);
314 if(matchDist<fkMaxDistance/2.) padsInCheckArea[cathode]++;
315 if(matchDist>minMatchDist[cathode])continue;
316 isMatch[cathode] = kTRUE;
317 minMatchDist[cathode] = matchDist;
318 foundDetElemId = currDetElemId;
321 if(cathode==kBending) trigDigitBendPlane = idigit;
322 for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
323 AliMpIntPair location = pad.GetLocation(loc);
324 nboard[cathode][loc] = location.GetFirst();
326 for(Int_t loc=pad.GetNofLocations(); loc<fgkNlocations; loc++){
327 nboard[cathode][loc]=-1;
331 for(Int_t cath=0; cath<fgkNcathodes; cath++){
332 if(padsInCheckArea[cath]>2) {
333 if(fDebugLevel>=1) printf("padsInCheckArea[%i] = %i\n",cath,padsInCheckArea[cath]);
338 if(isMatch[kBending] || isMatch[kNonBending]){
339 detElemId = foundDetElemId;
340 zRealMatch[ch] = foundZmatch;
341 coor[1] = yCoorAtPadZ;
343 Int_t whichCathode=kBending;
344 if(!isMatch[kBending])whichCathode=kNonBending;
347 return trigDigitBendPlane;
350 //_____________________________________________________________________________
351 Float_t AliMUONTriggerChamberEff::PadMatchTrack(Float_t xPad, Float_t yPad,
352 Float_t dpx, Float_t dpy,
353 Float_t xTrackAtPad, Float_t yTrackAtPad,
357 /// Decides if the digit belongs to the trigger track.
360 Float_t maxDist = 2.;//3. // cm
361 Float_t maxDistCheckArea = 6.; // cm
363 Float_t matchDist = fkMaxDistance;
365 Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
366 Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
367 Float_t maxDistX = maxDist;
368 Float_t maxDistY = maxDist;
370 if(fReproduceTrigResponse){
373 deltaX = TMath::Abs(xPad-xTrackAtPad);
374 deltaY = TMath::Abs(yPad-yTrackAtPad);
375 if(dpx<dpy && chamber>=2) maxDistX = 3.*dpx;// Non-bending plane: check the +- 1 strip between stations
376 if(dpy<dpx && chamber%2) maxDistY = 3.*dpy;// bending plane: check the +- 1 strip between planes in the same station
379 if(deltaX<=maxDistX && deltaY<=maxDistY) matchDist = TMath::Max(deltaX, deltaY);
380 else if(deltaX<=maxDistCheckArea && deltaY<=maxDistCheckArea) matchDist = fkMaxDistance/5.;
385 //_____________________________________________________________________________
386 void AliMUONTriggerChamberEff::CalculateEfficiency(Int_t trigger44, Int_t trigger34,
387 Float_t &efficiency, Float_t &error,
388 Bool_t failuresAsInput)
391 /// Returns the efficiency.
397 efficiency=(Double_t)trigger44/((Double_t)trigger34);
398 if(failuresAsInput)efficiency=1.-(Double_t)trigger44/((Double_t)trigger34);
400 Double_t q = TMath::Abs(1-efficiency);
401 if(efficiency<0)error=0.0;
402 else error = TMath::Sqrt(efficiency*q/((Double_t)trigger34));
406 //_____________________________________________________________________________
407 Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y,
408 Int_t chamber, Int_t cathode)
411 /// Given the (x,y) position in the chamber,
412 /// it returns the corresponding slat
415 Int_t resultingDetElemId = -1;
417 Float_t minDist = 999.;
418 for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
419 Int_t detElemId = it.CurrentDEId();
420 Int_t ich = detElemId/100-10;
421 Float_t tolerance=0.2*((Float_t)ich);
422 Float_t currDist=9999.;
424 const AliMpVSegmentation* seg =
425 AliMpSegmentation::Instance()
426 ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
429 Float_t deltax = seg->Dimensions().X();
430 Float_t deltay = seg->Dimensions().Y();
431 Float_t xlocal1 = -deltax;
432 Float_t ylocal1 = -deltay;
433 Float_t xlocal2 = +deltax;
434 Float_t ylocal2 = +deltay;
435 Float_t xg01, yg01, zg1, xg02, yg02, zg2;
436 fTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1);
437 fTransformer->Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2);
439 Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
450 if(x>=xg1-tolerance && x<=xg2+tolerance && y>=yg1-tolerance && y<=yg2+tolerance){ // takes into account errors in extrapolation
451 if(y<yg1) currDist = yg1-y;
452 else if(y>yg2) currDist = y-yg2;
453 if(currDist<minDist) {
454 resultingDetElemId = detElemId;
458 resultingDetElemId = detElemId;
461 } // loop on detElemId
462 return resultingDetElemId;
466 //_____________________________________________________________________________
467 void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y,
468 Int_t detElemId, Int_t cathode,
472 /// Given the (x,y) position in the chamber,
473 /// it returns the corresponding local board
476 for(Int_t loc=0; loc<fgkNlocations; loc++){
480 fTransformer->Global2Local(detElemId, x, y, 0, xl, yl, zl);
482 const AliMpVSegmentation* seg =
483 AliMpSegmentation::Instance()
484 ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
486 AliMpPad pad = seg->PadByPosition(pos,kFALSE);
487 for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
488 AliMpIntPair location = pad.GetLocation(loc);
489 localBoard[loc] = location.GetFirst();
495 //_____________________________________________________________________________
496 void AliMUONTriggerChamberEff::EventChamberEff(const AliMUONVTriggerStore& triggerStore,
497 const AliMUONVTriggerTrackStore& trigTrackStore,
498 const AliMUONVTrackStore& trackStore)
502 /// It loops over the the trigger rec. tracks in the event.
503 /// Then it search for matching digits around the track.
504 /// Finally it calculates the efficiency for each trigger board.
505 /// Files with calculated efficiency are placed in the user defined outputDir.
508 if(!fTransformer || ! fDigitMaker) {
509 AliError(Form("AliMUONGeometryTransformer or AliMUONDigitMaker not properly initialized!!"));
513 enum {kBending, kNonBending};
514 Float_t rad2deg = 180./TMath::Pi();
516 Int_t chOrder[fgkNchambers] = {0,2,1,3};
518 TArrayF zRealMatch(fgkNchambers);
519 TArrayF correctFactor(fgkNcathodes);
521 Bool_t match[fgkNchambers][fgkNcathodes];
522 Bool_t matchPad[fgkNcathodes];
523 for(Int_t cath=0; cath<fgkNcathodes; cath++){
524 matchPad[cath] = kFALSE;
527 TArrayF zMeanChamber(fgkNchambers);
528 for(Int_t ch=0; ch<fgkNchambers; ch++){
529 zMeanChamber[ch] = AliMUONConstants::DefaultChamberZ(10+ch);
532 TArrayI digitPerTrack(fgkNcathodes);
534 Float_t trackIntersectCh[fgkNchambers][fgkNcathodes];
536 TArrayI triggeredDigits[2];
537 for(Int_t itrack=0; itrack<2; itrack++){
538 triggeredDigits[itrack].Set(fgkNchambers);
539 triggeredDigits[itrack].Reset(-1);
542 TArrayI trigScheme[fgkNcathodes];
543 TArrayI slatThatTriggered[fgkNcathodes];
544 for(Int_t cath=0; cath<fgkNcathodes; cath++){
545 trigScheme[cath].Set(fgkNchambers);
546 slatThatTriggered[cath].Set(fgkNchambers);
549 Int_t boardThatTriggered[fgkNchambers][fgkNcathodes][fgkNlocations];
550 TArrayI nboard[fgkNcathodes];
551 for(Int_t cath=0; cath<fgkNcathodes; cath++){
552 nboard[cath].Set(fgkNlocations);
554 Int_t ineffBoard[fgkNlocations];
555 for(Int_t loc=0; loc<fgkNlocations; loc++){
556 ineffBoard[loc] = -1;
559 AliMUONDigitStoreV1 digitStore;
560 TriggerDigits(triggerStore,digitStore);
562 AliMUONTriggerTrack *recTrigTrack = 0x0;
564 TIter next(trigTrackStore.CreateIterator());
566 while ( ( recTrigTrack = static_cast<AliMUONTriggerTrack*>(next()) ) )
568 if(!IsCleanTrack(recTrigTrack, trackStore)) {
569 if(fDebugLevel>=1) printf("\tTrack %p (%f, %f) don't match tracker track: rejected!\n",(void *)recTrigTrack,recTrigTrack->GetX11(),recTrigTrack->GetY11());
573 digitPerTrack.Reset();
574 for(Int_t ch=0; ch<fgkNchambers; ch++){
575 zRealMatch[ch] = zMeanChamber[ch];
576 for(Int_t cath=0; cath<fgkNcathodes; cath++){
577 match[ch][cath]=kFALSE;
578 //slatThatTriggered[ch][cath]=-1;
579 //trigScheme[ch][cath] = 0;
580 for(Int_t loc=0; loc<fgkNlocations; loc++){
581 boardThatTriggered[ch][cath][loc]=-1;
586 for(Int_t cath=0; cath<fgkNcathodes; cath++){
587 slatThatTriggered[cath].Reset(-1);
588 trigScheme[cath].Reset();
591 Bool_t isClearEvent = kTRUE;
592 Bool_t doubleCountTrack = kFALSE;
594 Float_t x11 = recTrigTrack->GetX11();// x position (info from non-bending plane)
595 Float_t y11 = recTrigTrack->GetY11();// y position (info from bending plane)
596 Float_t thetaX = recTrigTrack->GetThetax();
597 Float_t thetaY = recTrigTrack->GetThetay();
599 if(fDebugLevel>=3) printf("\tTrack = %p\npos from track: (x,y) = (%f, %f), (thetaX, thetaY) = (%f, %f)\n",(void *)recTrigTrack,x11,y11,thetaX*rad2deg,thetaY*rad2deg);
601 for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop
602 Int_t currCh = chOrder[ch];
604 printf("zMeanChamber[%i] = %.2f\tzRealMatch[0] = %.2f\n",currCh,zMeanChamber[currCh],zRealMatch[0]);
606 for(Int_t cath=0; cath<fgkNcathodes; cath++){
607 correctFactor[cath]=1.;
609 // calculate corrections to trigger track theta
610 if(ch>=1)correctFactor[kNonBending] = zMeanChamber[0]/zRealMatch[0];// corrects x position
611 if(ch>=2)correctFactor[kBending] = (zMeanChamber[2] - zMeanChamber[0]) / (zRealMatch[2] - zRealMatch[0]);// corrects y position
613 // searching track intersection with chambers (first approximation)
614 Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0];
615 trackIntersectCh[currCh][0] = zMeanChamber[currCh] * TMath::Tan(thetaX) * correctFactor[kNonBending];// x position (info from non-bending plane)
616 trackIntersectCh[currCh][1] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
617 Int_t detElemIdFromTrack = DetElemIdFromPos(trackIntersectCh[currCh][0], trackIntersectCh[currCh][1], 11+currCh, 0);
618 if(detElemIdFromTrack<0) {
619 if(fDebugLevel>1) printf("Warning: trigger track outside trigger chamber\n");
623 triggeredDigits[1][currCh] = MatchingPad(digitStore, detElemIdFromTrack, trackIntersectCh[currCh], matchPad, nboard, zRealMatch, y11);
625 // if MatchingPad = -500 => too many digits matching pad =>
626 // => Event not clear => Reject track
627 if(triggeredDigits[1][currCh]<-100){
628 isClearEvent = kFALSE;
629 if(fDebugLevel>=1) printf("Warning: track = %p (%i) matches many pads. Rejected!\n",(void *)recTrigTrack, detElemIdFromTrack);
633 // deciding if digit matches track
634 Bool_t isDiffLocBoard = kFALSE;
635 if(fReproduceTrigResponse && ch>2){
636 for(Int_t cath=0; cath<fgkNcathodes; cath++){
637 if(boardThatTriggered[currCh][cath][0]>=0){
638 if(boardThatTriggered[currCh][cath][0]!=boardThatTriggered[currCh-1][cath][0]) isDiffLocBoard = kTRUE;
643 if(isDiffLocBoard && fDebugLevel>=1)printf("\tDifferent local board\n");
645 for(Int_t cath=0; cath<fgkNcathodes; cath++){
646 match[currCh][cath] = (matchPad[cath] && !isDiffLocBoard);
647 if(!match[currCh][cath]) continue;
648 digitPerTrack[cath]++;
649 trigScheme[cath][currCh]++;
650 slatThatTriggered[cath][currCh] = detElemIdFromTrack;
651 for(Int_t loc=0; loc<fgkNlocations; loc++){
652 boardThatTriggered[currCh][cath][loc] = nboard[cath][loc];
655 } // end chamber loop
657 for(Int_t cath=0; cath<fgkNcathodes; cath++){
658 if(digitPerTrack[cath]<3)isClearEvent = kFALSE;
659 if(fDebugLevel>=1 && !isClearEvent)printf("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath);
662 if(!isClearEvent && !fReproduceTrigResponse) continue;
664 Int_t commonDigits = 0;
665 for(Int_t ch=0; ch<fgkNchambers; ch++){
666 if(triggeredDigits[1][ch]==triggeredDigits[0][ch]) commonDigits++; // Compare with previous track
667 triggeredDigits[0][ch] = triggeredDigits[1][ch]; // Store this track parameters for comparison with next one
670 doubleCountTrack=kTRUE;
673 if(!doubleCountTrack || fReproduceTrigResponse){
674 for(Int_t cath=0; cath<fgkNcathodes; cath++){
676 Bool_t goodForSlatEff = kTRUE;
677 Bool_t goodForBoardEff = kTRUE;
678 Int_t ineffSlat = -1;
679 Int_t ineffDetElId = -1;
680 Int_t firstSlat = slatThatTriggered[cath][0]%100;
681 if(firstSlat<0) firstSlat=slatThatTriggered[cath][1]%100;
682 Int_t firstBoard = boardThatTriggered[0][kBending][0];
683 if(firstBoard<0) firstBoard=boardThatTriggered[1][kBending][0];
684 for(Int_t ch=0; ch<fgkNchambers; ch++){
685 Bool_t isCurrChIneff = kFALSE;
686 is44 *= trigScheme[cath][ch];
687 Int_t currSlat = slatThatTriggered[cath][ch]%100;
689 ineffDetElId = DetElemIdFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], 11+ch, cath);
690 currSlat = ineffDetElId%100;
691 ineffSlat = currSlat;
692 isCurrChIneff = kTRUE;
694 if(currSlat!=firstSlat)goodForSlatEff=kFALSE;
695 Bool_t atLeastOneLoc=kFALSE;
696 if(isCurrChIneff) LocalBoardFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], ineffDetElId, cath, ineffBoard);
697 for(Int_t loc=0; loc<fgkNlocations; loc++){
698 Int_t currBoard = boardThatTriggered[ch][cath][loc];
699 if(isCurrChIneff) currBoard = ineffBoard[loc];
700 if(currBoard==firstBoard){
705 if(!atLeastOneLoc)goodForBoardEff=kFALSE;
706 } // end chamber loop
711 if(fDebugLevel>=1)printf("Trigger44[%i] = %i\n",cath,fTrigger44[cath]);
713 for(Int_t ch=0; ch<fgkNchambers; ch++){
714 Int_t chCath = fgkNchambers*cath + ch;
715 fHitPerSlat[chCath][firstSlat]++;
716 if(fDebugLevel>=1)printf("Slat that triggered = %i\n",slatThatTriggered[cath][ch]);
717 if(goodForBoardEff && firstBoard>0){
718 fHitPerBoard[chCath][firstBoard-1]++;
719 if(fDebugLevel>=1)printf("Board that triggered = %i\n",firstBoard);
721 else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different boards: rejected!\n",(void *)recTrigTrack);
724 else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different slats: rejected!\n",(void *)recTrigTrack);
729 Int_t ineffCh = ineffDetElId/100-11;
730 Int_t chCath = fgkNchambers*cath + ineffCh;
731 fTrigger34[chCath]++;
732 if(fDebugLevel>=1) printf("Trigger34[%i] = %i\n",chCath,fTrigger34[chCath]);
734 if(fDebugLevel>=1) printf("Slat non efficient = %i\n",ineffDetElId);
735 fInefficientSlat[chCath][ineffSlat]++;
737 if(goodForBoardEff && firstBoard>0){
738 if(fDebugLevel>=1) printf("Board non efficient = %i\n",firstBoard);
739 fInefficientBoard[chCath][firstBoard-1]++;
741 else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different boards: rejected!\n",(void *)recTrigTrack);
743 else if(fDebugLevel>=1) printf("Track = %p: Particle crossed different slats: rejected!\n",(void *)recTrigTrack);
745 } // end loop on cathodes
747 else if(doubleCountTrack){
749 printf("\n\tTrack = %p: \nDouble Count Track: Track rejected!\n",(void *)recTrigTrack);
751 } // end trigger tracks loop
753 if(fPrintInfo) InfoDigit(digitStore);
756 //_____________________________________________________________________________
757 void AliMUONTriggerChamberEff::GetEfficiencyHistos(TList &countList, TList &noCountList)
760 /// Gets lists of histograms containing number of 4/4 and 3/4
761 /// for further efficiency calculations.
764 char *cathCode[fgkNcathodes] = {"bendPlane", "nonBendPlane"};
766 char *yAxisTitle = "counts";
768 const Int_t kNumOfBoards = AliMpConstants::NofLocalBoards();
770 enum {kAllChEff, kChNonEff, kNumOfHistoTypes};
771 char *histoTypeName[kNumOfHistoTypes] = {"CountInCh", "NonCountInCh"};
772 char *histoTypeTitle[kNumOfHistoTypes] = {"counted", "non counted"};
773 TH1F *histoCheckChamber[fgkNcathodes][kNumOfHistoTypes];
774 TH1F *histoCheckSlat[fgkNplanes][kNumOfHistoTypes];
775 TH1F *histoCheckBoard[fgkNplanes][kNumOfHistoTypes];
780 for(Int_t cath=0; cath<fgkNcathodes; cath++){
781 for(Int_t hType=0; hType<kNumOfHistoTypes; hType++){
782 sprintf(histoName, "%sChamber%s", cathCode[cath], histoTypeName[hType]);
783 sprintf(histoTitle, "%s %s", histoTypeTitle[hType], cathCode[cath]);
784 histoCheckChamber[cath][hType] = new TH1F(histoName, histoTitle, fgkNchambers, 11-0.5, 11+fgkNchambers-0.5);
785 histoCheckChamber[cath][hType]->SetXTitle("chamber");
786 histoCheckChamber[cath][hType]->SetYTitle(yAxisTitle);
787 histoCheckChamber[cath][hType]->GetXaxis()->SetNdivisions(fgkNchambers);
790 for(Int_t ch=0; ch<fgkNchambers; ch++){
791 Int_t chCath = fgkNchambers*cath + ch;
792 for(Int_t hType=0; hType<kNumOfHistoTypes; hType++){
793 sprintf(histoName, "%sSlat%s%i", cathCode[cath], histoTypeName[hType], 11+ch);
794 sprintf(histoTitle, "Chamber %i: slat %s %s", 11+ch, histoTypeTitle[hType], cathCode[cath]);
795 histoCheckSlat[chCath][hType] = new TH1F(histoName, histoTitle, fgkNslats, 0-0.5, fgkNslats-0.5);
796 histoCheckSlat[chCath][hType]->SetXTitle("slat");
797 histoCheckSlat[chCath][hType]->SetYTitle(yAxisTitle);
798 histoCheckSlat[chCath][hType]->GetXaxis()->SetNdivisions(fgkNslats);
800 sprintf(histoName, "%sBoard%s%i", cathCode[cath], histoTypeName[hType], 11+ch);
801 sprintf(histoTitle, "Chamber %i: board %s %s", 11+ch, histoTypeTitle[hType], cathCode[cath]);
802 histoCheckBoard[chCath][hType] = new TH1F(histoName, histoTitle, kNumOfBoards, 1-0.5, kNumOfBoards+1.-0.5);
803 histoCheckBoard[chCath][hType]->SetXTitle("boards");
804 histoCheckBoard[chCath][hType]->SetYTitle(yAxisTitle);
805 histoCheckBoard[chCath][hType]->GetXaxis()->SetNdivisions(kNumOfBoards);
812 for(Int_t cath=0; cath<fgkNcathodes; cath++){
813 for(Int_t ch=0; ch<fgkNchambers; ch++){
814 Int_t chCath = fgkNchambers*cath + ch;
815 for(Int_t slat=0; slat<fgkNslats; slat++){
816 bin = histoCheckSlat[chCath][kAllChEff]->FindBin(slat);
817 histoCheckSlat[chCath][kAllChEff]->SetBinContent(bin, fHitPerSlat[chCath][slat]);
818 histoCheckSlat[chCath][kChNonEff]->SetBinContent(bin, fInefficientSlat[chCath][slat]);
820 bin = histoCheckChamber[cath][kAllChEff]->FindBin(11+ch);
821 histoCheckChamber[cath][kAllChEff]->SetBinContent(bin, fTrigger44[cath]);
822 histoCheckChamber[cath][kChNonEff]->SetBinContent(bin, fTrigger34[chCath]);
824 for(Int_t board=0; board<kNumOfBoards; board++){
825 bin = histoCheckBoard[chCath][kAllChEff]->FindBin(board+1);
826 histoCheckBoard[chCath][kAllChEff]->SetBinContent(bin, fHitPerBoard[chCath][board]);
827 histoCheckBoard[chCath][kChNonEff]->SetBinContent(bin, fInefficientBoard[chCath][board]);
832 for(Int_t cath=0; cath<fgkNcathodes; cath++){
833 countList.Add(histoCheckChamber[cath][kAllChEff]);
834 noCountList.Add(histoCheckChamber[cath][kChNonEff]);
837 for(Int_t cath=0; cath<fgkNcathodes; cath++){
838 for(Int_t ch=0; ch<fgkNchambers; ch++){
839 Int_t chCath = fgkNchambers*cath + ch;
840 countList.Add(histoCheckSlat[chCath][kAllChEff]);
841 noCountList.Add(histoCheckSlat[chCath][kChNonEff]);
845 for(Int_t cath=0; cath<fgkNcathodes; cath++){
846 for(Int_t ch=0; ch<fgkNchambers; ch++){
847 Int_t chCath = fgkNchambers*cath + ch;
848 countList.Add(histoCheckBoard[chCath][kAllChEff]);
849 noCountList.Add(histoCheckBoard[chCath][kChNonEff]);
855 //_____________________________________________________________________________
856 Bool_t AliMUONTriggerChamberEff::IsCleanTrack(AliMUONTriggerTrack *triggerTrack,
857 const AliMUONVTrackStore& trackStore)
860 /// Try to match track from tracking system with trigger track
862 const Double_t kDistSigma[3]={1,1,0.02}; // sigma of distributions (trigger-track) X,Y,slopeY
863 const Double_t kMaxChi2MatchTrigger = 16.0;
865 AliMUONTrackParam trackParam;
867 Double_t distTriggerTrack[3];
868 Double_t xTrack, yTrack, ySlopeTrack, chi2;
871 TIter next(trackStore.CreateIterator());
873 while ( ( track = static_cast<AliMUONTrack*>(next()) ) )
875 trackParam = *((AliMUONTrackParam*) (track->GetTrackParamAtHit()->Last()));
876 AliMUONTrackExtrap::ExtrapToZ(&trackParam, AliMUONConstants::DefaultChamberZ(10)); // extrap to 1st trigger chamber
878 xTrack = trackParam.GetNonBendingCoor();
879 yTrack = trackParam.GetBendingCoor();
880 ySlopeTrack = trackParam.GetBendingSlope();
882 distTriggerTrack[0] = (triggerTrack->GetX11()-xTrack)/kDistSigma[0];
883 distTriggerTrack[1] = (triggerTrack->GetY11()-yTrack)/kDistSigma[1];
884 distTriggerTrack[2] = (TMath::Tan(triggerTrack->GetThetay())-ySlopeTrack)/kDistSigma[2];
886 for (Int_t iVar = 0; iVar < 3; iVar++) chi2 += distTriggerTrack[iVar]*distTriggerTrack[iVar];
887 chi2 /= 3.; // Normalized Chi2: 3 degrees of freedom (X,Y,slopeY)
888 if (chi2 < kMaxChi2MatchTrigger) return kTRUE;
895 //_____________________________________________________________________________
896 void AliMUONTriggerChamberEff::SaveInESDFile()
899 /// Store AliMUONTriggerChamberEff in esd file
901 TList countHistoList, noCountHistoList;
902 GetEfficiencyHistos(countHistoList, noCountHistoList);
903 AliMUONTriggerEfficiencyCells *effMap =
904 new AliMUONTriggerEfficiencyCells(&countHistoList, &noCountHistoList);
906 TDirectory *dir = gDirectory;
908 TFile *logFile = 0x0;
909 Char_t *esdFileName = "AliESDs.root";
910 TSeqCollection *list = gROOT->GetListOfFiles();
911 Bool_t reopenFile = kFALSE;
912 Int_t n = list->GetEntries();
913 for(Int_t i=0; i<n; i++) {
914 logFile = (TFile*)list->At(i);
915 if (strstr(logFile->GetName(), esdFileName)) break;
919 AliWarning(Form("%s already stored on disk. Re-opening in update mode.",esdFileName));
920 logFile = new TFile(esdFileName, "update");
925 TTree *esdTree = (TTree*)logFile->Get("esdTree");
927 if(!esdTree->GetUserInfo()->FindObject("AliMUONTriggerEfficiencyCells")){
928 AliInfo(Form("Adding AliMUONTriggerEfficiencyCells in %s",esdTree->GetName()));
929 esdTree->GetUserInfo()->Add(effMap);
930 esdTree->Write("",TObject::kOverwrite);
941 //_____________________________________________________________________________
942 void AliMUONTriggerChamberEff::CheckConstants() const
944 /// Check consistence of redefined constants
946 assert(fgkNcathodes == AliMpConstants::NofCathodes());
947 assert(fgkNchambers == AliMpConstants::NofTriggerChambers());
948 assert(fgkNplanes == AliMpConstants::NofTriggerChambers() * fgkNcathodes);