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 "AliMUONDigit.h"
27 #include "AliMUONConstants.h"
28 #include "AliMUONGlobalTrigger.h"
29 #include "AliMUONGeometryTransformer.h"
30 #include "AliMUONSegmentation.h"
32 #include "AliMUONRecData.h"
33 #include "AliMUONTriggerTrack.h"
35 #include "AliMpVSegmentation.h"
36 #include "AliMpSegmentation.h"
38 #include "AliMpDEIterator.h"
39 #include "AliMpPlaneType.h"
41 #include "AliRunLoader.h"
44 #include <Riostream.h>
50 ClassImp(AliMUONTriggerChamberEff)
53 //_____________________________________________________________________________
54 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(const char* galiceFile,
55 Int_t firstEvent, Int_t lastEvent)
57 fFirstEvent(firstEvent),
58 fLastEvent(lastEvent),
63 fReproduceTrigResponse(kFALSE),
69 /// Standard constructor
70 SetGaliceFile(galiceFile);
74 //_____________________________________________________________________________
75 AliMUONTriggerChamberEff::AliMUONTriggerChamberEff(Int_t firstRun, Int_t lastRun,
76 const char* galiceRunDir,
77 Int_t firstEvent, Int_t lastEvent)
79 fFirstEvent(firstEvent),
80 fLastEvent(lastEvent),
85 fReproduceTrigResponse(kFALSE),
89 fGaliceDir(galiceRunDir)
91 /// Standard constructor
95 //_____________________________________________________________________________
96 AliMUONTriggerChamberEff::~AliMUONTriggerChamberEff()
99 fRunLoader->UnloadAll();
104 //_____________________________________________________________________________
105 void AliMUONTriggerChamberEff::SetGaliceFile(const char *galiceFile)
108 /// Opens the galice.root and loads tracks and digits.
111 fRunLoader = AliRunLoader::Open(galiceFile,"MUONFolder","READ");
114 AliError(Form("Error opening %s file \n",galiceFile));
118 fRunLoader->LoadgAlice();
119 gAlice = fRunLoader->GetAliRun();
120 fMUON = (AliMUON*)gAlice->GetModule("MUON");
122 if(fLastEvent<=0 || fLastEvent>fRunLoader->GetNumberOfEvents())fLastEvent = fRunLoader->GetNumberOfEvents()-1;
123 if(fFirstEvent<0)fFirstEvent=0;
126 AliLoader* loader = fRunLoader->GetLoader("MUONLoader");
129 fData = new AliMUONRecData(loader,"MUON","MUON");
130 loader->LoadTracks("READ");
131 loader->LoadDigits("READ");
135 AliError(Form("Could get MUONLoader"));
140 //_____________________________________________________________________________
141 void AliMUONTriggerChamberEff::CleanGalice()
144 /// Unload all loaded data
148 fRunLoader->UnloadAll("all");
153 //_____________________________________________________________________________
154 void AliMUONTriggerChamberEff::ResetArrays()
157 /// Sets the data member counters to 0.
160 for(Int_t ch=0; ch<fgkNchambers; ch++){
161 for(Int_t cath=0; cath<fgkNcathodes; cath++){
162 fTrigger34[ch][cath] = 0;
163 fTrigger44[cath] = 0;
164 for(Int_t slat=0; slat<fgkNslats; slat++){
165 fInefficientSlat[ch][cath][slat] = 0;
166 fHitPerSlat[ch][cath][slat] = 0;
173 //_____________________________________________________________________________
174 void AliMUONTriggerChamberEff::InfoDigit()
177 /// Prints information on digits (for debugging)
180 AliMUONDigit * mDigit=0x0;
181 Int_t firstTrigCh = AliMUONConstants::NTrackingCh();
183 Int_t nchambers = AliMUONConstants::NCh();
184 fData->SetTreeAddress("D,GLT");
188 for(Int_t ichamber=firstTrigCh; ichamber<nchambers; ichamber++) {
189 TClonesArray* digits = fData->Digits(ichamber);
191 Int_t ndigits = (Int_t)digits->GetEntriesFast();
192 for(Int_t idigit=0; idigit<ndigits; idigit++) {
193 mDigit = (AliMUONDigit*)digits->At(idigit);
196 } // end chamber loop
197 fData->ResetDigits();
198 fData->ResetTrigger();
202 //_____________________________________________________________________________
203 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)
206 /// Check slat and board number of digit matching track
209 enum {kBending, kNonBending};
211 Float_t minMatchDist[fgkNcathodes];
213 for(Int_t cath=0; cath<fgkNcathodes; cath++){
214 isMatch[cath]=kFALSE;
215 minMatchDist[cath]=9999.;
217 Int_t iChamber = detElemId/100-1;
218 Int_t ch = iChamber-10;
219 Float_t oldDeltaZ = AliMUONConstants::DefaultChamberZ(iChamber) - AliMUONConstants::DefaultChamberZ(10);
221 Int_t iSlat = detElemId%100;
222 Int_t trigDigitBendPlane = -1;
223 TClonesArray* digits = fData->Digits(iChamber);
225 Int_t foundDetElemId = detElemId;
226 Float_t foundZmatch=999.;
227 Float_t yCoorAtPadZ=999.;
228 Int_t ndigits = (Int_t)digits->GetEntriesFast();
229 AliMUONDigit * mDigit = 0x0;
230 for(Int_t idigit=0; idigit<ndigits; idigit++) { // digit loop
231 mDigit = (AliMUONDigit*)digits->At(idigit);
232 Int_t currDetElemId = mDigit->DetElemId();
233 Int_t currSlat = currDetElemId%100;
234 if(TMath::Abs(currSlat%18-iSlat%18)>1)continue; // Check neighbour slats
235 Int_t cathode = mDigit->Cathode();
236 Int_t ix = mDigit->PadX();
237 Int_t iy = mDigit->PadY();
238 Float_t xpad, ypad, zpad;
239 const AliMpVSegmentation* seg = AliMpSegmentation::Instance()
240 ->GetMpSegmentation(currDetElemId,AliMp::GetCathodType(cathode));
242 AliMpPad pad = seg->PadByIndices(AliMpIntPair(ix,iy),kTRUE);
243 Float_t xlocal1 = pad.Position().X();
244 Float_t ylocal1 = pad.Position().Y();
245 Float_t dpx = pad.Dimensions().X();
246 Float_t dpy = pad.Dimensions().Y();
247 kGeomTransformer->Local2Global(currDetElemId, xlocal1, ylocal1, 0, xpad, ypad, zpad);
248 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]);
249 // searching track intersection with chambers (second approximation)
251 Float_t deltaZ = zpad - zRealMatch[0];
252 y = (coor[1]-y11)*deltaZ/oldDeltaZ + y11;
253 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);
255 Float_t matchDist = PadMatchTrack(xpad, ypad, dpx, dpy, coor[0], y, ch);
256 if(matchDist>minMatchDist[cathode])continue;
257 isMatch[cathode] = kTRUE;
258 minMatchDist[cathode] = matchDist;
259 foundDetElemId = currDetElemId;
262 if(cathode==kBending)trigDigitBendPlane = idigit;
263 for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
264 AliMpIntPair location = pad.GetLocation(loc);
265 nboard[cathode][loc] = location.GetFirst();
267 for(Int_t loc=pad.GetNofLocations(); loc<4; loc++){
268 nboard[cathode][loc]=-1;
271 if(isMatch[kBending] || isMatch[kNonBending]){
272 detElemId = foundDetElemId;
273 zRealMatch[ch] = foundZmatch;
274 coor[1] = yCoorAtPadZ;
276 Int_t whichCathode=kBending;
277 if(!isMatch[kBending])whichCathode=kNonBending;
280 return trigDigitBendPlane;
283 //_____________________________________________________________________________
284 Float_t AliMUONTriggerChamberEff::PadMatchTrack(Float_t xPad, Float_t yPad, Float_t dpx, Float_t dpy,
285 Float_t xTrackAtPad, Float_t yTrackAtPad, Int_t chamber)
288 /// Decides if the digit belongs to the trigger track.
291 Float_t maxDist = 3.;//cm
293 Float_t matchDist = 99999.;
295 Float_t deltaX = TMath::Abs(xPad-xTrackAtPad)-dpx;
296 Float_t deltaY = TMath::Abs(yPad-yTrackAtPad)-dpy;
297 Float_t maxDistX = maxDist;
298 Float_t maxDistY = maxDist;
300 if(fReproduceTrigResponse){
303 deltaX = TMath::Abs(xPad-xTrackAtPad);
304 deltaY = TMath::Abs(yPad-yTrackAtPad);
305 if(dpx<dpy && chamber>=2) maxDistX = 3.*dpx;// Non-bending plane: check the +- 1 strip between stations
306 if(dpy<dpx && chamber%2) maxDistY = 3.*dpy;// bending plane: check the +- 1 strip between planes in the same station
309 if(deltaX<=maxDistX && deltaY<=maxDistY)matchDist = deltaX*deltaX + deltaY*deltaY;
314 //_____________________________________________________________________________
315 void AliMUONTriggerChamberEff::CalculateEfficiency(Int_t trigger44, Int_t trigger34,
316 Float_t &efficiency, Float_t &error, Bool_t failuresAsInput)
319 /// Returns the efficiency.
325 efficiency=(Double_t)trigger44/((Double_t)trigger34);
326 if(failuresAsInput)efficiency=1.-(Double_t)trigger44/((Double_t)trigger34);
328 Double_t q = TMath::Abs(1-efficiency);
329 if(efficiency<0)error=0.0;
330 else error = TMath::Sqrt(efficiency*q/((Double_t)trigger34));
334 //_____________________________________________________________________________
335 Int_t AliMUONTriggerChamberEff::DetElemIdFromPos(Float_t x, Float_t y, Int_t chamber, Int_t cathode)
338 /// Given the (x,y) position in the chamber,
339 /// it returns the corresponding slat
342 Int_t resultingDetElemId = -1;
344 const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
345 AliMUONSegmentation *segmentation = fMUON->GetSegmentation();
346 Float_t minDist = 999.;
347 for ( it.First(chamber-1); ! it.IsDone(); it.Next() ){
348 Int_t detElemId = it.CurrentDEId();
349 Int_t ich = detElemId/100-10;
350 Float_t tolerance=0.2*((Float_t)ich);
351 Float_t currDist=9999.;
353 if ( segmentation->HasDE(detElemId) ){
354 const AliMpVSegmentation* seg =
355 AliMpSegmentation::Instance()
356 ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
358 Float_t deltax = seg->Dimensions().X();
359 Float_t deltay = seg->Dimensions().Y();
360 Float_t xlocal1 = -deltax;
361 Float_t ylocal1 = -deltay;
362 Float_t xlocal2 = +deltax;
363 Float_t ylocal2 = +deltay;
364 Float_t xg01, yg01, zg1, xg02, yg02, zg2;
365 kGeomTransformer->Local2Global(detElemId, xlocal1, ylocal1, 0, xg01, yg01, zg1);
366 kGeomTransformer->Local2Global(detElemId, xlocal2, ylocal2, 0, xg02, yg02, zg2);
368 Float_t xg1 = xg01, xg2 = xg02, yg1 = yg01, yg2 = yg02;
379 if(x>=xg1-tolerance && x<=xg2+tolerance && y>=yg1-tolerance && y<=yg2+tolerance){ // takes into account errors in extrapolation
380 if(y<yg1) currDist = yg1-y;
381 else if(y>yg2) currDist = y-yg2;
382 if(currDist<minDist) {
383 resultingDetElemId = detElemId;
387 resultingDetElemId = detElemId;
393 return resultingDetElemId;
397 //_____________________________________________________________________________
398 void AliMUONTriggerChamberEff::LocalBoardFromPos(Float_t x, Float_t y, Int_t detElemId, Int_t cathode, Int_t localBoard[4])
401 /// Given the (x,y) position in the chamber,
402 /// it returns the corresponding local board
405 for(Int_t loc=0; loc<4; loc++){
408 const AliMUONGeometryTransformer *kGeomTransformer = fMUON->GetGeometryTransformer();
410 kGeomTransformer->Global2Local(detElemId, x, y, 0, xl, yl, zl);
412 const AliMpVSegmentation* seg =
413 AliMpSegmentation::Instance()
414 ->GetMpSegmentation(detElemId,AliMp::GetCathodType(cathode));
416 AliMpPad pad = seg->PadByPosition(pos,kFALSE);
417 for (Int_t loc=0; loc<pad.GetNofLocations(); loc++){
418 AliMpIntPair location = pad.GetLocation(loc);
419 localBoard[loc] = location.GetFirst();
425 //_____________________________________________________________________________
426 void AliMUONTriggerChamberEff::PrintTrigger(AliMUONGlobalTrigger *globalTrig)
429 /// Print trigger response.
432 printf("===================================================\n");
433 printf(" Global Trigger output\t \tLow pt\tHigh pt\n");
435 printf(" number of Single:\t \t");
436 printf("%i\t",globalTrig->SingleLpt());
437 printf("%i\t",globalTrig->SingleHpt());
440 printf(" number of UnlikeSign pair:\t");
441 printf("%i\t",globalTrig->PairUnlikeLpt());
442 printf("%i\t",globalTrig->PairUnlikeHpt());
445 printf(" number of LikeSign pair:\t");
446 printf("%i\t",globalTrig->PairLikeLpt());
447 printf("%i\t",globalTrig->PairLikeHpt());
449 printf("===================================================\n");
453 void AliMUONTriggerChamberEff::PerformTriggerChamberEff(const char* outputDir)
457 /// It loops over the the trigger rec. tracks in the event.
458 /// Then it search for matching digits around the track.
459 /// Finally it calculates the efficiency for each trigger board.
460 /// Files with calculated efficiency are placed in the user defined outputDir.
463 enum {kBending, kNonBending};
464 Int_t evtBeforePrint = 1000;
465 Float_t rad2deg = 180./TMath::Pi();
467 Int_t chOrder[fgkNchambers] = {0,2,1,3};
468 Float_t zRealMatch[fgkNchambers] = {0.0};
469 Float_t correctFactor[fgkNcathodes] = {1.};
471 Bool_t match[fgkNchambers][fgkNcathodes] = {{kFALSE}};
472 Bool_t matchPad[fgkNcathodes]={kFALSE};
474 TClonesArray *recTrigTracksArray = 0x0;
475 AliMUONTriggerTrack *recTrigTrack = 0x0;
477 Float_t zMeanChamber[fgkNchambers];
478 for(Int_t ch=0; ch<fgkNchambers; ch++){
479 zMeanChamber[ch] = AliMUONConstants::DefaultChamberZ(10+ch);
482 TClonesArray * globalTrigger = 0x0;
483 AliMUONGlobalTrigger * gloTrg = 0x0;
485 Int_t partNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
486 Int_t totNumOfTrig[fgkNchambers][fgkNcathodes] = {{0}};
487 Int_t atLeast1MuPerEv[fgkNchambers][fgkNcathodes] = {{0}};
488 Int_t digitPerTrack[fgkNcathodes] = {0};
490 Float_t trackIntersectCh[fgkNchambers][2]={{0.0}};
492 Int_t triggeredDigits[2][fgkNchambers] = {{-1}};
494 Int_t trigScheme[fgkNchambers][fgkNcathodes]={{0}};
495 Int_t slatThatTriggered[fgkNchambers][fgkNcathodes]={{-1}};
496 Int_t boardThatTriggered[fgkNchambers][fgkNcathodes][4]={{{-1}}};
497 Int_t nboard[fgkNcathodes][4]={{-1}};
498 Int_t ineffBoard[4]={-1};
503 if(fFirstRun<0)fFirstRun=fLastRun=-1;
505 for(Int_t iRun = fFirstRun; iRun <= fLastRun; iRun++){// Loop over runs
506 // open run loader and load gAlice
508 cout<<"\n\nRun = "<<iRun<<endl;
509 sprintf(filename, "%s/run%i/galice.root", fGaliceDir.Data(), iRun);
510 if(gSystem->GetPathInfo(filename,fs)){
511 cout<<"Warning: "<<filename<<" not found. Skip to next one"<<endl;
514 cout<<"Opening file "<<filename<<endl;
515 SetGaliceFile(filename);
519 for (Int_t ievent=fFirstEvent; ievent<=fLastEvent; ievent++) { // event loop
520 Bool_t isClearEvent = kTRUE;
522 for(Int_t ch=0; ch<fgkNchambers; ch++){
523 for(Int_t cath=0; cath<fgkNcathodes; cath++){
524 partNumOfTrig[ch][cath]=0;
526 for(Int_t itrack=0; itrack<2; itrack++){
527 triggeredDigits[itrack][ch]=-1;
531 fRunLoader->GetEvent(ievent);
532 if (ievent%evtBeforePrint==0) printf("\t Event = %d\n",ievent);
534 fData->ResetDigits();
535 fData->ResetTrigger();
536 fData->ResetRecTriggerTracks();
537 fData->ResetRecTracks();
539 fData->SetTreeAddress("RL,RT");
540 fData->GetRecTriggerTracks();
541 recTrigTracksArray = fData->RecTriggerTracks();
542 Int_t nRecTrigTracks = (Int_t) recTrigTracksArray->GetEntriesFast();
544 fData->SetTreeAddress("D,GLT");
547 const AliMUONGeometryTransformer* kGeomTransformer = fMUON->GetGeometryTransformer();
549 for (Int_t iRecTrigTrack=0; iRecTrigTrack<nRecTrigTracks; iRecTrigTrack++) {
550 for(Int_t cath=0; cath<fgkNcathodes; cath++){
551 digitPerTrack[cath]=0;
553 for(Int_t ch=0; ch<fgkNchambers; ch++){
554 for(Int_t cath=0; cath<fgkNcathodes; cath++){
555 match[ch][cath]=kFALSE;
556 slatThatTriggered[ch][cath]=-1;
557 for(Int_t loc=0; loc<4; loc++){
558 boardThatTriggered[ch][cath][loc]=-1;
563 Bool_t doubleCountTrack = kFALSE;
565 // reading info from tracks
566 recTrigTrack = (AliMUONTriggerTrack *)recTrigTracksArray->At(iRecTrigTrack);
567 Float_t x11 = recTrigTrack->GetX11();// x position (info from non-bending plane)
568 Float_t y11 = recTrigTrack->GetY11();// y position (info from bending plane)
569 Float_t thetaX = recTrigTrack->GetThetax();
570 Float_t thetaY = recTrigTrack->GetThetay();
572 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);
574 for(Int_t ch=0; ch<fgkNchambers; ch++) {
575 zRealMatch[ch] = zMeanChamber[ch];
576 for(Int_t cath=0; cath<fgkNcathodes; cath++){
577 trigScheme[ch][cath] = 0;
581 for(Int_t ch=0; ch<fgkNchambers; ch++) { // chamber loop
582 Int_t currCh = chOrder[ch];
584 if(fDebugLevel<3)printf("\tEvent = %i, Track = %i\n", ievent, iRecTrigTrack);
585 printf("zMeanChamber[%i] = %.2f\tzRealMatch[0] = %.2f\n",currCh,zMeanChamber[currCh],zRealMatch[0]);
588 for(Int_t cath=0; cath<fgkNcathodes; cath++){
589 correctFactor[cath]=1.;
591 // calculate corrections to trigger track theta
592 if(ch>=1)correctFactor[kNonBending] = zMeanChamber[0]/zRealMatch[0];// corrects x position
593 if(ch>=2)correctFactor[kBending] = (zMeanChamber[2] - zMeanChamber[0]) / (zRealMatch[2] - zRealMatch[0]);// corrects y position
595 // searching track intersection with chambers (first approximation)
596 Float_t deltaZ = zMeanChamber[currCh] - zMeanChamber[0];
597 trackIntersectCh[currCh][0] = zMeanChamber[currCh] * TMath::Tan(thetaX) * correctFactor[kNonBending];// x position (info from non-bending plane)
598 trackIntersectCh[currCh][1] = y11 + deltaZ * TMath::Tan(thetaY) * correctFactor[kBending];// y position (info from bending plane)
599 Int_t detElemIdFromTrack = DetElemIdFromPos(trackIntersectCh[currCh][0], trackIntersectCh[currCh][1], 11+currCh, 0);
600 if(detElemIdFromTrack<0) {
601 if(fDebugLevel>1) printf("Warning: trigger track outside trigger chamber\n");
605 triggeredDigits[1][currCh] = MatchingPad(detElemIdFromTrack, trackIntersectCh[currCh], kGeomTransformer, matchPad, nboard, zRealMatch, y11);
607 // deciding if digit matches track
608 Bool_t isDiffLocBoard = kFALSE;
609 if(fReproduceTrigResponse && ch>2){
610 for(Int_t cath=0; cath<fgkNcathodes; cath++){
611 if(boardThatTriggered[currCh][cath][0]>=0){
612 if(boardThatTriggered[currCh][cath][0]!=boardThatTriggered[currCh-1][cath][0]) isDiffLocBoard = kTRUE;
617 if(isDiffLocBoard && fDebugLevel>=1)printf("\tDifferent local board\n");
619 for(Int_t cath=0; cath<fgkNcathodes; cath++){
620 match[currCh][cath] = (matchPad[cath] && !isDiffLocBoard);
621 if(!match[currCh][cath]) continue;
622 digitPerTrack[cath]++;
623 trigScheme[currCh][cath]++;
624 slatThatTriggered[currCh][cath] = detElemIdFromTrack;
625 for(Int_t loc=0; loc<4; loc++){
626 boardThatTriggered[currCh][cath][loc] = nboard[cath][loc];
629 } // end chamber loop
631 for(Int_t cath=0; cath<fgkNcathodes; cath++){
632 if(digitPerTrack[cath]<3)isClearEvent = kFALSE;
633 if(fDebugLevel>=1 && !isClearEvent)printf("Warning: found %i digits for trigger track cathode %i.\nRejecting event\n", digitPerTrack[cath],cath);
636 if(!isClearEvent && !fReproduceTrigResponse) continue;
638 Int_t commonDigits = 0;
639 for(Int_t ch=0; ch<fgkNchambers; ch++){
640 if(triggeredDigits[1][ch]==triggeredDigits[0][ch]) commonDigits++; // Compare with previous track
641 triggeredDigits[0][ch] = triggeredDigits[1][ch]; // Store this track parameters for comparison with next one
644 doubleCountTrack=kTRUE;
647 if(!doubleCountTrack || fReproduceTrigResponse){
648 for(Int_t cath=0; cath<fgkNcathodes; cath++){
650 Bool_t goodForSlatEff = kTRUE;
651 Bool_t goodForBoardEff = kTRUE;
652 Int_t ineffSlat = -1;
653 Int_t ineffDetElId = -1;
654 Int_t firstSlat = slatThatTriggered[0][cath]%100;
655 if(firstSlat<0) firstSlat=slatThatTriggered[1][cath]%100;
656 Int_t firstBoard = boardThatTriggered[0][kBending][0];
657 if(firstBoard<0) firstBoard=boardThatTriggered[1][kBending][0];
658 for(Int_t ch=0; ch<fgkNchambers; ch++){
659 Bool_t isCurrChIneff = kFALSE;
660 is44 *= trigScheme[ch][cath];
661 Int_t currSlat = slatThatTriggered[ch][cath]%100;
663 ineffDetElId = DetElemIdFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], 11+ch, cath);
664 currSlat = ineffDetElId%100;
665 ineffSlat = currSlat;
666 isCurrChIneff = kTRUE;
668 if(currSlat!=firstSlat)goodForSlatEff=kFALSE;
669 Bool_t atLeastOneLoc=kFALSE;
670 if(isCurrChIneff) LocalBoardFromPos(trackIntersectCh[ch][0], trackIntersectCh[ch][1], ineffDetElId, cath, ineffBoard);
671 for(Int_t loc=0; loc<4; loc++){
672 Int_t currBoard = boardThatTriggered[ch][cath][loc];
673 if(isCurrChIneff) currBoard = ineffBoard[loc];
674 if(currBoard==firstBoard){
679 if(!atLeastOneLoc)goodForBoardEff=kFALSE;
680 } // end chamber loop
682 for(Int_t ch=0; ch<fgkNchambers; ch++){
683 if(match[ch][cath])partNumOfTrig[ch][cath]++;
689 if(fDebugLevel>=1)printf("Trigger44[%i] = %i\n",cath,fTrigger44[cath]);
691 for(Int_t ch=0; ch<fgkNchambers; ch++){
692 fHitPerSlat[ch][cath][firstSlat]++;
693 if(fDebugLevel>=1)printf("Slat that triggered = %i\n",slatThatTriggered[ch][cath]);
694 if(goodForBoardEff && firstBoard>0){
695 fHitPerBoard[ch][cath][firstBoard-1]++;
696 if(fDebugLevel>=1)printf("Board that triggered = %i\n",firstBoard);
698 else if(fDebugLevel>=1)printf("Event = %i, Track = %i: Particle crossed different boards: rejected!\n",ievent,iRecTrigTrack);
701 else printf("Event = %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
706 Int_t ineffCh = ineffDetElId/100-11;
707 fTrigger34[ineffCh][cath]++;
708 if(fDebugLevel>=1) printf("Trigger34[%i][%i] = %i\n",ineffCh,cath,fTrigger34[ineffCh][cath]);
710 if(fDebugLevel>=1) printf("Slat non efficient = %i\n",ineffDetElId);
711 fInefficientSlat[ineffCh][cath][ineffSlat]++;
713 if(goodForBoardEff && firstBoard>0){
714 if(fDebugLevel>=1) printf("Board non efficient = %i\n",firstBoard);
715 fInefficientBoard[ineffCh][cath][firstBoard-1]++;
717 else if(fDebugLevel>=1) printf("Event = %i, Track = %i: Particle crossed different boards: rejected!\n",ievent,iRecTrigTrack);
719 else printf("Event %i, Track = %i: Particle crossed different slats: rejected!\n",ievent,iRecTrigTrack);
721 } // end loop on cathodes
723 else if(doubleCountTrack){
724 if(fDebugLevel<=1)printf("\n\tEvent = %i, Track = %i: ", ievent,iRecTrigTrack);
725 printf("Double Count Track: %i similar to %i. Track rejected!\n",iRecTrigTrack, iRecTrigTrack-1);
727 } // end trigger tracks loop
728 if(nRecTrigTracks<=0) continue;
730 for(Int_t ch=0; ch<fgkNchambers; ch++){
731 for(Int_t cath=0; cath<fgkNcathodes; cath++){
732 totNumOfTrig[ch][cath] += partNumOfTrig[ch][cath];
733 if(partNumOfTrig[ch][cath]>0)atLeast1MuPerEv[ch][cath]++;
739 globalTrigger = fData->GlobalTrigger();
740 Int_t nglobals = (Int_t) globalTrigger->GetEntriesFast(); // should be 1
742 for (Int_t iglobal=0; iglobal<nglobals; iglobal++) { // Global Trigger
743 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->At(iglobal);
745 PrintTrigger(gloTrg);
750 if(fFirstRun>=0)CleanGalice();
751 } //end loop over run
754 WriteEfficiencyMap(outputDir);
756 WriteOutput(outputDir, totNumOfTrig, atLeast1MuPerEv);
759 //_____________________________________________________________________________
760 void AliMUONTriggerChamberEff::WriteOutput(const char* outputDir, Int_t totNumOfTrig[4][2], Int_t atLeast1MuPerEv[4][2])
763 /// Writes information on calculated efficiency.
764 /// It writes: triggerChamberEff.root file containing efficiency histograms.
766 /// In addition a text file triggerChamberEff.out is created,
767 /// with further informations on efficiencies.
770 char *cathodeName[fgkNcathodes]={"Bending plane", "Non-Bending plane"};
771 char *cathCode[fgkNcathodes] = {"bendPlane", "nonBendPlane"};
773 char outFileName[100];
774 sprintf(outFileName, "%s/triggerChamberEff.out",outputDir);
775 FILE *outfile = fopen(outFileName, "w");
776 for(Int_t cath=0; cath<fgkNcathodes; cath++){
777 fprintf(outfile,"%s:\n",cathodeName[cath]);
778 for(Int_t ch=0; ch<fgkNchambers; ch++){
779 fprintf(outfile,"Total number of muon triggers chamber 1%i = %i\n",ch+1,totNumOfTrig[ch][cath]);
781 fprintf(outfile,"\n");
783 fprintf(outfile,"\n");
784 for(Int_t cath=0; cath<fgkNcathodes; cath++){
785 fprintf(outfile,"%s:\n",cathodeName[cath]);
786 for(Int_t ch=0; ch<fgkNchambers; ch++){
787 fprintf(outfile,"At least 1 muon triggered chamber 1%i = %i\n",ch+1, atLeast1MuPerEv[ch][cath]);
789 fprintf(outfile,"\n");
791 fprintf(outfile,"\n\n");
792 for(Int_t cath=0; cath<fgkNcathodes; cath++){
793 fprintf(outfile,"%s:\n",cathodeName[cath]);
794 fprintf(outfile,"Number of triggers where all chambers counted = %i\n",fTrigger44[cath]);
795 fprintf(outfile,"\n");
797 fprintf(outfile,"\n");
798 for(Int_t cath=0; cath<fgkNcathodes; cath++){
799 fprintf(outfile,"%s:\n",cathodeName[cath]);
800 for(Int_t ch=0; ch<fgkNchambers; ch++){
801 fprintf(outfile,"Number of triggers where chamber 1%i did not count = %i\n",ch+1,fTrigger34[ch][cath]);
803 fprintf(outfile,"\n");
806 fprintf(outfile,"\n");
807 for(Int_t cath=0; cath<fgkNcathodes; cath++){
808 fprintf(outfile,"%s:\n",cathodeName[cath]);
809 for(Int_t ch=0; ch<fgkNchambers; ch++){
810 Int_t sumIneff = 0, sumHits = 0;
811 fprintf(outfile,"\n Chamber %1i\n", ch+1);
812 for(Int_t slat=0; slat<fgkNslats; slat++){
813 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]);
814 sumIneff += fInefficientSlat[ch][cath][slat];
815 sumHits += fHitPerSlat[ch][cath][slat];
817 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);
819 fprintf(outfile,"\n");
823 sprintf(outFileName, "%s/triggerChamberEff.root",outputDir);
824 TFile *outputHistoFile = new TFile(outFileName,"RECREATE");
825 TDirectory *dir = gDirectory;
827 enum {kSlatIn11, kSlatIn12, kSlatIn13, kSlatIn14, kChamberEff};
828 char *yAxisTitle = "trigger efficiency (a.u.)";
829 char *xAxisTitle = "chamber";
831 TH1F *histo[fgkNcathodes][fgkNchambers+1];
832 TH1F *histoBoard[fgkNcathodes][fgkNchambers];
837 for(Int_t cath=0; cath<fgkNcathodes; cath++){
838 for(Int_t ch=0; ch<fgkNchambers+1; ch++){
840 sprintf(histoName, "%sChamberEff", cathCode[cath]);
841 sprintf(histoTitle, "Chamber efficiency %s", cathCode[cath]);
842 histo[cath][ch] = new TH1F(histoName, histoTitle, fgkNchambers, 11-0.5, 15-0.5);
843 histo[cath][ch]->SetXTitle(xAxisTitle);
844 histo[cath][ch]->SetYTitle(yAxisTitle);
845 histo[cath][ch]->GetXaxis()->SetNdivisions(fgkNchambers);
848 sprintf(histoName, "%sSlatEffChamber%i", cathCode[cath], 11+ch);
849 sprintf(histoTitle, "Chamber %i: slat efficiency %s", 11+ch, cathCode[cath]);
850 histo[cath][ch] = new TH1F(histoName, histoTitle, fgkNslats, 0-0.5, fgkNslats-0.5);
851 histo[cath][ch]->SetXTitle("slat");
852 histo[cath][ch]->SetYTitle(yAxisTitle);
853 histo[cath][ch]->GetXaxis()->SetNdivisions(fgkNslats);
855 sprintf(histoName, "%sBoardEffChamber%i", cathCode[cath], 11+ch);
856 sprintf(histoTitle, "Chamber %i: board efficiency %s", 11+ch, cathCode[cath]);
857 histoBoard[cath][ch] = new TH1F(histoName, histoTitle, fgkNboards, 1-0.5, fgkNboards+1.-0.5);
858 histoBoard[cath][ch]->SetXTitle("boards");
859 histoBoard[cath][ch]->SetYTitle(yAxisTitle);
860 histoBoard[cath][ch]->GetXaxis()->SetNdivisions(fgkNboards);
865 Float_t efficiency, efficiencyError;
867 for(Int_t cath=0; cath<fgkNcathodes; cath++){
868 for(Int_t ch=0; ch<fgkNchambers; ch++){
869 for(Int_t slat=0; slat<fgkNslats; slat++){
870 CalculateEfficiency(fHitPerSlat[ch][cath][slat], fHitPerSlat[ch][cath][slat]+fInefficientSlat[ch][cath][slat], efficiency, efficiencyError, kFALSE);
871 histo[cath][ch]->SetBinContent(slat+1, efficiency);
872 histo[cath][ch]->SetBinError(slat+1, efficiencyError);
874 CalculateEfficiency(fTrigger44[cath], fTrigger34[ch][cath]+fTrigger44[cath], efficiency, efficiencyError, kFALSE);
875 histo[cath][kChamberEff]->SetBinContent(ch+1, efficiency);
876 histo[cath][kChamberEff]->SetBinError(ch+1, efficiencyError);
878 for(Int_t board=0; board<fgkNboards; board++){
879 CalculateEfficiency(fHitPerBoard[ch][cath][board], fHitPerBoard[ch][cath][board]+fInefficientBoard[ch][cath][board], efficiency, efficiencyError, kFALSE);
880 histoBoard[cath][ch]->SetBinContent(board+1, efficiency);
881 histoBoard[cath][ch]->SetBinError(board+1, efficiencyError);
887 outputHistoFile->cd();
888 dir->GetList()->Write();
889 outputHistoFile->Close();
893 //_____________________________________________________________________________
894 void AliMUONTriggerChamberEff::WriteEfficiencyMap(const char* outputDir)
897 /// Writes the calculated efficiency in the text file efficiencyCells.dat
899 /// The file can be further put in $ALICE_ROOT/MUON/data
900 /// and used to run simulations with measured trigger chamber efficiencies.
905 Float_t efficiency, efficiencyError;
907 Int_t aCapo[] = {16, 38, 60, 76, 92, 108, 117, 133, 155, 177, 193, 209, 225, 234};
910 sprintf(filename, "%s/efficiencyCells.dat", outputDir);
911 ofstream outFile(filename);
912 outFile << "localBoards" << endl;
913 for(Int_t ch=0; ch<fgkNchambers; ch++){
915 outFile << "\n\ndetElemId:\t" << 11+ch;
917 for(Int_t cath=0; cath<fgkNcathodes; cath++){
918 outFile << "\n cathode:\t" << cath << endl;
920 for(Int_t board=0; board<fgkNboards; board++){
922 if(board==aCapo[currLine]){
926 CalculateEfficiency(fHitPerBoard[ch][cath][board], fHitPerBoard[ch][cath][board]+fInefficientBoard[ch][cath][board], efficiency, efficiencyError, kFALSE);
927 outFile << " " << setw(effOutWidth) << efficiency;