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"
43 //___________________________________________
44 AliTPCParam::AliTPCParam()
68 fNInnerWiresPerPad(0),
75 fNOuter1WiresPerPad(0),
76 fNOuter2WiresPerPad(0),
82 fInnerPadPitchLength(0.),
83 fInnerPadPitchWidth(0.),
86 fOuter1PadPitchLength(0.),
87 fOuter2PadPitchLength(0.),
88 fOuterPadPitchWidth(0.),
92 fBMWPCReadout(kFALSE),
120 fMaxVoltageDeviation(40.),
122 fMaxHVfractionBad(.4),
123 fVoltageDipScanPeriod(1.),
125 fResponseThreshold(0.),
135 //constructor sets the default parameters
138 SetTitle("75x40_100x60_150x60");
142 AliTPCParam::~AliTPCParam()
145 //destructor deletes some dynamicaly alocated variables
148 if (fResponseBin!=0) delete [] fResponseBin;
149 if (fResponseWeight!=0) delete [] fResponseWeight;
150 if (fRotAngle !=0) delete [] fRotAngle;
156 Int_t AliTPCParam::Transform0to1(Float_t *xyz, Int_t * index) const
159 // calculates sector number (index[1], undefined on input)
165 Float_t r = TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
166 if ((xyz[0]==0)&&(xyz[1]==0)) angle = 0.;
169 angle =TMath::ASin(xyz[1]/r);
170 if (xyz[0]<0) angle=TMath::Pi()-angle;
171 if ( (xyz[0]>0) && (xyz[1]<0) ) angle=2*TMath::Pi()+angle;
174 sector=Int_t(TMath::Nint((angle-fInnerAngleShift)/fInnerAngle));
177 AdjustCosSin(sector,cos,sin);
178 x1=xyz[0]*cos + xyz[1]*sin;
180 if (x1>fOuterRadiusLow)
182 sector=Int_t(TMath::Nint((angle-fOuterAngleShift)/fOuterAngle))+fNInnerSector;
183 if (xyz[2]<0) sector+=(fNOuterSector>>1);
186 if (xyz[2]<0) sector+=(fNInnerSector>>1);
187 if (sector<0 || sector>=fNSector) AliError(Form("Wrong sector %d",sector));
188 index[1]=sector; // calculated sector number
189 index[0]=1; // indicates system after transformation
193 Bool_t AliTPCParam::Transform(Float_t */*xyz*/, Int_t *index, Int_t* /*oindex*/)
195 //transformation from input coodination system to output coordination system
205 Int_t AliTPCParam::GetPadRow(Float_t *xyz, Int_t *index) const
208 //calculates pad row of point xyz - transformation to system 8 (digit system)
210 Int_t system = index[0];
212 Transform0to1(xyz,index);
216 Transform1to2(xyz,index);
220 if (fGeometryType==0){ //straight row
222 Transform2to3(xyz,index);
226 Transform3to4(xyz,index);
230 Transform4to8(xyz,index);
239 if (fGeometryType==1){ //cylindrical geometry
241 Transform2to5(xyz,index);
245 Transform2to3(xyz,index);
249 Transform3to4(xyz,index);
258 return -1; //if no reasonable system
261 void AliTPCParam::SetSectorAngles(Float_t innerangle, Float_t innershift, Float_t outerangle,
265 // set opening angles
266 static const Float_t kDegtoRad = 0.01745329251994;
267 fInnerAngle = innerangle; //opening angle of Inner sector
268 fInnerAngleShift = innershift; //shift of first inner sector center to the 0
269 fOuterAngle = outerangle; //opening angle of outer sector
270 fOuterAngleShift = outershift; //shift of first sector center to the 0
271 fInnerAngle *=kDegtoRad;
272 fInnerAngleShift *=kDegtoRad;
273 fOuterAngle *=kDegtoRad;
274 fOuterAngleShift *=kDegtoRad;
277 Float_t AliTPCParam::GetInnerAngle() const
284 Float_t AliTPCParam::GetInnerAngleShift() const
287 return fInnerAngleShift;
289 Float_t AliTPCParam::GetOuterAngle() const
294 Float_t AliTPCParam::GetOuterAngleShift() const
298 return fOuterAngleShift;
302 Int_t AliTPCParam::GetIndex(Int_t sector, Int_t row) const
305 //give index of the given sector and pad row
306 //no control if the sectors and rows are reasonable !!!
308 if (sector<fNInnerSector) return sector*fNRowLow+row;
309 return (fNInnerSector*fNRowLow)+(sector-fNInnerSector)*fNRowUp+row;
312 Bool_t AliTPCParam::AdjustSectorRow(Int_t index, Int_t & sector, Int_t &row) const
315 //return sector and padrow for given index
316 //if index is reasonable returns true else return false
318 if ( (index<0) || (index>fNtRows)) return kFALSE;
319 Int_t outindex = fNInnerSector*fNRowLow;
320 if (index<outindex) {
321 sector = index/fNRowLow;
322 row = index - sector*fNRowLow;
326 sector = index/fNRowUp;
327 row = index - sector*fNRowUp;
328 sector += fNInnerSector;
332 void AliTPCParam::SetDefault()
335 //set default parameters
337 //const static Int_t kMaxRows=600;
339 //sector default parameters
341 static const Float_t kInnerRadiusLow = 83.65;
342 static const Float_t kInnerRadiusUp = 133.3;
343 static const Float_t kOuterRadiusLow = 133.5;
344 static const Float_t kOuterRadiusUp = 247.7;
345 static const Float_t kInnerAngle = 20; // 20 degrees
346 static const Float_t kInnerAngleShift = 10;
347 static const Float_t kOuterAngle = 20; // 20 degrees
348 static const Float_t kOuterAngleShift = 10;
349 static const Float_t kInnerFrameSpace = 1.5;
350 static const Float_t kOuterFrameSpace = 1.5;
351 static const Float_t kInnerWireMount = 1.2;
352 static const Float_t kOuterWireMount = 1.4;
353 static const Float_t kZLength =250.;
354 static const Int_t kGeometryType = 0; //straight rows
355 static const Int_t kNRowLow = 63;
356 static const Int_t kNRowUp1 = 64;
357 static const Int_t kNRowUp2 = 32;
358 static const Int_t kNRowUp = 96;
360 //wires default parameters
362 static const Int_t kNInnerWiresPerPad = 3;
363 static const Int_t kInnerDummyWire = 2;
364 static const Float_t kInnerWWPitch = 0.25;
365 static const Float_t kRInnerFirstWire = 84.475;
366 static const Float_t kRInnerLastWire = 132.475;
367 static const Float_t kInnerOffWire = 0.5;
368 static const Int_t kNOuter1WiresPerPad = 4;
369 static const Int_t kNOuter2WiresPerPad = 6;
370 static const Float_t kOuterWWPitch = 0.25;
371 static const Float_t kROuterFirstWire = 134.225;
372 static const Float_t kROuterLastWire = 246.975;
373 static const Int_t kOuterDummyWire = 2;
374 static const Float_t kOuterOffWire = 0.5;
376 //pad default parameters
378 static const Float_t kInnerPadPitchLength = 0.75;
379 static const Float_t kInnerPadPitchWidth = 0.40;
380 static const Float_t kInnerPadLength = 0.75;
381 static const Float_t kInnerPadWidth = 0.40;
382 static const Float_t kOuter1PadPitchLength = 1.0;
383 static const Float_t kOuterPadPitchWidth = 0.6;
384 static const Float_t kOuter1PadLength = 1.0;
385 static const Float_t kOuterPadWidth = 0.6;
386 static const Float_t kOuter2PadPitchLength = 1.5;
387 static const Float_t kOuter2PadLength = 1.5;
389 static const Bool_t kBMWPCReadout = kTRUE; //MWPC readout - another possibility GEM
390 static const Int_t kNCrossRows = 1; //number of rows to cross-talk
393 //gas default parameters
395 static const Float_t kDiffT = 2.2e-2;
396 static const Float_t kDiffL = 2.2e-2;
397 static const Float_t kGasGain = 2.e4;
398 static const Float_t kDriftV =2.83e6;
399 static const Float_t kOmegaTau = 0.145;
400 static const Float_t kAttCoef = 250.;
401 static const Float_t kOxyCont = 5.e-6;
403 //electronic default parameters
405 static const Float_t kPadCoupling=0.5;
406 static const Int_t kZeroSup=2;
407 static const Float_t kNoise = 1000;
408 static const Float_t kChipGain = 12;
409 static const Float_t kChipNorm = 0.4;
410 static const Float_t kTSample = 2.e-7;
411 static const Float_t kTFWHM = 1.9e-7; //fwhm of charge distribution
412 static const Int_t kMaxTBin =445;
413 static const Int_t kADCSat =1024;
414 static const Float_t kADCDynRange =2000.;
418 static const Int_t kNResponseMax=100;
419 static const Float_t kResponseThreshold=0.01;
421 // static const Float_t kGateDelay=6.1e-6; //In s
422 static const Float_t kGateDelay=0.; //For the moment no gating
423 // static const Float_t kL1Delay=6.5e-6; //In s
424 static const Float_t kL1Delay=0.; //For the moment no delay
425 // static const UShort_t kNTBinsBeforeL1=14;
426 static const UShort_t kNTBinsBeforeL1=0; //For the moment no shift
429 //set sector parameters
431 SetInnerRadiusLow(kInnerRadiusLow);
432 SetOuterRadiusLow(kOuterRadiusLow);
433 SetInnerRadiusUp(kInnerRadiusUp);
434 SetOuterRadiusUp(kOuterRadiusUp);
435 SetInnerFrameSpace(kInnerFrameSpace);
436 SetOuterFrameSpace(kOuterFrameSpace);
437 SetInnerWireMount(kInnerWireMount);
438 SetOuterWireMount(kOuterWireMount);
439 SetSectorAngles(kInnerAngle,kInnerAngleShift,kOuterAngle,kOuterAngleShift);
440 SetZLength(kZLength);
441 SetGeometryType(kGeometryType);
442 SetRowNLow(kNRowLow);
443 SetRowNUp1 (kNRowUp1);
444 SetRowNUp2(kNRowUp2);
447 //set wire parameters
449 SetInnerNWires(kNInnerWiresPerPad);
450 SetInnerDummyWire(kInnerDummyWire);
451 SetInnerOffWire(kInnerOffWire);
452 SetOuter1NWires(kNOuter1WiresPerPad);
453 SetOuter2NWire(kNOuter2WiresPerPad);
454 SetOuterDummyWire(kOuterDummyWire);
455 SetOuterOffWire(kOuterOffWire);
456 SetInnerWWPitch(kInnerWWPitch);
457 SetRInnerFirstWire(kRInnerFirstWire);
458 SetRInnerLastWire(kRInnerLastWire);
459 SetOuterWWPitch(kOuterWWPitch);
460 SetROuterFirstWire(kROuterFirstWire);
461 SetROuterLastWire(kROuterLastWire);
465 SetInnerPadPitchLength(kInnerPadPitchLength);
466 SetInnerPadPitchWidth(kInnerPadPitchWidth);
467 SetInnerPadLength(kInnerPadLength);
468 SetInnerPadWidth(kInnerPadWidth);
469 SetOuter1PadPitchLength(kOuter1PadPitchLength);
470 SetOuter2PadPitchLength(kOuter2PadPitchLength);
471 SetOuterPadPitchWidth(kOuterPadPitchWidth);
472 SetOuter1PadLength(kOuter1PadLength);
473 SetOuter2PadLength(kOuter2PadLength);
474 SetOuterPadWidth(kOuterPadWidth);
475 SetMWPCReadout(kBMWPCReadout);
476 SetNCrossRows(kNCrossRows);
482 SetGasGain(kGasGain);
484 SetOmegaTau(kOmegaTau);
485 SetAttCoef(kAttCoef);
486 SetOxyCont(kOxyCont);
488 //set electronivc parameters
490 SetPadCoupling(kPadCoupling);
491 SetZeroSup(kZeroSup);
493 SetChipGain(kChipGain);
494 SetChipNorm(kChipNorm);
495 SetTSample(kTSample);
497 SetMaxTBin(kMaxTBin);
499 SetADCDynRange(kADCDynRange);
500 for (UInt_t i=0; i<36; i++)
502 SetNominalVoltage(1196.0, i);
504 for (UInt_t i=36; i<72; i++)
506 SetNominalVoltage(1417.0, i);
508 // //set magnetic field
509 // SetBField(kBField);
510 // SetNPrimLoss(kNPrimLoss);
511 // SetNTotalLoss(kNTotalLoss);
513 //set response parameters
515 SetNResponseMax(kNResponseMax);
516 SetResponseThreshold(static_cast<int>(kResponseThreshold));
518 SetGateDelay(kGateDelay);
519 SetL1Delay(kL1Delay);
520 SetNTBinsBeforeL1(kNTBinsBeforeL1);
524 Bool_t AliTPCParam::Update()
527 // update some calculated parameter which must be updated after changing "base"
529 // for example we can change size of pads and according this recalculate number
530 // of pad rows, number of of pads in given row ....
532 const Float_t kQel = 1.602e-19; // elementary charge
535 Int_t i,j; //loop variables because HP
536 //-----------------Sector section------------------------------------------
537 //calclulate number of sectors
538 fNInnerSector = Int_t(4*TMath::Pi()/fInnerAngle+0.2);
539 // number of inner sectors - factor 0.2 to don't be influnced by inprecision
540 if (fNInnerSector%2) return kFALSE;
541 fNOuterSector = Int_t(4*TMath::Pi()/fOuterAngle+0.2);
542 if (fNOuterSector%2) return kFALSE;
543 fNSector = fNInnerSector+fNOuterSector;
545 if (fRotAngle!=0) delete [] fRotAngle;
546 fRotAngle = new Float_t[4*fNSector];
547 //calculate sin and cosine of rotations angle
548 //sectors angles numbering from 0
551 Float_t angle = fInnerAngleShift;
552 for (i=0; j<fNInnerSector*4; i+=4, j+=4 , angle +=fInnerAngle){
553 fRotAngle[i]=TMath::Cos(angle);
554 fRotAngle[i+1]=TMath::Sin(angle);
555 fRotAngle[j] = fRotAngle[i];
556 fRotAngle[j+1] = fRotAngle[i+1];
557 fRotAngle[i+2] =angle;
558 fRotAngle[j+2] =angle;
560 angle = fOuterAngleShift;
561 j=(fNInnerSector+fNOuterSector/2)*4;
562 for (i=fNInnerSector*4; j<fNSector*4; i+=4,j+=4, angle +=fOuterAngle){
563 fRotAngle[i]=TMath::Cos(angle);
564 fRotAngle[i+1]=TMath::Sin(angle);
565 fRotAngle[j] = fRotAngle[i];
566 fRotAngle[j+1] = fRotAngle[i+1];
567 fRotAngle[i+2] =angle;
568 fRotAngle[j+2] =angle;
571 fZWidth = fTSample*fDriftV;
572 fTotalNormFac = fPadCoupling*fChipNorm*kQel*1.e15*fChipGain*fADCSat/fADCDynRange;
573 fNoiseNormFac = kQel*1.e15*fChipGain*fADCSat/fADCDynRange;
576 Float_t wspace; //available space for wire
577 Float_t dummyspace; //dummyspace for wire
579 wspace =fInnerRadiusUp-fInnerRadiusLow-2*fInnerOffWire;
580 nwire = Int_t(wspace/fInnerWWPitch);
581 wspace = Float_t(nwire)*fInnerWWPitch;
582 dummyspace =(fInnerRadiusUp-fInnerRadiusLow-wspace)/2.;
583 wspace =fOuterRadiusUp-fOuterRadiusLow-2*fOuterOffWire;
584 nwire = Int_t(wspace/fOuterWWPitch);
585 wspace = Float_t(nwire)*fOuterWWPitch;
586 dummyspace =(fOuterRadiusUp-fOuterRadiusLow-wspace)/2.;
587 fROuterFirstWire = fOuterRadiusLow+dummyspace;
588 fROuterLastWire = fROuterFirstWire+fOuterWWPitch*(Float_t)(nwire);
594 if (fResponseBin) delete [] fResponseBin;
595 if (fResponseWeight) delete [] fResponseWeight;
596 fResponseBin = new Int_t[3*fNResponseMax];
597 fResponseWeight = new Float_t[fNResponseMax];
600 fNTBinsL1 = fL1Delay/fTSample - (Float_t)fNTBinsBeforeL1;
605 void AliTPCParam::CleanGeoMatrices(){
607 // clean geo matrices
610 if (fTrackingMatrix) {
611 for(Int_t i = 0; i < fNSector; i++)
612 delete fTrackingMatrix[i];
613 delete [] fTrackingMatrix;
616 if (fClusterMatrix) {
617 for(Int_t i = 0; i < fNSector; i++)
618 delete fClusterMatrix[i];
619 delete [] fClusterMatrix;
623 for(Int_t i = 0; i < fNSector; i++)
624 delete fGlobalMatrix[i];
625 delete [] fGlobalMatrix;
631 Bool_t AliTPCParam::ReadGeoMatrices(){
636 AliFatal("Geo manager not initialized\n");
641 // clean geo matrices
644 // create new geo matrices
645 fTrackingMatrix = new TGeoHMatrix*[fNSector];
646 fClusterMatrix = new TGeoHMatrix*[fNSector];
647 fGlobalMatrix = new TGeoHMatrix*[fNSector];
648 for (Int_t isec=0; isec<fNSector; isec++) {
649 fGlobalMatrix[isec] = 0;
650 fClusterMatrix[isec]= 0;
651 fTrackingMatrix[isec]=0;
654 for (Int_t isec=0; isec<fNSector; isec++) {
655 fGlobalMatrix[isec] = 0;
656 fClusterMatrix[isec]= 0;
657 fTrackingMatrix[isec]=0;
658 AliGeomManager::ELayerID iLayer;
661 if(isec<fNInnerSector) {
662 iLayer = AliGeomManager::kTPC1;
666 iLayer = AliGeomManager::kTPC2;
667 iModule = isec - fNInnerSector;
670 UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,iModule);
671 TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(volid);
674 AliError(Form("Alignable entry for volume ID %d not in geometry. Exiting!",volid));
677 const char *path = pne->GetTitle();
678 if (!gGeoManager->cd(path)) return kFALSE;
679 TGeoHMatrix *m = gGeoManager->GetCurrentMatrix();
680 // Since GEANT4 does not allow reflections, in this case the reflection
681 // component if the matrix is embedded by TGeo inside TGeoScaledShape
682 if (gGeoManager->GetCurrentVolume()->GetShape()->IsReflected())
683 m->ReflectZ(kFALSE, kTRUE);
685 TGeoRotation mchange;
686 mchange.RotateY(90); mchange.RotateX(90);
687 Float_t ROCcenter[3];
688 GetChamberCenter(isec,ROCcenter);
690 // Convert to global coordinate system
692 fGlobalMatrix[isec] = new TGeoHMatrix(*m);
693 fGlobalMatrix[isec]->Multiply(&(mchange.Inverse()));
694 TGeoTranslation center("center",-ROCcenter[0],-ROCcenter[1],-ROCcenter[2]);
695 fGlobalMatrix[isec]->Multiply(¢er);
697 // cluster correction matrix
699 fClusterMatrix[isec] = new TGeoHMatrix;
700 Double_t sectorAngle = 20.*(isec%18)+10;
701 TGeoHMatrix rotMatrix;
702 rotMatrix.RotateZ(sectorAngle);
703 if (GetGlobalMatrix(isec)->GetTranslation()[2]>0){
707 TGeoRotation mirrorZ;
708 mirrorZ.SetAngles(90,0,90,90,180,0);
709 fClusterMatrix[isec]->Multiply(&mirrorZ);
711 TGeoTranslation trans(0,0,GetZLength(isec));
712 fClusterMatrix[isec]->MultiplyLeft(&trans);
713 fClusterMatrix[isec]->MultiplyLeft((GetGlobalMatrix(isec)));
714 fClusterMatrix[isec]->MultiplyLeft(&(rotMatrix.Inverse()));
719 TGeoHMatrix * AliTPCParam::Tracking2LocalMatrix(const TGeoHMatrix * geoMatrix, Int_t sector) const{
721 // make local to tracking matrix
723 Double_t sectorAngle = 20.*(sector%18)+10;
724 TGeoHMatrix *newMatrix = new TGeoHMatrix();
725 newMatrix->RotateZ(sectorAngle);
726 newMatrix->MultiplyLeft(&(geoMatrix->Inverse()));
733 Bool_t AliTPCParam::GetStatus() const
735 //get information about object consistency
739 Int_t AliTPCParam::GetNRowLow() const
741 //get the number of pad rows in low sector
744 Int_t AliTPCParam::GetNRowUp() const
746 //get the number of pad rows in up sector
749 Int_t AliTPCParam::GetNRowUp1() const
751 //get the number of pad rows in up1 sector
754 Int_t AliTPCParam::GetNRowUp2() const
756 //get the number of pad rows in up2 sector
759 Float_t AliTPCParam::GetPadRowRadiiLow(Int_t irow) const
761 //get the pad row (irow) radii
762 if ( !(irow<0) && (irow<fNRowLow) )
763 return fPadRowLow[irow];
768 Float_t AliTPCParam::GetPadRowRadiiUp(Int_t irow) const
770 //get the pad row (irow) radii
771 if ( !(irow<0) && (irow<fNRowUp) )
772 return fPadRowUp[irow];
777 Int_t AliTPCParam::GetNPadsLow(Int_t irow) const
779 //get the number of pads in row irow
780 if ( !(irow<0) && (irow<fNRowLow) )
781 return fNPadsLow[irow];
787 Int_t AliTPCParam::GetNPadsUp(Int_t irow) const
789 //get the number of pads in row irow
790 if ( !(irow<0) && (irow<fNRowUp) )
791 return fNPadsUp[irow];
795 Float_t AliTPCParam::GetYInner(Int_t irow) const
797 return fYInner[irow];
801 Float_t AliTPCParam::GetYOuter(Int_t irow) const
803 return fYOuter[irow];
806 Int_t AliTPCParam::GetSectorIndex(Float_t angle, Int_t row, Float_t z) const
808 // returns the sector index
809 // takes as input the angle, index of the pad row and z position
812 if (angle > 2.*TMath::Pi()) angle -= 2.*TMath::Pi();
813 if (angle < 0. ) angle += 2.*TMath::Pi();
817 sector=Int_t(TMath::Nint((angle-fInnerAngleShift)/fInnerAngle));
818 if (z<0) sector += (fNInnerSector>>1);
821 sector=Int_t(TMath::Nint((angle-fOuterAngleShift)/fOuterAngle))+fNInnerSector;
822 if (z<0) sector += (fNOuterSector>>1);
828 Float_t AliTPCParam::GetChamberCenter(Int_t isec, Float_t * center) const
830 // returns the default radial position
831 // of the readout chambers
833 const Float_t kROCcenterIn = 110.2;
834 const Float_t kROCcenterOut = 188.45;
836 if (isec<fNInnerSector){
838 center[0] = kROCcenterIn;
840 center[2] = -5.51-0.08;
846 center[0] = kROCcenterOut;
848 center[2] = -5.61-0.08;
850 return kROCcenterOut;