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 /// \class AliMUONTriggerChamberEff
19 /// implementation of the trigger chamber efficiency determination from
20 /// data, and returns the
21 /// efficiencyCells.dat with the calculated efficiencies
23 /// \author Diego Stocco (Torino)
25 #include "AliMUONTriggerChamberEff.h"
26 #include "AliMUONVDigit.h"
27 #include "AliMUONConstants.h"
28 #include "AliMUONGlobalTrigger.h"
29 #include "AliMUONGeometryTransformer.h"
31 #include "AliMUONRecData.h"
32 #include "AliMUONTriggerTrack.h"
34 #include "AliMpVSegmentation.h"
35 #include "AliMpSegmentation.h"
37 #include "AliMpDEIterator.h"
38 #include "AliMpPlaneType.h"
40 #include "AliRunLoader.h"
43 #include <Riostream.h>
49 ClassImp(AliMUONTriggerChamberEff)
52 //_____________________________________________________________________________
53 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const char* galiceFile,
54 Int_t firstEvent, Int_t lastEvent)
56 fFirstEvent(firstEvent),
57 fLastEvent(lastEvent),
62 fReproduceTrigResponse(kFALSE),
68 /// Standard constructor
69 SetGaliceFile(galiceFile);
73 //_____________________________________________________________________________
74 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(Int_t firstRun, Int_t lastRun,
75 const char* galiceRunDir,
76 Int_t firstEvent, Int_t lastEvent)
78 fFirstEvent(firstEvent),
79 fLastEvent(lastEvent),
84 fReproduceTrigResponse(kFALSE),
88 fGaliceDir(galiceRunDir)
90 /// Standard constructor
94 //_____________________________________________________________________________
95 AliMUONTriggerChamberEff::~AliMUONTriggerChamberEff()
98 fRunLoader->UnloadAll();
103 //_____________________________________________________________________________
104 void AliMUONTriggerChamberEff::SetGaliceFile(const char *galiceFile)
107 /// Opens the galice.root and loads tracks and digits.
110 fRunLoader = AliRunLoader::Open(galiceFile,"MUONFolder","READ");
113 AliError(Form("Error opening %s file \n",galiceFile));
117 fRunLoader->LoadgAlice();
118 gAlice = fRunLoader->GetAliRun();
119 fMUON = (AliMUON*)gAlice->GetModule("MUON");
121 if(fLastEvent<=0 || fLastEvent>fRunLoader->GetNumberOfEvents())fLastEvent = fRunLoader->GetNumberOfEvents()-1;
122 if(fFirstEvent<0)fFirstEvent=0;
125 AliLoader* loader = fRunLoader->GetLoader("MUONLoader");
128 fData = new AliMUONRecData(loader,"MUON","MUON");
129 loader->LoadTracks("READ");
130 loader->LoadDigits("READ");
134 AliError(Form("Could get MUONLoader"));
139 //_____________________________________________________________________________
140 void AliMUONTriggerChamberEff::CleanGalice()
143 /// Unload all loaded data
147 fRunLoader->UnloadAll("all");
152 //_____________________________________________________________________________
153 void AliMUONTriggerChamberEff::ResetArrays()
156 /// Sets the data member counters to 0.
159 for(Int_t ch=0; ch<fgkNchambers; ch++){
160 for(Int_t cath=0; cath<fgkNcathodes; cath++){
161 fTrigger34[ch][cath] = 0;
162 fTrigger44[cath] = 0;
163 for(Int_t slat=0; slat<fgkNslats; slat++){
164 fInefficientSlat[ch][cath][slat] = 0;
165 fHitPerSlat[ch][cath][slat] = 0;
172 //_____________________________________________________________________________
173 void AliMUONTriggerChamberEff::InfoDigit()
176 /// Prints information on digits (for debugging)
179 AliMUONDigit * mDigit=0x0;
180 Int_t firstTrigCh = AliMUONConstants::NTrackingCh();
182 Int_t nchambers = AliMUONConstants::NCh();
183 fData->SetTreeAddress("D,GLT");
187 for(Int_t ichamber=firstTrigCh; ichamber<nchambers; ichamber++) {
188 TClonesArray* digits = fData->Digits(ichamber);
190 Int_t ndigits = (Int_t)digits->GetEntriesFast();
191 for(Int_t idigit=0; idigit<ndigits; idigit++) {
192 mDigit = (AliMUONVDigit*)digits->At(idigit);
195 } // end chamber loop
196 fData->ResetDigits();
197 fData->ResetTrigger();
201 //_____________________________________________________________________________
202 Int_t AliMUONTriggerChamberEff::MatchingPad(Int_t &detElemId, Float_t coor[2], const AliMUONGeometryTransformer *kGeomTransformer, Bool_t isMatch[fgkNcathodes], Int_t nboard[fgkNcathodes][4], Float_t zRealMatch[fgkNchambers], Float_t y11)
205 /// Check slat and board number of digit matching track
208 enum {kBending, kNonBending};
210 Float_t minMatchDist[fgkNcathodes];
212 for(Int_t cath=0; cath<fgkNcathodes; cath++){
213 isMatch[cath]=kFALSE;
214 minMatchDist[cath]=9999.;
216 Int_t iChamber = detElemId/100-1;
217 Int_t ch = iChamber-10;
218 Float_t oldDeltaZ = AliMUONConstants::DefaultChamberZ(iChamber) - AliMUONConstants::DefaultChamberZ(10);
220 Int_t iSlat = detElemId%100;
221 Int_t trigDigitBendPlane = -1;
222 TClonesArray* digits = fData->Digits(iChamber);
224 Int_t foundDetElemId = detElemId;
225 Float_t foundZmatch=999.;
226 Float_t yCoorAtPadZ=999.;
227 Int_t ndigits = (Int_t)digits->GetEntriesFast();
228 AliMUONVDigit * mDigit = 0x0;
229 for(Int_t idigit=0; idigit<ndigits; idigit++) { // digit loop
230 mDigit = (AliMUONVDigit*)digits->At(idigit);
231 Int_t currDetElemId = mDigit->DetElemId();
232 Int_t currSlat = currDetElemId%100;
233 if(TMath::Abs(currSlat%18-iSlat%18)>1)continue; // Check neighbour slats
234 Int_t cathode = mDigit->Cathode();
235 Int_t ix = mDigit->PadX();
236 Int_t iy = mDigit->PadY();
237 Float_t xpad, ypad, zpad;
238 const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
239 ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
241 AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE);
242 Float_t xlocal1 = pad.Position().X();
243 Float_t ylocal1 = pad.Position().Y();
244 Float_t dpx = pad.Dimensions().X();
245 Float_t dpy = pad.Dimensions().Y();
246 kGeomTransformer->Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
247 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]);
248 // searching track intersection with chambers (second approximation)
250 Float_t deltaZ = zpad - zRealMatch[0];
251 y = (coor[1]-y11)*deltaZ/oldDeltaZ + y11;
252 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);
254 Float_t matchDist = PadMatchTrack(xpad, ypad, dpx, dpy, coor[0], y, ch);
255 if(matchDist>minMatchDist[cathode])continue;
256 isMatch[cathode] = kTRUE;
257 minMatchDist[cathode] = matchDist;
258 foundDetElemId = currDetElemId;
261 if(cathode==kBending)trigDigitBendPlane = idigit;
262 for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
263 AliMpIntPair location = pad.GetLocation(loc);
264 nboard[cathode][loc] = location.GetFirst();
266 for(Int_t loc=pad.GetNofLocations(); loc<4; loc++){
267 nboard[cathode][loc]=-1;
270 if(isMatch[kBending] || isMatch[kNonBending]){
271 detElemId = foundDetElemId;
272 zRealMatch[ch] = foundZmatch;
273 coor[1] = yCoorAtPadZ;
275 Int_t whichCathode=kBending;
276 if(!isMatch[kBending])whichCathode=kNonBending;
279 return trigDigitBendPlane;
282 //_____________________________________________________________________________
283 Float_t AliMUONTriggerChamberEff::PadMatchTrack(Float_t xPad, Float_t yPad, Float_t dpx, Float_t dpy,
284 Float_t xTrackAtPad, Float_t yTrackAtPad, Int_t chamber)
287 /// Decides if the digit belongs to the trigger track.
290 Float_t maxDist = 3.;//cm
292 Float_t matchDist = 99999.;
294 Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
295 Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
296 Float_t maxDistX = maxDist;
297 Float_t maxDistY = maxDist;
299 if(fReproduceTrigResponse){
302 deltaX = TMath::Abs(xPad-xTrackAtPad);
303 deltaY = TMath::Abs(yPad-yTrackAtPad);
304 if(dpx<dpy && chamber>=2) maxDistX = 3.*dpx;// Non-bending plane: check the +- 1 strip between stations
305 if(dpy<dpx && chamber%2) maxDistY = 3.*dpy;// bending plane: check the +- 1 strip between planes in the same station
308 if(deltaX<=maxDistX && deltaY<=maxDistY)matchDist = deltaX*deltaX + deltaY*deltaY;
313 //_____________________________________________________________________________
314 void AliMUONTriggerChamberEff::CalculateEfficiency(Int_t trigger44, Int_t trigger34,
315 Float_t &efficiency, Float_t &error, Bool_t failuresAsInput)
318 /// Returns the efficiency.
324 efficiency=(Double_t)trigger44/((Double_t)trigger34);
325 if(failuresAsInput)efficiency=1.-(Double_t)trigger44/((Double_t)trigger34);
327 Double_t q = TMath::Abs(1-efficiency);
328 if(efficiency<0)error=0.0;
329 else error = TMath::Sqrt(efficiency*q/((Double_t)trigger34));
333 //_____________________________________________________________________________
334 Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y, Int_t chamber, Int_t cathode)
337 /// Given the (x,y) position in the chamber,
338 /// it returns the corresponding slat
341 Int_t resultingDetElemId = -1;
343 const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
344 Float_t minDist = 999.;
345 for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
346 Int_t detElemId = it.CurrentDEId();
347 Int_t ich = detElemId/100-10;
348 Float_t tolerance=0.2*((Float_t)ich);
349 Float_t currDist=9999.;
351 const AliMpVSegmentation* seg =
352 AliMpSegmentation::Instance()
353 ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
355 Float_t deltax = seg->Dimensions().X();
356 Float_t deltay = seg->Dimensions().Y();
357 Float_t xlocal1 = -deltax;
358 Float_t ylocal1 = -deltay;
359 Float_t xlocal2 = +deltax;
360 Float_t ylocal2 = +deltay;
361 Float_t xg01, yg01, zg1, xg02, yg02, zg2;
362 kGeomTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1);
363 kGeomTransformer->Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2);
365 Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
376 if(x>=xg1-tolerance && x<=xg2+tolerance && y>=yg1-tolerance && y<=yg2+tolerance){ // takes into account errors in extrapolation
377 if(y<yg1) currDist = yg1-y;
378 else if(y>yg2) currDist = y-yg2;
379 if(currDist<minDist) {
380 resultingDetElemId = detElemId;
384 resultingDetElemId = detElemId;
389 return resultingDetElemId;
393 //_____________________________________________________________________________
394 void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y, Int_t detElemId, Int_t cathode, Int_t localBoard[4])
397 /// Given the (x,y) position in the chamber,
398 /// it returns the corresponding local board
401 for(Int_t loc=0; loc<4; loc++){
404 const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
406 kGeomTransformer->Global2Local(detElemId, x, y, 0, xl, yl, zl);
408 const AliMpVSegmentation* seg =
409 AliMpSegmentation::Instance()
410 ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
412 AliMpPad pad = seg->PadByPosition(pos,kFALSE);
413 for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
414 AliMpIntPair location = pad.GetLocation(loc);
415 localBoard[loc] = location.GetFirst();
421 //_____________________________________________________________________________
422 void AliMUONTriggerChamberEff::PrintTrigger(AliMUONGlobalTrigger *globalTrig)
425 /// Print trigger response.
428 printf("===================================================\n");
429 printf(" Global Trigger output\t \tLow pt\tHigh pt\n");
431 printf(" number of Single:\t \t");
432 printf("%i\t",globalTrig->SingleLpt());
433 printf("%i\t",globalTrig->SingleHpt());
436 printf(" number of UnlikeSign pair:\t");
437 printf("%i\t",globalTrig->PairUnlikeLpt());
438 printf("%i\t",globalTrig->PairUnlikeHpt());
441 printf(" number of LikeSign pair:\t");
442 printf("%i\t",globalTrig->PairLikeLpt());
443 printf("%i\t",globalTrig->PairLikeHpt());
445 printf("===================================================\n");
449 void AliMUONTriggerChamberEff::PerformTriggerChamberEff(const char* outputDir)
453 /// It loops over the the trigger rec. tracks in the event.
454 /// Then it search for matching digits around the track.
455 /// Finally it calculates the efficiency for each trigger board.
456 /// Files with calculated efficiency are placed in the user defined outputDir.
459 enum {kBending, kNonBending};
460 Int_t evtBeforePrint = 1000;
461 Float_t rad2deg = 180./TMath::Pi();
463 Int_t chOrder[fgkNchambers] = {0,2,1,3};
464 Float_t zRealMatch[fgkNchambers] = {0.0};
465 Float_t correctFactor[fgkNcathodes] = {1.};
467 Bool_t match[fgkNchambers][fgkNcathodes] = {{kFALSE}};
468 Bool_t matchPad[fgkNcathodes]={kFALSE};
470 TClonesArray *recTrigTracksArray = 0x0;
471 AliMUONTriggerTrack *recTrigTrack = 0x0;
473 Float_t zMeanChamber[fgkNchambers];
474 for(Int_t ch=0; ch<fgkNchambers; ch++){
475 zMeanChamber[ch] = AliMUONConstants::DefaultChamberZ(10+ch);
478 TClonesArray * globalTrigger = 0x0;
479 AliMUONGlobalTrigger * gloTrg = 0x0;
481 Int_t partNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
482 Int_t totNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
483 Int_t atLeast1MuPerEv[fgkNchambers][fgkNcathodes] = {{0}};
484 Int_t digitPerTrack[fgkNcathodes] = {0};
486 Float_t trackIntersectCh[fgkNchambers][2]={{0.0}};
488 Int_t triggeredDigits[2][fgkNchambers] = {{-1}};
490 Int_t trigScheme[fgkNchambers][fgkNcathodes]={{0}};
491 Int_t slatThatTriggered[fgkNchambers][fgkNcathodes]={{-1}};
492 Int_t boardThatTriggered[fgkNchambers][fgkNcathodes][4]={{{-1}}};
493 Int_t nboard[fgkNcathodes][4]={{-1}};
494 Int_t ineffBoard[4]={-1};
499 if(fFirstRun<0)fFirstRun=fLastRun=-1;
501 for(Int_t iRun = fFirstRun; iRun <= fLastRun; iRun++){// Loop over runs
502 // open run loader and load gAlice
504 cout<<"\n\nRun = "<<iRun<<endl;
505 sprintf(filename, "%s/run%i/galice.root", fGaliceDir.Data(), iRun);
506 if(gSystem->GetPathInfo(filename,fs)){
507 cout<<"Warning: "<<filename<<" not found. Skip to next one"<<endl;
510 cout<<"Opening file "<<filename<<endl;
511 SetGaliceFile(filename);
515 for (Int_t ievent=fFirstEvent; ievent<=fLastEvent; ievent++) { // event loop
516 Bool_t isClearEvent = kTRUE;
518 for(Int_t ch=0; ch<fgkNchambers; ch++){
519 for(Int_t cath=0; cath<fgkNcathodes; cath++){
520 partNumOfTrig[ch][cath]=0;
522 for(Int_t itrack=0; itrack<2; itrack++){
523 triggeredDigits[itrack][ch]=-1;
527 fRunLoader->GetEvent(ievent);
528 if (ievent%evtBeforePrint==0) printf("\t Event = %d\n",ievent);
530 fData->ResetDigits();
531 fData->ResetTrigger();
532 fData->ResetRecTriggerTracks();
533 fData->ResetRecTracks();
535 fData->SetTreeAddress("RL,RT");
536 fData->GetRecTriggerTracks();
537 recTrigTracksArray = fData->RecTriggerTracks();
538 Int_t nRecTrigTracks = (Int_t) recTrigTracksArray->GetEntriesFast();
540 fData->SetTreeAddress("D,GLT");
543 const AliMUONGeometryTransformer* kGeomTransformer = fMUON->GetGeometryTransformer();
545 for (Int_t iRecTrigTrack=0; iRecTrigTrack<nRecTrigTracks; iRecTrigTrack++) {
546 for(Int_t cath=0; cath<fgkNcathodes; cath++){
547 digitPerTrack[cath]=0;
549 for(Int_t ch=0; ch<fgkNchambers; ch++){
550 for(Int_t cath=0; cath<fgkNcathodes; cath++){
551 match[ch][cath]=kFALSE;
552 slatThatTriggered[ch][cath]=-1;
553 for(Int_t loc=0; loc<4; loc++){
554 boardThatTriggered[ch][cath][loc]=-1;
559 Bool_t doubleCountTrack = kFALSE;
561 // reading info from tracks
562 recTrigTrack = (AliMUONTriggerTrack *)recTrigTracksArray->At(iRecTrigTrack);
563 Float_t x11 = recTrigTrack->GetX11();// x position (info from non-bending plane)
564 Float_t y11 = recTrigTrack->GetY11();// y position (info from bending plane)
565 Float_t thetaX = recTrigTrack->GetThetax();
566 Float_t thetaY = recTrigTrack->GetThetay();
568 if(fDebugLevel>=3)printf("\tEvent = %i, Track = %i\npos from track: (x,y) = (%f, %f), (thetaX, thetaY) = (%f, %f)\n",ievent,iRecTrigTrack,x11,y11,thetaX*rad2deg,thetaY*rad2deg);
570 for(Int_t ch=0; ch<fgkNchambers; ch++) {
571 zRealMatch[ch] = zMeanChamber[ch];
572 for(Int_t cath=0; cath<fgkNcathodes; cath++){
573 trigScheme[ch][cath] = 0;
577 for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop
578 Int_t currCh = chOrder[ch];
580 if(fDebugLevel<3)printf("\tEvent = %i, Track = %i\n", ievent, iRecTrigTrack);
581 printf("zMeanChamber[%i] = %.2f\tzRealMatch[0] = %.2f\n",currCh,zMeanChamber[currCh],zRealMatch[0]);
584 for(Int_t cath=0; cath<fgkNcathodes; cath++){
585 correctFactor[cath]=1.;
587 // calculate corrections to trigger track theta
588 if(ch>=1)correctFactor[kNonBending] = zMeanChamber[0]/zRealMatch[0];// corrects x position
589 if(ch>=2)correctFactor[kBending] = (zMeanChamber[2] - zMeanChamber[0]) / (zRealMatch[2] - zRealMatch[0]);// corrects y position
591 // searching track intersection with chambers (first approximation)
592 Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0];
593 trackIntersectCh[currCh][0] = zMeanChamber[currCh] * TMath::Tan(thetaX) * correctFactor[kNonBending];// x position (info from non-bending plane)
594 trackIntersectCh[currCh][1] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
595 Int_t detElemIdFromTrack = DetElemIdFromPos(trackIntersectCh[currCh][0], trackIntersectCh[currCh][1], 11+currCh, 0);
596 if(detElemIdFromTrack<0) {
597 if(fDebugLevel>1) printf("Warning: trigger track outside trigger chamber\n");
601 triggeredDigits[1][currCh] = MatchingPad(detElemIdFromTrack, trackIntersectCh[currCh], kGeomTransformer, matchPad, nboard, zRealMatch, y11);
603 // deciding if digit matches track
604 Bool_t isDiffLocBoard = kFALSE;
605 if(fReproduceTrigResponse && ch>2){
606 for(Int_t cath=0; cath<fgkNcathodes; cath++){
607 if(boardThatTriggered[currCh][cath][0]>=0){
608 if(boardThatTriggered[currCh][cath][0]!=boardThatTriggered[currCh-1][cath][0]) isDiffLocBoard = kTRUE;
613 if(isDiffLocBoard && fDebugLevel>=1)printf("\tDifferent local board\n");
615 for(Int_t cath=0; cath<fgkNcathodes; cath++){
616 match[currCh][cath] = (matchPad[cath] && !isDiffLocBoard);
617 if(!match[currCh][cath]) continue;
618 digitPerTrack[cath]++;
619 trigScheme[currCh][cath]++;
620 slatThatTriggered[currCh][cath] = detElemIdFromTrack;
621 for(Int_t loc=0; loc<4; loc++){
622 boardThatTriggered[currCh][cath][loc] = nboard[cath][loc];
625 } // end chamber loop
627 for(Int_t cath=0; cath<fgkNcathodes; cath++){
628 if(digitPerTrack[cath]<3)isClearEvent = kFALSE;
629 if(fDebugLevel>=1 && !isClearEvent)printf("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath);
632 if(!isClearEvent && !fReproduceTrigResponse) continue;
634 Int_t commonDigits = 0;
635 for(Int_t ch=0; ch<fgkNchambers; ch++){
636 if(triggeredDigits[1][ch]==triggeredDigits[0][ch]) commonDigits++; // Compare with previous track
637 triggeredDigits[0][ch] = triggeredDigits[1][ch]; // Store this track parameters for comparison with next one
640 doubleCountTrack=kTRUE;
643 if(!doubleCountTrack || fReproduceTrigResponse){
644 for(Int_t cath=0; cath<fgkNcathodes; cath++){
646 Bool_t goodForSlatEff = kTRUE;
647 Bool_t goodForBoardEff = kTRUE;
648 Int_t ineffSlat = -1;
649 Int_t ineffDetElId = -1;
650 Int_t firstSlat = slatThatTriggered[0][cath]%100;
651 if(firstSlat<0) firstSlat=slatThatTriggered[1][cath]%100;
652 Int_t firstBoard = boardThatTriggered[0][kBending][0];
653 if(firstBoard<0) firstBoard=boardThatTriggered[1][kBending][0];
654 for(Int_t ch=0; ch<fgkNchambers; ch++){
655 Bool_t isCurrChIneff = kFALSE;
656 is44 *= trigScheme[ch][cath];
657 Int_t currSlat = slatThatTriggered[ch][cath]%100;
659 ineffDetElId = DetElemIdFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], 11+ch, cath);
660 currSlat = ineffDetElId%100;
661 ineffSlat = currSlat;
662 isCurrChIneff = kTRUE;
664 if(currSlat!=firstSlat)goodForSlatEff=kFALSE;
665 Bool_t atLeastOneLoc=kFALSE;
666 if(isCurrChIneff) LocalBoardFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], ineffDetElId, cath, ineffBoard);
667 for(Int_t loc=0; loc<4; loc++){
668 Int_t currBoard = boardThatTriggered[ch][cath][loc];
669 if(isCurrChIneff) currBoard = ineffBoard[loc];
670 if(currBoard==firstBoard){
675 if(!atLeastOneLoc)goodForBoardEff=kFALSE;
676 } // end chamber loop
678 for(Int_t ch=0; ch<fgkNchambers; ch++){
679 if(match[ch][cath])partNumOfTrig[ch][cath]++;
685 if(fDebugLevel>=1)printf("Trigger44[%i] = %i\n",cath,fTrigger44[cath]);
687 for(Int_t ch=0; ch<fgkNchambers; ch++){
688 fHitPerSlat[ch][cath][firstSlat]++;
689 if(fDebugLevel>=1)printf("Slat that triggered = %i\n",slatThatTriggered[ch][cath]);
690 if(goodForBoardEff && firstBoard>0){
691 fHitPerBoard[ch][cath][firstBoard-1]++;
692 if(fDebugLevel>=1)printf("Board that triggered = %i\n",firstBoard);
694 else if(fDebugLevel>=1)printf("Event = %i, Track = %i: Particle crossed different boards: rejected!\n",ievent,iRecTrigTrack);
697 else printf("Event = %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
702 Int_t ineffCh = ineffDetElId/100-11;
703 fTrigger34[ineffCh][cath]++;
704 if(fDebugLevel>=1) printf("Trigger34[%i][%i] = %i\n",ineffCh,cath,fTrigger34[ineffCh][cath]);
706 if(fDebugLevel>=1) printf("Slat non efficient = %i\n",ineffDetElId);
707 fInefficientSlat[ineffCh][cath][ineffSlat]++;
709 if(goodForBoardEff && firstBoard>0){
710 if(fDebugLevel>=1) printf("Board non efficient = %i\n",firstBoard);
711 fInefficientBoard[ineffCh][cath][firstBoard-1]++;
713 else if(fDebugLevel>=1) printf("Event = %i, Track = %i: Particle crossed different boards: rejected!\n",ievent,iRecTrigTrack);
715 else printf("Event %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
717 } // end loop on cathodes
719 else if(doubleCountTrack){
720 if(fDebugLevel<=1)printf("\n\tEvent = %i, Track = %i: ", ievent,iRecTrigTrack);
721 printf("Double Count Track: %i similar to %i. Track rejected!\n",iRecTrigTrack, iRecTrigTrack-1);
723 } // end trigger tracks loop
724 if(nRecTrigTracks<=0) continue;
726 for(Int_t ch=0; ch<fgkNchambers; ch++){
727 for(Int_t cath=0; cath<fgkNcathodes; cath++){
728 totNumOfTrig[ch][cath] += partNumOfTrig[ch][cath];
729 if(partNumOfTrig[ch][cath]>0)atLeast1MuPerEv[ch][cath]++;
735 globalTrigger = fData->GlobalTrigger();
736 Int_t nglobals = (Int_t) globalTrigger->GetEntriesFast(); // should be 1
738 for (Int_t iglobal=0; iglobal<nglobals; iglobal++) { // Global Trigger
739 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->At(iglobal);
741 PrintTrigger(gloTrg);
746 if(fFirstRun>=0)CleanGalice();
747 } //end loop over run
750 WriteEfficiencyMap(outputDir);
752 WriteOutput(outputDir, totNumOfTrig, atLeast1MuPerEv);
755 //_____________________________________________________________________________
756 void AliMUONTriggerChamberEff::WriteOutput(const char* outputDir, Int_t totNumOfTrig[4][2], Int_t atLeast1MuPerEv[4][2])
759 /// Writes information on calculated efficiency.
760 /// It writes: triggerChamberEff.root file containing efficiency histograms.
762 /// In addition a text file triggerChamberEff.out is created,
763 /// with further informations on efficiencies.
766 char *cathodeName[fgkNcathodes]={"Bending plane", "Non-Bending plane"};
767 char *cathCode[fgkNcathodes] = {"bendPlane", "nonBendPlane"};
769 char outFileName[100];
770 sprintf(outFileName, "%s/triggerChamberEff.out",outputDir);
771 FILE *outfile = fopen(outFileName, "w");
772 for(Int_t cath=0; cath<fgkNcathodes; cath++){
773 fprintf(outfile,"%s:\n",cathodeName[cath]);
774 for(Int_t ch=0; ch<fgkNchambers; ch++){
775 fprintf(outfile,"Total number of muon triggers chamber 1%i = %i\n",ch+1,totNumOfTrig[ch][cath]);
777 fprintf(outfile,"\n");
779 fprintf(outfile,"\n");
780 for(Int_t cath=0; cath<fgkNcathodes; cath++){
781 fprintf(outfile,"%s:\n",cathodeName[cath]);
782 for(Int_t ch=0; ch<fgkNchambers; ch++){
783 fprintf(outfile,"At least 1 muon triggered chamber 1%i = %i\n",ch+1, atLeast1MuPerEv[ch][cath]);
785 fprintf(outfile,"\n");
787 fprintf(outfile,"\n\n");
788 for(Int_t cath=0; cath<fgkNcathodes; cath++){
789 fprintf(outfile,"%s:\n",cathodeName[cath]);
790 fprintf(outfile,"Number of triggers where all chambers counted = %i\n",fTrigger44[cath]);
791 fprintf(outfile,"\n");
793 fprintf(outfile,"\n");
794 for(Int_t cath=0; cath<fgkNcathodes; cath++){
795 fprintf(outfile,"%s:\n",cathodeName[cath]);
796 for(Int_t ch=0; ch<fgkNchambers; ch++){
797 fprintf(outfile,"Number of triggers where chamber 1%i did not count = %i\n",ch+1,fTrigger34[ch][cath]);
799 fprintf(outfile,"\n");
802 fprintf(outfile,"\n");
803 for(Int_t cath=0; cath<fgkNcathodes; cath++){
804 fprintf(outfile,"%s:\n",cathodeName[cath]);
805 for(Int_t ch=0; ch<fgkNchambers; ch++){
806 Int_t sumIneff = 0, sumHits = 0;
807 fprintf(outfile,"\n Chamber %1i\n", ch+1);
808 for(Int_t slat=0; slat<fgkNslats; slat++){
809 fprintf(outfile,"Number of triggers where slat %2i - did not count = %5i - was hit (hit%sCh%iSlat%i) = %5i\n",slat,fInefficientSlat[ch][cath][slat],cathCode[cath],11+ch,slat,fHitPerSlat[ch][cath][slat]);
810 sumIneff += fInefficientSlat[ch][cath][slat];
811 sumHits += fHitPerSlat[ch][cath][slat];
813 fprintf(outfile,"Number of triggers where chamber %1i - did not count = %5i - was hit (hit%sCh%i) = %5i\n",ch+1,sumIneff,cathCode[cath],11+ch,sumHits);
815 fprintf(outfile,"\n");
819 sprintf(outFileName, "%s/triggerChamberEff.root",outputDir);
820 TFile *outputHistoFile = new TFile(outFileName,"RECREATE");
821 TDirectory *dir = gDirectory;
823 enum {kSlatIn11, kSlatIn12, kSlatIn13, kSlatIn14, kChamberEff};
824 char *yAxisTitle = "trigger efficiency (a.u.)";
825 char *xAxisTitle = "chamber";
827 TH1F *histo[fgkNcathodes][fgkNchambers+1];
828 TH1F *histoBoard[fgkNcathodes][fgkNchambers];
833 for(Int_t cath=0; cath<fgkNcathodes; cath++){
834 for(Int_t ch=0; ch<fgkNchambers+1; ch++){
836 sprintf(histoName, "%sChamberEff", cathCode[cath]);
837 sprintf(histoTitle, "Chamber efficiency %s", cathCode[cath]);
838 histo[cath][ch] = new TH1F(histoName, histoTitle, fgkNchambers, 11-0.5, 15-0.5);
839 histo[cath][ch]->SetXTitle(xAxisTitle);
840 histo[cath][ch]->SetYTitle(yAxisTitle);
841 histo[cath][ch]->GetXaxis()->SetNdivisions(fgkNchambers);
844 sprintf(histoName, "%sSlatEffChamber%i", cathCode[cath], 11+ch);
845 sprintf(histoTitle, "Chamber %i: slat efficiency %s", 11+ch, cathCode[cath]);
846 histo[cath][ch] = new TH1F(histoName, histoTitle, fgkNslats, 0-0.5, fgkNslats-0.5);
847 histo[cath][ch]->SetXTitle("slat");
848 histo[cath][ch]->SetYTitle(yAxisTitle);
849 histo[cath][ch]->GetXaxis()->SetNdivisions(fgkNslats);
851 sprintf(histoName, "%sBoardEffChamber%i", cathCode[cath], 11+ch);
852 sprintf(histoTitle, "Chamber %i: board efficiency %s", 11+ch, cathCode[cath]);
853 histoBoard[cath][ch] = new TH1F(histoName, histoTitle, fgkNboards, 1-0.5, fgkNboards+1.-0.5);
854 histoBoard[cath][ch]->SetXTitle("boards");
855 histoBoard[cath][ch]->SetYTitle(yAxisTitle);
856 histoBoard[cath][ch]->GetXaxis()->SetNdivisions(fgkNboards);
861 Float_t efficiency, efficiencyError;
863 for(Int_t cath=0; cath<fgkNcathodes; cath++){
864 for(Int_t ch=0; ch<fgkNchambers; ch++){
865 for(Int_t slat=0; slat<fgkNslats; slat++){
866 CalculateEfficiency(fHitPerSlat[ch][cath][slat], fHitPerSlat[ch][cath][slat]+fInefficientSlat[ch][cath][slat], efficiency, efficiencyError, kFALSE);
867 histo[cath][ch]->SetBinContent(slat+1, efficiency);
868 histo[cath][ch]->SetBinError(slat+1, efficiencyError);
870 CalculateEfficiency(fTrigger44[cath], fTrigger34[ch][cath]+fTrigger44[cath], efficiency, efficiencyError, kFALSE);
871 histo[cath][kChamberEff]->SetBinContent(ch+1, efficiency);
872 histo[cath][kChamberEff]->SetBinError(ch+1, efficiencyError);
874 for(Int_t board=0; board<fgkNboards; board++){
875 CalculateEfficiency(fHitPerBoard[ch][cath][board], fHitPerBoard[ch][cath][board]+fInefficientBoard[ch][cath][board], efficiency, efficiencyError, kFALSE);
876 histoBoard[cath][ch]->SetBinContent(board+1, efficiency);
877 histoBoard[cath][ch]->SetBinError(board+1, efficiencyError);
883 outputHistoFile->cd();
884 dir->GetList()->Write();
885 outputHistoFile->Close();
889 //_____________________________________________________________________________
890 void AliMUONTriggerChamberEff::WriteEfficiencyMap(const char* outputDir)
893 /// Writes the calculated efficiency in the text file efficiencyCells.dat
895 /// The file can be further put in $ALICE_ROOT/MUON/data
896 /// and used to run simulations with measured trigger chamber efficiencies.
901 Float_t efficiency, efficiencyError;
903 Int_t aCapo[] = {16, 38, 60, 76, 92, 108, 117, 133, 155, 177, 193, 209, 225, 234};
906 sprintf(filename, "%s/efficiencyCells.dat", outputDir);
907 ofstream outFile(filename);
908 outFile << "localBoards" << endl;
909 for(Int_t ch=0; ch<fgkNchambers; ch++){
911 outFile << "\n\ndetElemId:\t" << 11+ch;
913 for(Int_t cath=0; cath<fgkNcathodes; cath++){
914 outFile << "\n cathode:\t" << cath << endl;
916 for(Int_t board=0; board<fgkNboards; board++){
918 if(board==aCapo[currLine]){
922 CalculateEfficiency(fHitPerBoard[ch][cath][board], fHitPerBoard[ch][cath][board]+fInefficientBoard[ch][cath][board], efficiency, efficiencyError, kFALSE);
923 outFile << " " << setw(effOutWidth) << efficiency;