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 // Manager and of geomety classes for set: TPC //
21 // !sectors are numbered from 0 //
22 // !pad rows are numbered from 0 //
24 // 12.6. changed z relative
25 // Origin: Marian Ivanov, Uni. of Bratislava, ivanov@fmph.uniba.sk //
27 ///////////////////////////////////////////////////////////////////////
31 #include <AliTPCParam.h>
33 #include <TGeoManager.h>
34 #include <TGeoPhysicalNode.h>
36 #include "AliAlignObj.h"
37 #include "AliAlignObjParams.h"
39 #include "TGraphErrors.h"
40 #include "AliTPCcalibDB.h"
41 #include "AliTPCROC.h"
42 #include "AliMathBase.h"
44 TObjArray *AliTPCParam::fBBParam = 0;
49 //___________________________________________
50 AliTPCParam::AliTPCParam()
74 fNInnerWiresPerPad(0),
81 fNOuter1WiresPerPad(0),
82 fNOuter2WiresPerPad(0),
88 fInnerPadPitchLength(0.),
89 fInnerPadPitchWidth(0.),
92 fOuter1PadPitchLength(0.),
93 fOuter2PadPitchLength(0.),
94 fOuterPadPitchWidth(0.),
98 fBMWPCReadout(kFALSE),
119 fGainSlopesHV(0), // graph with the gain slope as function of HV - per chamber
120 fGainSlopesPT(0), // graph with the gain slope as function of P/T - per chamber
135 fMaxVoltageDeviation(40.),
137 fMaxHVfractionBad(.4),
138 fVoltageDipScanPeriod(1.),
140 fResponseThreshold(0.),
150 //constructor sets the default parameters
153 SetTitle("75x40_100x60_150x60");
155 if (!fBBParam) fBBParam= new TObjArray(1000);
158 AliTPCParam::~AliTPCParam()
161 //destructor deletes some dynamicaly alocated variables
164 if (fResponseBin!=0) delete [] fResponseBin;
165 if (fResponseWeight!=0) delete [] fResponseWeight;
166 if (fRotAngle !=0) delete [] fRotAngle;
172 Int_t AliTPCParam::Transform0to1(Float_t *xyz, Int_t * index) const
175 // calculates sector number (index[1], undefined on input)
181 Float_t r = TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
182 if ((xyz[0]==0)&&(xyz[1]==0)) angle = 0.;
185 angle =TMath::ASin(xyz[1]/r);
186 if (xyz[0]<0) angle=TMath::Pi()-angle;
187 if ( (xyz[0]>0) && (xyz[1]<0) ) angle=2*TMath::Pi()+angle;
190 sector=Int_t(TMath::Nint((angle-fInnerAngleShift)/fInnerAngle));
193 AdjustCosSin(sector,cos,sin);
194 x1=xyz[0]*cos + xyz[1]*sin;
196 if (x1>fOuterRadiusLow)
198 sector=Int_t(TMath::Nint((angle-fOuterAngleShift)/fOuterAngle))+fNInnerSector;
199 if (xyz[2]<0) sector+=(fNOuterSector>>1);
202 if (xyz[2]<0) sector+=(fNInnerSector>>1);
203 if (sector<0 || sector>=fNSector) AliError(Form("Wrong sector %d",sector));
204 index[1]=sector; // calculated sector number
205 index[0]=1; // indicates system after transformation
209 Bool_t AliTPCParam::Transform(Float_t */*xyz*/, Int_t *index, Int_t* /*oindex*/)
211 //transformation from input coodination system to output coordination system
221 Int_t AliTPCParam::GetPadRow(Float_t *xyz, Int_t *index) const
224 //calculates pad row of point xyz - transformation to system 8 (digit system)
226 Int_t system = index[0];
228 Transform0to1(xyz,index);
232 Transform1to2(xyz,index);
236 if (fGeometryType==0){ //straight row
238 Transform2to3(xyz,index);
242 Transform3to4(xyz,index);
246 Transform4to8(xyz,index);
255 if (fGeometryType==1){ //cylindrical geometry
257 Transform2to5(xyz,index);
261 Transform2to3(xyz,index);
265 Transform3to4(xyz,index);
274 return -1; //if no reasonable system
277 void AliTPCParam::SetSectorAngles(Float_t innerangle, Float_t innershift, Float_t outerangle,
281 // set opening angles
282 static const Float_t kDegtoRad = 0.01745329251994;
283 fInnerAngle = innerangle; //opening angle of Inner sector
284 fInnerAngleShift = innershift; //shift of first inner sector center to the 0
285 fOuterAngle = outerangle; //opening angle of outer sector
286 fOuterAngleShift = outershift; //shift of first sector center to the 0
287 fInnerAngle *=kDegtoRad;
288 fInnerAngleShift *=kDegtoRad;
289 fOuterAngle *=kDegtoRad;
290 fOuterAngleShift *=kDegtoRad;
293 Float_t AliTPCParam::GetInnerAngle() const
300 Float_t AliTPCParam::GetInnerAngleShift() const
303 return fInnerAngleShift;
305 Float_t AliTPCParam::GetOuterAngle() const
310 Float_t AliTPCParam::GetOuterAngleShift() const
314 return fOuterAngleShift;
318 Int_t AliTPCParam::GetIndex(Int_t sector, Int_t row) const
321 //give index of the given sector and pad row
322 //no control if the sectors and rows are reasonable !!!
324 if (sector<fNInnerSector) return sector*fNRowLow+row;
325 return (fNInnerSector*fNRowLow)+(sector-fNInnerSector)*fNRowUp+row;
328 Bool_t AliTPCParam::AdjustSectorRow(Int_t index, Int_t & sector, Int_t &row) const
331 //return sector and padrow for given index
332 //if index is reasonable returns true else return false
334 if ( (index<0) || (index>fNtRows)) return kFALSE;
335 Int_t outindex = fNInnerSector*fNRowLow;
336 if (index<outindex) {
337 sector = index/fNRowLow;
338 row = index - sector*fNRowLow;
342 sector = index/fNRowUp;
343 row = index - sector*fNRowUp;
344 sector += fNInnerSector;
348 void AliTPCParam::SetDefault()
351 //set default parameters
353 //const static Int_t kMaxRows=600;
355 //sector default parameters
357 static const Float_t kInnerRadiusLow = 83.65;
358 static const Float_t kInnerRadiusUp = 133.3;
359 static const Float_t kOuterRadiusLow = 133.5;
360 static const Float_t kOuterRadiusUp = 247.7;
361 static const Float_t kInnerAngle = 20; // 20 degrees
362 static const Float_t kInnerAngleShift = 10;
363 static const Float_t kOuterAngle = 20; // 20 degrees
364 static const Float_t kOuterAngleShift = 10;
365 static const Float_t kInnerFrameSpace = 1.5;
366 static const Float_t kOuterFrameSpace = 1.5;
367 static const Float_t kInnerWireMount = 1.2;
368 static const Float_t kOuterWireMount = 1.4;
369 static const Float_t kZLength =250.;
370 static const Int_t kGeometryType = 0; //straight rows
371 static const Int_t kNRowLow = 63;
372 static const Int_t kNRowUp1 = 64;
373 static const Int_t kNRowUp2 = 32;
374 static const Int_t kNRowUp = 96;
376 //wires default parameters
378 static const Int_t kNInnerWiresPerPad = 3;
379 static const Int_t kInnerDummyWire = 2;
380 static const Float_t kInnerWWPitch = 0.25;
381 static const Float_t kRInnerFirstWire = 84.475;
382 static const Float_t kRInnerLastWire = 132.475;
383 static const Float_t kInnerOffWire = 0.5;
384 static const Int_t kNOuter1WiresPerPad = 4;
385 static const Int_t kNOuter2WiresPerPad = 6;
386 static const Float_t kOuterWWPitch = 0.25;
387 static const Float_t kROuterFirstWire = 134.225;
388 static const Float_t kROuterLastWire = 246.975;
389 static const Int_t kOuterDummyWire = 2;
390 static const Float_t kOuterOffWire = 0.5;
392 //pad default parameters
394 static const Float_t kInnerPadPitchLength = 0.75;
395 static const Float_t kInnerPadPitchWidth = 0.40;
396 static const Float_t kInnerPadLength = 0.75;
397 static const Float_t kInnerPadWidth = 0.40;
398 static const Float_t kOuter1PadPitchLength = 1.0;
399 static const Float_t kOuterPadPitchWidth = 0.6;
400 static const Float_t kOuter1PadLength = 1.0;
401 static const Float_t kOuterPadWidth = 0.6;
402 static const Float_t kOuter2PadPitchLength = 1.5;
403 static const Float_t kOuter2PadLength = 1.5;
405 static const Bool_t kBMWPCReadout = kTRUE; //MWPC readout - another possibility GEM
406 static const Int_t kNCrossRows = 1; //number of rows to cross-talk
409 //gas default parameters
411 static const Float_t kDiffT = 2.2e-2;
412 static const Float_t kDiffL = 2.2e-2;
413 static const Float_t kGasGain = 2.e4;
414 static const Float_t kDriftV =2.83e6;
415 static const Float_t kOmegaTau = 0.145;
416 static const Float_t kAttCoef = 250.;
417 static const Float_t kOxyCont = 5.e-6;
418 static const Float_t kFpot = 22.77e-9;
419 static const Float_t kNprim=14.35;
420 static const Float_t kNtot=42.66;
421 static const Float_t kWmean = 35.97e-9;
422 static const Float_t kExp = 2.2;
423 static const Float_t kEend = 10.e-6;
425 //electronic default parameters
427 static const Float_t kPadCoupling=0.5;
428 static const Int_t kZeroSup=2;
429 static const Float_t kNoise = 1000;
430 static const Float_t kChipGain = 12;
431 static const Float_t kChipNorm = 0.4;
432 static const Float_t kTSample = 2.e-7;
433 static const Float_t kTFWHM = 1.9e-7; //fwhm of charge distribution
434 static const Int_t kMaxTBin =445;
435 static const Int_t kADCSat =1024;
436 static const Float_t kADCDynRange =2000.;
440 static const Int_t kNResponseMax=100;
441 static const Float_t kResponseThreshold=0.01;
443 // static const Float_t kGateDelay=6.1e-6; //In s
444 static const Float_t kGateDelay=0.; //For the moment no gating
445 // static const Float_t kL1Delay=6.5e-6; //In s
446 static const Float_t kL1Delay=0.; //For the moment no delay
447 // static const UShort_t kNTBinsBeforeL1=14;
448 static const UShort_t kNTBinsBeforeL1=0; //For the moment no shift
451 //set sector parameters
453 SetInnerRadiusLow(kInnerRadiusLow);
454 SetOuterRadiusLow(kOuterRadiusLow);
455 SetInnerRadiusUp(kInnerRadiusUp);
456 SetOuterRadiusUp(kOuterRadiusUp);
457 SetInnerFrameSpace(kInnerFrameSpace);
458 SetOuterFrameSpace(kOuterFrameSpace);
459 SetInnerWireMount(kInnerWireMount);
460 SetOuterWireMount(kOuterWireMount);
461 SetSectorAngles(kInnerAngle,kInnerAngleShift,kOuterAngle,kOuterAngleShift);
462 SetZLength(kZLength);
463 SetGeometryType(kGeometryType);
464 SetRowNLow(kNRowLow);
465 SetRowNUp1 (kNRowUp1);
466 SetRowNUp2(kNRowUp2);
469 //set wire parameters
471 SetInnerNWires(kNInnerWiresPerPad);
472 SetInnerDummyWire(kInnerDummyWire);
473 SetInnerOffWire(kInnerOffWire);
474 SetOuter1NWires(kNOuter1WiresPerPad);
475 SetOuter2NWire(kNOuter2WiresPerPad);
476 SetOuterDummyWire(kOuterDummyWire);
477 SetOuterOffWire(kOuterOffWire);
478 SetInnerWWPitch(kInnerWWPitch);
479 SetRInnerFirstWire(kRInnerFirstWire);
480 SetRInnerLastWire(kRInnerLastWire);
481 SetOuterWWPitch(kOuterWWPitch);
482 SetROuterFirstWire(kROuterFirstWire);
483 SetROuterLastWire(kROuterLastWire);
487 SetInnerPadPitchLength(kInnerPadPitchLength);
488 SetInnerPadPitchWidth(kInnerPadPitchWidth);
489 SetInnerPadLength(kInnerPadLength);
490 SetInnerPadWidth(kInnerPadWidth);
491 SetOuter1PadPitchLength(kOuter1PadPitchLength);
492 SetOuter2PadPitchLength(kOuter2PadPitchLength);
493 SetOuterPadPitchWidth(kOuterPadPitchWidth);
494 SetOuter1PadLength(kOuter1PadLength);
495 SetOuter2PadLength(kOuter2PadLength);
496 SetOuterPadWidth(kOuterPadWidth);
497 SetMWPCReadout(kBMWPCReadout);
498 SetNCrossRows(kNCrossRows);
504 SetGasGain(kGasGain);
506 SetOmegaTau(kOmegaTau);
507 SetAttCoef(kAttCoef);
508 SetOxyCont(kOxyCont);
516 SetComposition(0.9,0.,0.1,0.,0.,0.);// Ne-CO2 90/10
518 SetBetheBloch(GetBetheBlochParamAlice());
520 //set electronivc parameters
522 SetPadCoupling(kPadCoupling);
523 SetZeroSup(kZeroSup);
525 SetChipGain(kChipGain);
526 SetChipNorm(kChipNorm);
527 SetTSample(kTSample);
529 SetMaxTBin(kMaxTBin);
531 SetADCDynRange(kADCDynRange);
532 for (UInt_t i=0; i<36; i++)
534 SetNominalVoltage(1196.0, i);
536 for (UInt_t i=36; i<72; i++)
538 SetNominalVoltage(1417.0, i);
540 // //set magnetic field
541 // SetBField(kBField);
542 // SetNPrimLoss(kNPrimLoss);
543 // SetNTotalLoss(kNTotalLoss);
545 //set response parameters
547 SetNResponseMax(kNResponseMax);
548 SetResponseThreshold(static_cast<int>(kResponseThreshold));
550 SetGateDelay(kGateDelay);
551 SetL1Delay(kL1Delay);
552 SetNTBinsBeforeL1(kNTBinsBeforeL1);
553 SetNominalGainSlopes();
557 Bool_t AliTPCParam::Update()
560 // update some calculated parameter which must be updated after changing "base"
562 // for example we can change size of pads and according this recalculate number
563 // of pad rows, number of of pads in given row ....
565 const Float_t kQel = 1.602e-19; // elementary charge
568 Int_t i,j; //loop variables because HP
569 //-----------------Sector section------------------------------------------
570 //calclulate number of sectors
571 fNInnerSector = Int_t(4*TMath::Pi()/fInnerAngle+0.2);
572 // number of inner sectors - factor 0.2 to don't be influnced by inprecision
573 if (fNInnerSector%2) return kFALSE;
574 fNOuterSector = Int_t(4*TMath::Pi()/fOuterAngle+0.2);
575 if (fNOuterSector%2) return kFALSE;
576 fNSector = fNInnerSector+fNOuterSector;
578 if (fRotAngle!=0) delete [] fRotAngle;
579 fRotAngle = new Float_t[4*fNSector];
580 //calculate sin and cosine of rotations angle
581 //sectors angles numbering from 0
584 Float_t angle = fInnerAngleShift;
585 for (i=0; j<fNInnerSector*4; i+=4, j+=4 , angle +=fInnerAngle){
586 fRotAngle[i]=TMath::Cos(angle);
587 fRotAngle[i+1]=TMath::Sin(angle);
588 fRotAngle[j] = fRotAngle[i];
589 fRotAngle[j+1] = fRotAngle[i+1];
590 fRotAngle[i+2] =angle;
591 fRotAngle[j+2] =angle;
593 angle = fOuterAngleShift;
594 j=(fNInnerSector+fNOuterSector/2)*4;
595 for (i=fNInnerSector*4; j<fNSector*4; i+=4,j+=4, angle +=fOuterAngle){
596 fRotAngle[i]=TMath::Cos(angle);
597 fRotAngle[i+1]=TMath::Sin(angle);
598 fRotAngle[j] = fRotAngle[i];
599 fRotAngle[j+1] = fRotAngle[i+1];
600 fRotAngle[i+2] =angle;
601 fRotAngle[j+2] =angle;
604 fZWidth = fTSample*fDriftV;
605 fTotalNormFac = fPadCoupling*fChipNorm*kQel*1.e15*fChipGain*fADCSat/fADCDynRange;
606 fNoiseNormFac = kQel*1.e15*fChipGain*fADCSat/fADCDynRange;
609 Float_t wspace; //available space for wire
610 Float_t dummyspace; //dummyspace for wire
612 wspace =fInnerRadiusUp-fInnerRadiusLow-2*fInnerOffWire;
613 nwire = Int_t(wspace/fInnerWWPitch);
614 wspace = Float_t(nwire)*fInnerWWPitch;
615 dummyspace =(fInnerRadiusUp-fInnerRadiusLow-wspace)/2.;
616 wspace =fOuterRadiusUp-fOuterRadiusLow-2*fOuterOffWire;
617 nwire = Int_t(wspace/fOuterWWPitch);
618 wspace = Float_t(nwire)*fOuterWWPitch;
619 dummyspace =(fOuterRadiusUp-fOuterRadiusLow-wspace)/2.;
620 fROuterFirstWire = fOuterRadiusLow+dummyspace;
621 fROuterLastWire = fROuterFirstWire+fOuterWWPitch*(Float_t)(nwire);
627 if (fResponseBin) delete [] fResponseBin;
628 if (fResponseWeight) delete [] fResponseWeight;
629 fResponseBin = new Int_t[3*fNResponseMax];
630 fResponseWeight = new Float_t[fNResponseMax];
633 fNTBinsL1 = fL1Delay/fTSample - (Float_t)fNTBinsBeforeL1;
638 void AliTPCParam::CleanGeoMatrices(){
640 // clean geo matrices
643 if (fTrackingMatrix) {
644 for(Int_t i = 0; i < fNSector; i++)
645 delete fTrackingMatrix[i];
646 delete [] fTrackingMatrix;
649 if (fClusterMatrix) {
650 for(Int_t i = 0; i < fNSector; i++)
651 delete fClusterMatrix[i];
652 delete [] fClusterMatrix;
656 for(Int_t i = 0; i < fNSector; i++)
657 delete fGlobalMatrix[i];
658 delete [] fGlobalMatrix;
664 Bool_t AliTPCParam::ReadGeoMatrices(){
669 AliFatal("Geo manager not initialized\n");
674 // clean geo matrices
677 // create new geo matrices
678 fTrackingMatrix = new TGeoHMatrix*[fNSector];
679 fClusterMatrix = new TGeoHMatrix*[fNSector];
680 fGlobalMatrix = new TGeoHMatrix*[fNSector];
681 for (Int_t isec=0; isec<fNSector; isec++) {
682 fGlobalMatrix[isec] = 0;
683 fClusterMatrix[isec]= 0;
684 fTrackingMatrix[isec]=0;
687 for (Int_t isec=0; isec<fNSector; isec++) {
688 fGlobalMatrix[isec] = 0;
689 fClusterMatrix[isec]= 0;
690 fTrackingMatrix[isec]=0;
691 AliGeomManager::ELayerID iLayer;
694 if(isec<fNInnerSector) {
695 iLayer = AliGeomManager::kTPC1;
699 iLayer = AliGeomManager::kTPC2;
700 iModule = isec - fNInnerSector;
703 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,iModule);
704 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(volid);
707 AliError(Form("Alignable entry for volume ID %d not in geometry. Exiting!",volid));
710 const char *path = pne->GetTitle();
711 if (!gGeoManager->cd(path)) return kFALSE;
712 TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
713 // Since GEANT4 does not allow reflections, in this case the reflection
714 // component if the matrix is embedded by TGeo inside TGeoScaledShape
715 if (gGeoManager->GetCurrentVolume()->GetShape()->IsReflected())
716 m->ReflectZ(kFALSE, kTRUE);
718 TGeoRotation mchange;
719 mchange.RotateY(90); mchange.RotateX(90);
720 Float_t ROCcenter[3];
721 GetChamberCenter(isec,ROCcenter);
723 // Convert to global coordinate system
725 fGlobalMatrix[isec] = new TGeoHMatrix(*m);
726 fGlobalMatrix[isec]->Multiply(&(mchange.Inverse()));
727 TGeoTranslation center("center",-ROCcenter[0],-ROCcenter[1],-ROCcenter[2]);
728 fGlobalMatrix[isec]->Multiply(¢er);
730 // cluster correction matrix
732 fClusterMatrix[isec] = new TGeoHMatrix;
733 Double_t sectorAngle = 20.*(isec%18)+10;
734 TGeoHMatrix rotMatrix;
735 rotMatrix.RotateZ(sectorAngle);
736 if (GetGlobalMatrix(isec)->GetTranslation()[2]>0){
740 TGeoRotation mirrorZ;
741 mirrorZ.SetAngles(90,0,90,90,180,0);
742 fClusterMatrix[isec]->Multiply(&mirrorZ);
744 TGeoTranslation trans(0,0,GetZLength(isec));
745 fClusterMatrix[isec]->MultiplyLeft(&trans);
746 fClusterMatrix[isec]->MultiplyLeft((GetGlobalMatrix(isec)));
747 fClusterMatrix[isec]->MultiplyLeft(&(rotMatrix.Inverse()));
752 TGeoHMatrix * AliTPCParam::Tracking2LocalMatrix(const TGeoHMatrix * geoMatrix, Int_t sector) const{
754 // make local to tracking matrix
756 Double_t sectorAngle = 20.*(sector%18)+10;
757 TGeoHMatrix *newMatrix = new TGeoHMatrix();
758 newMatrix->RotateZ(sectorAngle);
759 newMatrix->MultiplyLeft(&(geoMatrix->Inverse()));
766 Bool_t AliTPCParam::GetStatus() const
768 //get information about object consistency
772 Int_t AliTPCParam::GetNRowLow() const
774 //get the number of pad rows in low sector
777 Int_t AliTPCParam::GetNRowUp() const
779 //get the number of pad rows in up sector
782 Int_t AliTPCParam::GetNRowUp1() const
784 //get the number of pad rows in up1 sector
787 Int_t AliTPCParam::GetNRowUp2() const
789 //get the number of pad rows in up2 sector
792 Float_t AliTPCParam::GetPadRowRadiiLow(Int_t irow) const
794 //get the pad row (irow) radii
795 if ( !(irow<0) && (irow<fNRowLow) )
796 return fPadRowLow[irow];
801 Float_t AliTPCParam::GetPadRowRadiiUp(Int_t irow) const
803 //get the pad row (irow) radii
804 if ( !(irow<0) && (irow<fNRowUp) )
805 return fPadRowUp[irow];
810 Int_t AliTPCParam::GetNPadsLow(Int_t irow) const
812 //get the number of pads in row irow
813 if ( !(irow<0) && (irow<fNRowLow) )
814 return fNPadsLow[irow];
820 Int_t AliTPCParam::GetNPadsUp(Int_t irow) const
822 //get the number of pads in row irow
823 if ( !(irow<0) && (irow<fNRowUp) )
824 return fNPadsUp[irow];
829 Int_t AliTPCParam::GetWireSegment(Int_t sector, Int_t row) const
832 // Get Anode wire segment index IROC --> 4 segments in [0,3], 7 segments OROC[4,10]
834 // To be speed-up using caching lookup table
836 Int_t wireIndex = -1;
837 // check if the given set of sector and row is OK
838 if ( (sector<0 || sector>=72) || (row<0 || row>95) || (sector<36 && row>64) ){
839 AliError("No matching anode wire segment for this set of sector-row \n");
842 // find the wire index for given sector-row
843 if ( sector<36 ){ // IROC anode wire segments
844 if (row<16) wireIndex=0;
845 else if (row>=16 && row<32) wireIndex=1;
846 else if (row>=32 && row<48) wireIndex=2;
848 } else { // OROC anode wire segments
849 if (row<16) wireIndex=4;
850 else if ( row>=16 && row<32) wireIndex=5;
851 else if ( row>=32 && row<48) wireIndex=6;
852 else if ( row>=48 && row<64) wireIndex=7;
853 else if ( row>=64 && row<75) wireIndex=8;
854 else if ( row>=75 && row<85) wireIndex=9;
860 Int_t AliTPCParam::GetNPadsPerSegment(Int_t wireSegmentID) const
863 // Get the number of pads in a given anode wire segment
865 // check if the given segment index is OK
866 // To be done (if needed) - cache the lookup table
868 if ( wireSegmentID<0 || wireSegmentID>10 ){
869 AliError("Wrong anode wire segment index. it should be [0,10] \n");
872 // get sector type from wireSegmentID
873 Int_t sector = (wireSegmentID<4) ? 0 : 36; // ROC [0,35] --> IROC, ROC [36,71] --> OROC
874 // get the upper and lower row number for the given wireSegmentID
875 Int_t segRowDown = 0;
878 if ( wireSegmentID == 0 || wireSegmentID == 4 ) {
881 } else if ( wireSegmentID == 1 || wireSegmentID == 5 ) {
884 } else if ( wireSegmentID == 2 || wireSegmentID == 6 ) {
887 } else if ( wireSegmentID == 3 || wireSegmentID == 7 ) {
890 } else if ( wireSegmentID == 8 ) {
893 } else if ( wireSegmentID == 9 ) {
900 // count the number of pads on the given segment
901 AliTPCROC *r=AliTPCROC::Instance();
903 for (Int_t irow = segRowDown; irow < segRowUp ; irow++){
904 nPads += r->GetNPads(sector,irow);
909 Float_t AliTPCParam::GetYInner(Int_t irow) const
911 return fYInner[irow];
915 Float_t AliTPCParam::GetYOuter(Int_t irow) const
917 return fYOuter[irow];
920 Int_t AliTPCParam::GetSectorIndex(Float_t angle, Int_t row, Float_t z) const
922 // returns the sector index
923 // takes as input the angle, index of the pad row and z position
926 if (angle > 2.*TMath::Pi()) angle -= 2.*TMath::Pi();
927 if (angle < 0. ) angle += 2.*TMath::Pi();
931 sector=Int_t(TMath::Nint((angle-fInnerAngleShift)/fInnerAngle));
932 if (z<0) sector += (fNInnerSector>>1);
935 sector=Int_t(TMath::Nint((angle-fOuterAngleShift)/fOuterAngle))+fNInnerSector;
936 if (z<0) sector += (fNOuterSector>>1);
942 Float_t AliTPCParam::GetChamberCenter(Int_t isec, Float_t * center) const
944 // returns the default radial position
945 // of the readout chambers
947 const Float_t kROCcenterIn = 110.2;
948 const Float_t kROCcenterOut = 188.45;
950 if (isec<fNInnerSector){
952 center[0] = kROCcenterIn;
954 center[2] = -5.51-0.08;
960 center[0] = kROCcenterOut;
962 center[2] = -5.61-0.08;
964 return kROCcenterOut;
968 void AliTPCParam::SetNominalGainSlopes(){
970 // Setting the nominal TPC gain slopes
971 // Nominal values were obtained as a mena values foe 2010,2011, and 2012 data
972 // Differntial values can be provided per year
974 Float_t sector[72]={0};
975 Float_t gainHV[72]={0};
976 Float_t gainPT[72]={0};
978 for (Int_t isec=0; isec<72; isec++){
980 gainHV[isec]=0.0115; // change of the Gain dG/G per 1 Volt of voltage change(1/V) - it is roughly the same for IROC and OROC
981 gainPT[isec]=2.2; // change of the Gains dG/G per P/T change ()
983 fGainSlopesHV = new TGraphErrors(72,sector,gainHV,0,0);
984 fGainSlopesPT = new TGraphErrors(72,sector,gainPT,0,0);
985 fGainSlopesHV->SetName("GainSlopesHV");
986 fGainSlopesPT->SetName("GainSlopesPT");
990 TVectorD * AliTPCParam::GetBetheBlochParamNa49(){
992 // Parameters of the BB for the Aleph parametrization AliMathBase::BetheBlochAleph
993 // Na49 parameters were used as first set of parameters for ALICE simulation
994 // (see TPC TDR for details)
1001 return new TVectorD(v);
1004 TVectorD * AliTPCParam::GetBetheBlochParamAlice(){
1007 // Parameters of the BB for the Aleph parametrization AliMathBase::BetheBlochAleph
1008 // Na49 parameters were used as first set of parameters for ALICE simulation
1009 // Second set was obtained from ALICE 2009-2013 data taking
1010 // (see TPC TDR for details)
1018 return new TVectorD(v);
1022 Double_t AliTPCParam::BetheBlochAleph(Double_t bg, Int_t type){
1024 // GetBetheBloch retur values for the parametrs regieter at poition type
1025 // Used for visualization and comparison purposes
1026 TVectorD * paramBB =0;
1028 AliTPCParam* param = AliTPCcalibDB::Instance()->GetParameters();
1029 if (param) paramBB=param->GetBetheBlochParameters();
1032 paramBB = (TVectorD*)fBBParam->At(type);
1034 if (!paramBB) return 0;
1036 return AliMathBase::BetheBlochAleph(bg,(*paramBB)(0),(*paramBB)(1),(*paramBB)(2),(*paramBB)(3),(*paramBB)(4));
1040 void AliTPCParam::RegisterBBParam(TVectorD* param, Int_t position){
1044 fBBParam->AddAt(param,position);