Line data Source code
1 : /**************************************************************************
2 : * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 : * *
4 : * Author: The ALICE Off-line Project. *
5 : * Contributors are mentioned in the code where appropriate. *
6 : * *
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 : **************************************************************************/
15 :
16 :
17 : /// \class AliTPCParam
18 : /// \brief Manager and of geomety classes for set: TPC
19 : ///
20 : /// !sectors are numbered from 0
21 : /// !pad rows are numbered from 0
22 : ///
23 : /// 12.6. changed z relative
24 : ///
25 : /// \author Marian Ivanov, Uni. of Bratislava, ivanov@fmph.uniba.sk
26 :
27 : //
28 :
29 : #include <AliTPCParam.h>
30 :
31 : #include <TGeoManager.h>
32 : #include <TGeoPhysicalNode.h>
33 : #include <TString.h>
34 : #include "AliAlignObj.h"
35 : #include "AliAlignObjParams.h"
36 : #include "AliLog.h"
37 : #include "TGraphErrors.h"
38 : #include "AliTPCcalibDB.h"
39 : #include "AliTPCROC.h"
40 : #include "AliMathBase.h"
41 :
42 : TObjArray *AliTPCParam::fBBParam = 0;
43 :
44 : /// \cond CLASSIMP
45 24 : ClassImp(AliTPCParam)
46 : /// \endcond
47 :
48 :
49 : //___________________________________________
50 : AliTPCParam::AliTPCParam()
51 18 : :AliDetectorParam(),
52 18 : fbStatus(kFALSE),
53 18 : fInnerRadiusLow(0.),
54 18 : fInnerRadiusUp(0.),
55 18 : fOuterRadiusUp(0.),
56 18 : fOuterRadiusLow(0.),
57 18 : fInnerAngle(0.),
58 18 : fInnerAngleShift(0.),
59 18 : fOuterAngle(0.),
60 18 : fOuterAngleShift(0.),
61 18 : fInnerFrameSpace(0.),
62 18 : fOuterFrameSpace(0.),
63 18 : fInnerWireMount(0.),
64 18 : fOuterWireMount(0.),
65 18 : fNInnerSector(0),
66 18 : fNOuterSector(0),
67 18 : fNSector(0),
68 18 : fZLength(0),
69 18 : fRotAngle(),
70 18 : fGeometryType(0),
71 18 : fTrackingMatrix(0),
72 18 : fClusterMatrix(0),
73 18 : fGlobalMatrix(0),
74 18 : fNInnerWiresPerPad(0),
75 18 : fInnerWWPitch(0),
76 18 : fInnerDummyWire(0),
77 18 : fInnerOffWire(0.),
78 18 : fRInnerFirstWire(0.),
79 18 : fRInnerLastWire(0.),
80 18 : fLastWireUp1(0.),
81 18 : fNOuter1WiresPerPad(0),
82 18 : fNOuter2WiresPerPad(0),
83 18 : fOuterWWPitch(0.),
84 18 : fOuterDummyWire(0),
85 18 : fOuterOffWire(0.),
86 18 : fROuterFirstWire(0.),
87 18 : fROuterLastWire(0.),
88 18 : fInnerPadPitchLength(0.),
89 18 : fInnerPadPitchWidth(0.),
90 18 : fInnerPadLength(0.),
91 18 : fInnerPadWidth(0.),
92 18 : fOuter1PadPitchLength(0.),
93 18 : fOuter2PadPitchLength(0.),
94 18 : fOuterPadPitchWidth(0.),
95 18 : fOuter1PadLength(0.),
96 18 : fOuter2PadLength(0.),
97 18 : fOuterPadWidth(0.),
98 18 : fBMWPCReadout(kFALSE),
99 18 : fNCrossRows(0),
100 18 : fNRowLow(0),
101 18 : fNRowUp1(0),
102 18 : fNRowUp2(0),
103 18 : fNRowUp(0),
104 18 : fNtRows(0),
105 18 : fDiffT(0.),
106 18 : fDiffL(0.),
107 18 : fGasGain(0.),
108 18 : fDriftV(0.),
109 18 : fOmegaTau(0.),
110 18 : fAttCoef(0.),
111 18 : fOxyCont(0.),
112 18 : fFpot(0.),
113 18 : fNprim(0.),
114 18 : fNtot(0.),
115 18 : fWmean(0.),
116 18 : fExp(0.),
117 18 : fEend(0.),
118 18 : fBetheBloch(0x0), // dE/dx:BG - used in the reconstruction
119 18 : fBetheBlochMC(0x0), // dN_{prim}/dx:BG - used for the simulation of energy loss
120 18 : fGainSlopesHV(0), // graph with the gain slope as function of HV - per chamber
121 18 : fGainSlopesPT(0), // graph with the gain slope as function of P/T - per chamber
122 18 : fPadCoupling(0.),
123 18 : fZeroSup(0),
124 18 : fNoise(0.),
125 18 : fChipGain(0.),
126 18 : fChipNorm(0.),
127 18 : fTSample(0.),
128 18 : fZWidth(0.),
129 18 : fTSigma(0.),
130 18 : fMaxTBin(0),
131 18 : fADCSat(0),
132 18 : fADCDynRange(0.),
133 18 : fTotalNormFac(0.),
134 18 : fNoiseNormFac(0.),
135 18 : fUseGlitchFilter(kTRUE),
136 18 : fNominalVoltage(),
137 18 : fMaxVoltageDeviation(40.),
138 18 : fMaxDipVoltage(2.),
139 18 : fMaxHVfractionBad(.4),
140 18 : fVoltageDipScanPeriod(1.),
141 18 : fNResponseMax(0),
142 18 : fResponseThreshold(0.),
143 18 : fCurrentMax(0),
144 18 : fResponseBin(0),
145 18 : fResponseWeight(0),
146 18 : fGateDelay(0.),
147 18 : fL1Delay(0.),
148 18 : fNTBinsBeforeL1(0),
149 18 : fNTBinsL1(0.)
150 54 : {
151 : //
152 : //constructor sets the default parameters
153 : //
154 :
155 18 : SetTitle("75x40_100x60_150x60");
156 18 : SetDefault();
157 27 : if (!fBBParam) fBBParam= new TObjArray(1000);
158 18 : fRegionGain[0]=fRegionGain[1]=fRegionGain[2]=0.;
159 18 : }
160 :
161 : AliTPCParam::~AliTPCParam()
162 6 : {
163 : /// destructor deletes some dynamicaly alocated variables
164 :
165 9 : if (fResponseBin!=0) delete [] fResponseBin;
166 9 : if (fResponseWeight!=0) delete [] fResponseWeight;
167 9 : if (fRotAngle !=0) delete [] fRotAngle;
168 :
169 3 : CleanGeoMatrices();
170 :
171 3 : }
172 :
173 : Int_t AliTPCParam::Transform0to1(Float_t *xyz, Int_t * index) const
174 : {
175 : /// calculates sector number (index[1], undefined on input)
176 : /// xyz intact
177 :
178 : Float_t angle,x1;
179 : Int_t sector;
180 8 : Float_t r = TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
181 4 : if ((xyz[0]==0)&&(xyz[1]==0)) angle = 0.;
182 : else
183 : {
184 4 : angle =TMath::ASin(xyz[1]/r);
185 4 : if (xyz[0]<0) angle=TMath::Pi()-angle;
186 8 : if ( (xyz[0]>0) && (xyz[1]<0) ) angle=2*TMath::Pi()+angle;
187 : }
188 :
189 4 : sector=Int_t(TMath::Nint((angle-fInnerAngleShift)/fInnerAngle));
190 :
191 4 : Float_t cos,sin;
192 4 : AdjustCosSin(sector,cos,sin);
193 4 : x1=xyz[0]*cos + xyz[1]*sin;
194 :
195 4 : if (x1>fOuterRadiusLow)
196 : {
197 4 : sector=Int_t(TMath::Nint((angle-fOuterAngleShift)/fOuterAngle))+fNInnerSector;
198 4 : if (xyz[2]<0) sector+=(fNOuterSector>>1);
199 : }
200 : else
201 0 : if (xyz[2]<0) sector+=(fNInnerSector>>1);
202 8 : if (sector<0 || sector>=fNSector) AliError(Form("Wrong sector %d",sector));
203 4 : index[1]=sector; // calculated sector number
204 4 : index[0]=1; // indicates system after transformation
205 4 : return sector;
206 4 : }
207 :
208 : Bool_t AliTPCParam::Transform(Float_t */*xyz*/, Int_t *index, Int_t* /*oindex*/)
209 : {
210 : /// transformation from input coodination system to output coordination system
211 :
212 : switch (index[0]){
213 : case 0:
214 : break;
215 : };
216 :
217 0 : return kFALSE;
218 :
219 : }
220 :
221 : Int_t AliTPCParam::GetPadRow(Float_t *xyz, Int_t *index) const
222 : {
223 : /// calculates pad row of point xyz - transformation to system 8 (digit system)
224 :
225 3382744 : Int_t system = index[0];
226 1691372 : if (0==system) {
227 0 : Transform0to1(xyz,index);
228 : system=1;
229 0 : }
230 1691372 : if (1==system) {
231 0 : Transform1to2(xyz,index);
232 : system=2;
233 0 : }
234 :
235 1691372 : if (fGeometryType==0){ //straight row
236 1691372 : if (2==system) {
237 1691372 : Transform2to3(xyz,index);
238 : system=3;
239 1691372 : }
240 1691372 : if (3==system) {
241 1691372 : Transform3to4(xyz,index);
242 : system=4;
243 1691372 : }
244 1691372 : if (4==system) {
245 1691372 : Transform4to8(xyz,index);
246 : system=8;
247 1691372 : }
248 1691372 : if (8==system) {
249 1691372 : index[0]=8;
250 1691372 : return index[2];
251 : }
252 : }
253 :
254 0 : if (fGeometryType==1){ //cylindrical geometry
255 0 : if (2==system) {
256 0 : Transform2to5(xyz,index);
257 : system=5;
258 0 : }
259 0 : if (5==system) {
260 0 : Transform2to3(xyz,index);
261 : system=6;
262 0 : }
263 0 : if (6==system) {
264 0 : Transform3to4(xyz,index);
265 : system=7;
266 0 : }
267 0 : if (8==system) {
268 0 : index[0]=8;
269 0 : return index[2];
270 : }
271 : }
272 0 : index[0]=system;
273 0 : return -1; //if no reasonable system
274 1691372 : }
275 :
276 : void AliTPCParam::SetSectorAngles(Float_t innerangle, Float_t innershift, Float_t outerangle,
277 : Float_t outershift)
278 : {
279 : /// set opening angles
280 :
281 : static const Float_t kDegtoRad = 0.01745329251994;
282 72 : fInnerAngle = innerangle; //opening angle of Inner sector
283 36 : fInnerAngleShift = innershift; //shift of first inner sector center to the 0
284 36 : fOuterAngle = outerangle; //opening angle of outer sector
285 36 : fOuterAngleShift = outershift; //shift of first sector center to the 0
286 36 : fInnerAngle *=kDegtoRad;
287 36 : fInnerAngleShift *=kDegtoRad;
288 36 : fOuterAngle *=kDegtoRad;
289 36 : fOuterAngleShift *=kDegtoRad;
290 36 : }
291 :
292 : Float_t AliTPCParam::GetInnerAngle() const
293 : {
294 : /// return angle
295 :
296 1649122 : return fInnerAngle;
297 :
298 : }
299 :
300 : Float_t AliTPCParam::GetInnerAngleShift() const
301 : {
302 : /// return angle
303 :
304 1648870 : return fInnerAngleShift;
305 : }
306 : Float_t AliTPCParam::GetOuterAngle() const
307 : {
308 : /// return angle
309 :
310 621716 : return fOuterAngle;
311 : }
312 : Float_t AliTPCParam::GetOuterAngleShift() const
313 : {
314 : /// return angle
315 :
316 621332 : return fOuterAngleShift;
317 : }
318 :
319 :
320 : Int_t AliTPCParam::GetIndex(Int_t sector, Int_t row) const
321 : {
322 : /// give index of the given sector and pad row
323 : /// no control if the sectors and rows are reasonable !!!
324 :
325 274131 : if (sector<fNInnerSector) return sector*fNRowLow+row;
326 69120 : return (fNInnerSector*fNRowLow)+(sector-fNInnerSector)*fNRowUp+row;
327 114417 : }
328 :
329 : Bool_t AliTPCParam::AdjustSectorRow(Int_t index, Int_t & sector, Int_t &row) const
330 : {
331 : /// return sector and padrow for given index
332 : /// if index is reasonable returns true else return false
333 :
334 274563 : if ( (index<0) || (index>fNtRows)) return kFALSE;
335 91521 : Int_t outindex = fNInnerSector*fNRowLow;
336 91521 : if (index<outindex) {
337 36225 : sector = index/fNRowLow;
338 36225 : row = index - sector*fNRowLow;
339 36225 : return kTRUE;
340 : }
341 55296 : index-= outindex;
342 55296 : sector = index/fNRowUp;
343 55296 : row = index - sector*fNRowUp;
344 55296 : sector += fNInnerSector;
345 55296 : return kTRUE;
346 91521 : }
347 :
348 : void AliTPCParam::SetDefault()
349 : {
350 : /// set default parameters
351 : ///
352 : /// const static Int_t kMaxRows=600;
353 : ///
354 : /// sector default parameters
355 :
356 : static const Float_t kInnerRadiusLow = 83.65;
357 : static const Float_t kInnerRadiusUp = 133.3;
358 : static const Float_t kOuterRadiusLow = 133.5;
359 : static const Float_t kOuterRadiusUp = 247.7;
360 : static const Float_t kInnerAngle = 20; // 20 degrees
361 : static const Float_t kInnerAngleShift = 10;
362 : static const Float_t kOuterAngle = 20; // 20 degrees
363 : static const Float_t kOuterAngleShift = 10;
364 : static const Float_t kInnerFrameSpace = 1.5;
365 : static const Float_t kOuterFrameSpace = 1.5;
366 : static const Float_t kInnerWireMount = 1.2;
367 : static const Float_t kOuterWireMount = 1.4;
368 : static const Float_t kZLength =250.;
369 : static const Int_t kGeometryType = 0; //straight rows
370 : static const Int_t kNRowLow = 63;
371 : static const Int_t kNRowUp1 = 64;
372 : static const Int_t kNRowUp2 = 32;
373 : static const Int_t kNRowUp = 96;
374 : //
375 : //wires default parameters
376 : //
377 : static const Int_t kNInnerWiresPerPad = 3;
378 : static const Int_t kInnerDummyWire = 2;
379 : static const Float_t kInnerWWPitch = 0.25;
380 : static const Float_t kRInnerFirstWire = 84.475;
381 : static const Float_t kRInnerLastWire = 132.475;
382 : static const Float_t kInnerOffWire = 0.5;
383 : static const Int_t kNOuter1WiresPerPad = 4;
384 : static const Int_t kNOuter2WiresPerPad = 6;
385 : static const Float_t kOuterWWPitch = 0.25;
386 : static const Float_t kROuterFirstWire = 134.225;
387 : static const Float_t kROuterLastWire = 246.975;
388 : static const Int_t kOuterDummyWire = 2;
389 : static const Float_t kOuterOffWire = 0.5;
390 : //
391 : //pad default parameters
392 : //
393 : static const Float_t kInnerPadPitchLength = 0.75;
394 : static const Float_t kInnerPadPitchWidth = 0.40;
395 : static const Float_t kInnerPadLength = 0.75;
396 : static const Float_t kInnerPadWidth = 0.40;
397 : static const Float_t kOuter1PadPitchLength = 1.0;
398 : static const Float_t kOuterPadPitchWidth = 0.6;
399 : static const Float_t kOuter1PadLength = 1.0;
400 : static const Float_t kOuterPadWidth = 0.6;
401 : static const Float_t kOuter2PadPitchLength = 1.5;
402 : static const Float_t kOuter2PadLength = 1.5;
403 :
404 : static const Bool_t kBMWPCReadout = kTRUE; //MWPC readout - another possibility GEM
405 : static const Int_t kNCrossRows = 1; //number of rows to cross-talk
406 :
407 : //
408 : //gas default parameters
409 : //
410 : static const Float_t kDiffT = 2.2e-2;
411 : static const Float_t kDiffL = 2.2e-2;
412 : static const Float_t kGasGain = 2.e4;
413 : static const Float_t kDriftV =2.83e6;
414 : static const Float_t kOmegaTau = 0.145;
415 : static const Float_t kAttCoef = 250.;
416 : static const Float_t kOxyCont = 5.e-6;
417 : static const Float_t kFpot = 22.77e-9;
418 : static const Float_t kNprim=14.35;
419 : static const Float_t kNtot=42.66;
420 : static const Float_t kWmean = 35.97e-9;
421 : static const Float_t kExp = 2.2;
422 : static const Float_t kEend = 10.e-6;
423 : //
424 : //electronic default parameters
425 : //
426 : static const Float_t kPadCoupling=0.5;
427 : static const Int_t kZeroSup=2;
428 : static const Float_t kNoise = 1000;
429 : static const Float_t kChipGain = 12;
430 : static const Float_t kChipNorm = 0.4;
431 : static const Float_t kTSample = 2.e-7;
432 : static const Float_t kTFWHM = 1.9e-7; //fwhm of charge distribution
433 : static const Int_t kMaxTBin =445;
434 : static const Int_t kADCSat =1024;
435 : static const Float_t kADCDynRange =2000.;
436 : //
437 : //response constants
438 : //
439 : static const Int_t kNResponseMax=100;
440 : static const Float_t kResponseThreshold=0.01;
441 : //L1 constants
442 : // static const Float_t kGateDelay=6.1e-6; //In s
443 : static const Float_t kGateDelay=0.; //For the moment no gating
444 : // static const Float_t kL1Delay=6.5e-6; //In s
445 : static const Float_t kL1Delay=0.; //For the moment no delay
446 : // static const UShort_t kNTBinsBeforeL1=14;
447 : static const UShort_t kNTBinsBeforeL1=0; //For the moment no shift
448 72 : fbStatus = kFALSE;
449 : //
450 : //set sector parameters
451 : //
452 36 : SetInnerRadiusLow(kInnerRadiusLow);
453 36 : SetOuterRadiusLow(kOuterRadiusLow);
454 36 : SetInnerRadiusUp(kInnerRadiusUp);
455 36 : SetOuterRadiusUp(kOuterRadiusUp);
456 36 : SetInnerFrameSpace(kInnerFrameSpace);
457 36 : SetOuterFrameSpace(kOuterFrameSpace);
458 36 : SetInnerWireMount(kInnerWireMount);
459 36 : SetOuterWireMount(kOuterWireMount);
460 36 : SetSectorAngles(kInnerAngle,kInnerAngleShift,kOuterAngle,kOuterAngleShift);
461 36 : SetZLength(kZLength);
462 36 : SetGeometryType(kGeometryType);
463 36 : SetRowNLow(kNRowLow);
464 36 : SetRowNUp1 (kNRowUp1);
465 36 : SetRowNUp2(kNRowUp2);
466 36 : SetRowNUp(kNRowUp);
467 : //
468 : //set wire parameters
469 : //
470 36 : SetInnerNWires(kNInnerWiresPerPad);
471 36 : SetInnerDummyWire(kInnerDummyWire);
472 36 : SetInnerOffWire(kInnerOffWire);
473 36 : SetOuter1NWires(kNOuter1WiresPerPad);
474 36 : SetOuter2NWire(kNOuter2WiresPerPad);
475 36 : SetOuterDummyWire(kOuterDummyWire);
476 36 : SetOuterOffWire(kOuterOffWire);
477 36 : SetInnerWWPitch(kInnerWWPitch);
478 36 : SetRInnerFirstWire(kRInnerFirstWire);
479 36 : SetRInnerLastWire(kRInnerLastWire);
480 36 : SetOuterWWPitch(kOuterWWPitch);
481 36 : SetROuterFirstWire(kROuterFirstWire);
482 36 : SetROuterLastWire(kROuterLastWire);
483 : //
484 : //set pad parameter
485 : //
486 36 : SetInnerPadPitchLength(kInnerPadPitchLength);
487 36 : SetInnerPadPitchWidth(kInnerPadPitchWidth);
488 36 : SetInnerPadLength(kInnerPadLength);
489 36 : SetInnerPadWidth(kInnerPadWidth);
490 36 : SetOuter1PadPitchLength(kOuter1PadPitchLength);
491 36 : SetOuter2PadPitchLength(kOuter2PadPitchLength);
492 36 : SetOuterPadPitchWidth(kOuterPadPitchWidth);
493 36 : SetOuter1PadLength(kOuter1PadLength);
494 36 : SetOuter2PadLength(kOuter2PadLength);
495 36 : SetOuterPadWidth(kOuterPadWidth);
496 36 : SetMWPCReadout(kBMWPCReadout);
497 36 : SetNCrossRows(kNCrossRows);
498 : //
499 : //set gas paremeters
500 : //
501 36 : SetDiffT(kDiffT);
502 36 : SetDiffL(kDiffL);
503 36 : SetGasGain(kGasGain);
504 36 : SetDriftV(kDriftV);
505 36 : SetOmegaTau(kOmegaTau);
506 36 : SetAttCoef(kAttCoef);
507 36 : SetOxyCont(kOxyCont);
508 36 : SetFpot(kFpot);
509 36 : SetNprim(kNprim);
510 36 : SetNtot(kNtot);
511 36 : SetWmean(kWmean);
512 36 : SetExp(kExp);
513 36 : SetEend(kEend);
514 : //
515 36 : SetComposition(0.9,0.,0.1,0.,0.,0.);// Ne-CO2 90/10
516 : //
517 36 : SetBetheBloch(GetBetheBlochParamAlice());
518 36 : SetBetheBlochMC(GetBetheBlochParamAliceMC());
519 : //
520 : //set electronivc parameters
521 : //
522 36 : SetPadCoupling(kPadCoupling);
523 36 : SetZeroSup(kZeroSup);
524 36 : SetNoise(kNoise);
525 36 : SetChipGain(kChipGain);
526 36 : SetChipNorm(kChipNorm);
527 36 : SetTSample(kTSample);
528 36 : SetTFWHM(kTFWHM);
529 36 : SetMaxTBin(kMaxTBin);
530 36 : SetADCSat(kADCSat);
531 36 : SetADCDynRange(kADCDynRange);
532 2664 : for (UInt_t i=0; i<36; i++)
533 : {
534 1296 : SetNominalVoltage(1196.0, i);
535 : }
536 2664 : for (UInt_t i=36; i<72; i++)
537 : {
538 1296 : SetNominalVoltage(1417.0, i);
539 : }
540 : // //set magnetic field
541 : // SetBField(kBField);
542 : // SetNPrimLoss(kNPrimLoss);
543 : // SetNTotalLoss(kNTotalLoss);
544 : //
545 : //set response parameters
546 : //
547 36 : SetNResponseMax(kNResponseMax);
548 36 : SetResponseThreshold(static_cast<int>(kResponseThreshold));
549 : //L1 data
550 36 : SetGateDelay(kGateDelay);
551 36 : SetL1Delay(kL1Delay);
552 36 : SetNTBinsBeforeL1(kNTBinsBeforeL1);
553 36 : SetNominalGainSlopes();
554 36 : }
555 :
556 :
557 : Bool_t AliTPCParam::Update()
558 : {
559 : /// update some calculated parameter which must be updated after changing "base"
560 : /// parameters
561 : /// for example we can change size of pads and according this recalculate number
562 : /// of pad rows, number of of pads in given row ....
563 :
564 : const Float_t kQel = 1.602e-19; // elementary charge
565 66 : fbStatus = kFALSE;
566 :
567 : Int_t i,j; //loop variables because HP
568 : //-----------------Sector section------------------------------------------
569 : //calclulate number of sectors
570 33 : fNInnerSector = Int_t(4*TMath::Pi()/fInnerAngle+0.2);
571 : // number of inner sectors - factor 0.2 to don't be influnced by inprecision
572 33 : if (fNInnerSector%2) return kFALSE;
573 33 : fNOuterSector = Int_t(4*TMath::Pi()/fOuterAngle+0.2);
574 33 : if (fNOuterSector%2) return kFALSE;
575 33 : fNSector = fNInnerSector+fNOuterSector;
576 :
577 63 : if (fRotAngle!=0) delete [] fRotAngle;
578 33 : fRotAngle = new Float_t[4*fNSector];
579 : //calculate sin and cosine of rotations angle
580 : //sectors angles numbering from 0
581 :
582 33 : j=fNInnerSector*2;
583 33 : Float_t angle = fInnerAngleShift;
584 1254 : for (i=0; j<fNInnerSector*4; i+=4, j+=4 , angle +=fInnerAngle){
585 594 : fRotAngle[i]=TMath::Cos(angle);
586 594 : fRotAngle[i+1]=TMath::Sin(angle);
587 594 : fRotAngle[j] = fRotAngle[i];
588 594 : fRotAngle[j+1] = fRotAngle[i+1];
589 594 : fRotAngle[i+2] =angle;
590 594 : fRotAngle[j+2] =angle;
591 594 : fRotAngle[i+3] =angle;
592 594 : fRotAngle[j+3] =angle;
593 : }
594 33 : angle = fOuterAngleShift;
595 33 : j=(fNInnerSector+fNOuterSector/2)*4;
596 1254 : for (i=fNInnerSector*4; j<fNSector*4; i+=4,j+=4, angle +=fOuterAngle){
597 594 : fRotAngle[i]=TMath::Cos(angle);
598 594 : fRotAngle[i+1]=TMath::Sin(angle);
599 594 : fRotAngle[j] = fRotAngle[i];
600 594 : fRotAngle[j+1] = fRotAngle[i+1];
601 594 : fRotAngle[i+2] =angle;
602 594 : fRotAngle[j+2] =angle;
603 594 : fRotAngle[i+3] =angle;
604 594 : fRotAngle[j+3] =angle;
605 : }
606 :
607 33 : fZWidth = fTSample*fDriftV;
608 33 : fTotalNormFac = fPadCoupling*fChipNorm*kQel*1.e15*fChipGain*fADCSat/fADCDynRange;
609 33 : fNoiseNormFac = kQel*1.e15*fChipGain*fADCSat/fADCDynRange;
610 : //wire section
611 : /* Int_t nwire;
612 : Float_t wspace; //available space for wire
613 : Float_t dummyspace; //dummyspace for wire
614 :
615 : wspace =fInnerRadiusUp-fInnerRadiusLow-2*fInnerOffWire;
616 : nwire = Int_t(wspace/fInnerWWPitch);
617 : wspace = Float_t(nwire)*fInnerWWPitch;
618 : dummyspace =(fInnerRadiusUp-fInnerRadiusLow-wspace)/2.;
619 : wspace =fOuterRadiusUp-fOuterRadiusLow-2*fOuterOffWire;
620 : nwire = Int_t(wspace/fOuterWWPitch);
621 : wspace = Float_t(nwire)*fOuterWWPitch;
622 : dummyspace =(fOuterRadiusUp-fOuterRadiusLow-wspace)/2.;
623 : fROuterFirstWire = fOuterRadiusLow+dummyspace;
624 : fROuterLastWire = fROuterFirstWire+fOuterWWPitch*(Float_t)(nwire);
625 : */
626 :
627 : //
628 : //response data
629 : //
630 63 : if (fResponseBin) delete [] fResponseBin;
631 63 : if (fResponseWeight) delete [] fResponseWeight;
632 33 : fResponseBin = new Int_t[3*fNResponseMax];
633 33 : fResponseWeight = new Float_t[fNResponseMax];
634 :
635 : //L1 data
636 33 : fNTBinsL1 = fL1Delay/fTSample - (Float_t)fNTBinsBeforeL1;
637 33 : fbStatus = kTRUE;
638 : return kTRUE;
639 33 : }
640 :
641 : void AliTPCParam::CleanGeoMatrices(){
642 : /// clean geo matrices
643 :
644 40 : if (fTrackingMatrix) {
645 730 : for(Int_t i = 0; i < fNSector; i++)
646 360 : delete fTrackingMatrix[i];
647 10 : delete [] fTrackingMatrix;
648 : }
649 :
650 20 : if (fClusterMatrix) {
651 730 : for(Int_t i = 0; i < fNSector; i++)
652 720 : delete fClusterMatrix[i];
653 10 : delete [] fClusterMatrix;
654 : }
655 :
656 20 : if (fGlobalMatrix) {
657 730 : for(Int_t i = 0; i < fNSector; i++)
658 720 : delete fGlobalMatrix[i];
659 10 : delete [] fGlobalMatrix;
660 : }
661 :
662 20 : return;
663 : }
664 :
665 : Bool_t AliTPCParam::ReadGeoMatrices(){
666 : /// read geo matrixes
667 :
668 34 : if (!gGeoManager){
669 0 : AliFatal("Geo manager not initialized\n");
670 0 : }
671 17 : AliAlignObjParams o;
672 : //
673 :
674 : // clean geo matrices
675 17 : CleanGeoMatrices();
676 :
677 : // create new geo matrices
678 34 : fTrackingMatrix = new TGeoHMatrix*[fNSector];
679 34 : fClusterMatrix = new TGeoHMatrix*[fNSector];
680 34 : fGlobalMatrix = new TGeoHMatrix*[fNSector];
681 2482 : for (Int_t isec=0; isec<fNSector; isec++) {
682 1224 : fGlobalMatrix[isec] = 0;
683 1224 : fClusterMatrix[isec]= 0;
684 1224 : fTrackingMatrix[isec]=0;
685 : }
686 : //
687 2499 : for (Int_t isec=0; isec<fNSector; isec++) {
688 1224 : fGlobalMatrix[isec] = 0;
689 1224 : fClusterMatrix[isec]= 0;
690 1224 : fTrackingMatrix[isec]=0;
691 : AliGeomManager::ELayerID iLayer;
692 : Int_t iModule;
693 :
694 1224 : if(isec<fNInnerSector) {
695 : iLayer = AliGeomManager::kTPC1;
696 : iModule = isec;
697 612 : }
698 : else {
699 : iLayer = AliGeomManager::kTPC2;
700 612 : iModule = isec - fNInnerSector;
701 : }
702 :
703 1224 : UShort_t volid = AliGeomManager::LayerToVolUID(iLayer,iModule);
704 1224 : TGeoPNEntry* pne = gGeoManager->GetAlignableEntryByUID(volid);
705 1224 : if(!pne)
706 : {
707 0 : AliError(Form("Alignable entry for volume ID %d not in geometry. Exiting!",volid));
708 0 : return kFALSE;
709 : }
710 1224 : const char *path = pne->GetTitle();
711 2448 : if (!gGeoManager->cd(path)) return kFALSE;
712 1224 : 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 3672 : if (gGeoManager->GetCurrentVolume()->GetShape()->IsReflected())
716 0 : m->ReflectZ(kFALSE, kTRUE);
717 : //
718 1224 : TGeoRotation mchange;
719 2448 : mchange.RotateY(90); mchange.RotateX(90);
720 1224 : Float_t ROCcenter[3];
721 1224 : GetChamberCenter(isec,ROCcenter);
722 : //
723 : // Convert to global coordinate system
724 : //
725 3672 : fGlobalMatrix[isec] = new TGeoHMatrix(*m);
726 2448 : fGlobalMatrix[isec]->Multiply(&(mchange.Inverse()));
727 1224 : TGeoTranslation center("center",-ROCcenter[0],-ROCcenter[1],-ROCcenter[2]);
728 1224 : fGlobalMatrix[isec]->Multiply(¢er);
729 : //
730 : // cluster correction matrix
731 : //
732 3672 : fClusterMatrix[isec] = new TGeoHMatrix;
733 1224 : Double_t sectorAngle = 20.*(isec%18)+10;
734 1224 : TGeoHMatrix rotMatrix;
735 1224 : rotMatrix.RotateZ(sectorAngle);
736 2448 : if (GetGlobalMatrix(isec)->GetTranslation()[2]>0){
737 : //
738 : // mirrored system
739 : //
740 612 : TGeoRotation mirrorZ;
741 612 : mirrorZ.SetAngles(90,0,90,90,180,0);
742 612 : fClusterMatrix[isec]->Multiply(&mirrorZ);
743 612 : }
744 1224 : TGeoTranslation trans(0,0,GetZLength(isec));
745 1224 : fClusterMatrix[isec]->MultiplyLeft(&trans);
746 1224 : fClusterMatrix[isec]->MultiplyLeft((GetGlobalMatrix(isec)));
747 2448 : fClusterMatrix[isec]->MultiplyLeft(&(rotMatrix.Inverse()));
748 1224 : }
749 17 : return kTRUE;
750 17 : }
751 :
752 : TGeoHMatrix * AliTPCParam::Tracking2LocalMatrix(const TGeoHMatrix * geoMatrix, Int_t sector) const{
753 : /// make local to tracking matrix
754 :
755 144 : Double_t sectorAngle = 20.*(sector%18)+10;
756 72 : TGeoHMatrix *newMatrix = new TGeoHMatrix();
757 72 : newMatrix->RotateZ(sectorAngle);
758 72 : newMatrix->MultiplyLeft(&(geoMatrix->Inverse()));
759 72 : return newMatrix;
760 0 : }
761 :
762 :
763 :
764 :
765 : Bool_t AliTPCParam::GetStatus() const
766 : {
767 : /// get information about object consistency
768 :
769 0 : return fbStatus;
770 : }
771 :
772 : Int_t AliTPCParam::GetNRowLow() const
773 : {
774 : /// get the number of pad rows in low sector
775 :
776 140712 : return fNRowLow;
777 : }
778 : Int_t AliTPCParam::GetNRowUp() const
779 : {
780 : /// get the number of pad rows in up sector
781 :
782 608 : return fNRowUp;
783 : }
784 : Int_t AliTPCParam::GetNRowUp1() const
785 : {
786 : /// get the number of pad rows in up1 sector
787 :
788 1425296 : return fNRowUp1;
789 : }
790 : Int_t AliTPCParam::GetNRowUp2() const
791 : {
792 : /// get the number of pad rows in up2 sector
793 :
794 1080 : return fNRowUp2;
795 : }
796 : Float_t AliTPCParam::GetPadRowRadiiLow(Int_t irow) const
797 : {
798 : /// get the pad row (irow) radii
799 :
800 338028 : if ( !(irow<0) && (irow<fNRowLow) )
801 112676 : return fPadRowLow[irow];
802 : else
803 0 : return 0;
804 112676 : }
805 :
806 : Float_t AliTPCParam::GetPadRowRadiiUp(Int_t irow) const
807 : {
808 : /// get the pad row (irow) radii
809 :
810 206976 : if ( !(irow<0) && (irow<fNRowUp) )
811 68992 : return fPadRowUp[irow];
812 : else
813 0 : return 0;
814 68992 : }
815 :
816 : Int_t AliTPCParam::GetNPadsLow(Int_t irow) const
817 : {
818 : /// get the number of pads in row irow
819 :
820 12049505 : if ( !(irow<0) && (irow<fNRowLow) )
821 3999060 : return fNPadsLow[irow];
822 : else
823 22980 : return 0;
824 4022040 : }
825 :
826 :
827 : Int_t AliTPCParam::GetNPadsUp(Int_t irow) const
828 : {
829 : /// get the number of pads in row irow
830 :
831 8605676 : if ( !(irow<0) && (irow<fNRowUp) )
832 2837892 : return fNPadsUp[irow];
833 : else
834 32235 : return 0;
835 2870127 : }
836 :
837 : Int_t AliTPCParam::GetWireSegment(Int_t sector, Int_t row) const
838 : {
839 : /// Get Anode wire segment index IROC --> 4 segments in [0,3], 7 segments OROC[4,10]
840 : ///
841 : /// To be speed-up using caching lookup table
842 :
843 : Int_t wireIndex = -1;
844 : // check if the given set of sector and row is OK
845 0 : if ( (sector<0 || sector>=72) || (row<0 || row>95) || (sector<36 && row>64) ){
846 0 : AliError("No matching anode wire segment for this set of sector-row \n");
847 0 : return wireIndex;
848 : }
849 : // find the wire index for given sector-row
850 0 : if ( sector<36 ){ // IROC anode wire segments
851 0 : if (row<16) wireIndex=0;
852 0 : else if (row>=16 && row<32) wireIndex=1;
853 0 : else if (row>=32 && row<48) wireIndex=2;
854 : else wireIndex=3;
855 : } else { // OROC anode wire segments
856 0 : if (row<16) wireIndex=4;
857 0 : else if ( row>=16 && row<32) wireIndex=5;
858 0 : else if ( row>=32 && row<48) wireIndex=6;
859 0 : else if ( row>=48 && row<64) wireIndex=7;
860 0 : else if ( row>=64 && row<75) wireIndex=8;
861 0 : else if ( row>=75 && row<85) wireIndex=9;
862 : else wireIndex=10;
863 : }
864 0 : return wireIndex;
865 0 : }
866 :
867 : Int_t AliTPCParam::GetNPadsPerSegment(Int_t wireSegmentID) const
868 : {
869 : /// Get the number of pads in a given anode wire segment
870 : ///
871 : /// check if the given segment index is OK
872 : /// To be done (if needed) - cache the lookup table
873 :
874 0 : if ( wireSegmentID<0 || wireSegmentID>10 ){
875 0 : AliError("Wrong anode wire segment index. it should be [0,10] \n");
876 0 : return -1;
877 : }
878 : // get sector type from wireSegmentID
879 0 : Int_t sector = (wireSegmentID<4) ? 0 : 36; // ROC [0,35] --> IROC, ROC [36,71] --> OROC
880 : // get the upper and lower row number for the given wireSegmentID
881 : Int_t segRowDown = 0;
882 : Int_t segRowUp = 0;
883 :
884 0 : if ( wireSegmentID == 0 || wireSegmentID == 4 ) {
885 : segRowDown = 0;
886 : segRowUp = 16;
887 0 : } else if ( wireSegmentID == 1 || wireSegmentID == 5 ) {
888 : segRowDown = 16;
889 : segRowUp = 32;
890 0 : } else if ( wireSegmentID == 2 || wireSegmentID == 6 ) {
891 : segRowDown = 32;
892 : segRowUp = 48;
893 0 : } else if ( wireSegmentID == 3 || wireSegmentID == 7 ) {
894 : segRowDown = 48;
895 : segRowUp = 63;
896 0 : } else if ( wireSegmentID == 8 ) {
897 : segRowDown = 64;
898 : segRowUp = 75;
899 0 : } else if ( wireSegmentID == 9 ) {
900 : segRowDown = 75;
901 : segRowUp = 85;
902 0 : } else {
903 : segRowDown = 85;
904 : segRowUp = 95;
905 : }
906 : // count the number of pads on the given segment
907 0 : AliTPCROC *r=AliTPCROC::Instance();
908 : Int_t nPads=0;
909 0 : for (Int_t irow = segRowDown; irow < segRowUp ; irow++){
910 0 : nPads += r->GetNPads(sector,irow);
911 : }
912 : return nPads;
913 0 : }
914 :
915 : Float_t AliTPCParam::GetYInner(Int_t irow) const
916 : {
917 0 : return fYInner[irow];
918 : }
919 :
920 :
921 : Float_t AliTPCParam::GetYOuter(Int_t irow) const
922 : {
923 0 : return fYOuter[irow];
924 : }
925 :
926 : Int_t AliTPCParam::GetSectorIndex(Float_t angle, Int_t row, Float_t z) const
927 : {
928 : /// returns the sector index
929 : /// takes as input the angle, index of the pad row and z position
930 :
931 0 : if(row<0) return -1;
932 :
933 0 : if (angle > 2.*TMath::Pi()) angle -= 2.*TMath::Pi();
934 0 : if (angle < 0. ) angle += 2.*TMath::Pi();
935 :
936 : Int_t sector;
937 0 : if(row<fNRowLow) {
938 0 : sector=Int_t(TMath::Nint((angle-fInnerAngleShift)/fInnerAngle));
939 0 : if (z<0) sector += (fNInnerSector>>1);
940 : }
941 : else {
942 0 : sector=Int_t(TMath::Nint((angle-fOuterAngleShift)/fOuterAngle))+fNInnerSector;
943 0 : if (z<0) sector += (fNOuterSector>>1);
944 : }
945 :
946 : return sector;
947 0 : }
948 :
949 : Float_t AliTPCParam::GetChamberCenter(Int_t isec, Float_t * center) const
950 : {
951 : /// returns the default radial position
952 : /// of the readout chambers
953 :
954 : const Float_t kROCcenterIn = 110.2;
955 : const Float_t kROCcenterOut = 188.45;
956 :
957 3672 : if (isec<fNInnerSector){
958 1836 : if (center){
959 612 : center[0] = kROCcenterIn;
960 612 : center[1] = 0;
961 612 : center[2] = -5.51-0.08;
962 612 : }
963 612 : return kROCcenterIn;
964 : }
965 : else{
966 612 : if (center){
967 612 : center[0] = kROCcenterOut;
968 612 : center[1] = 0;
969 612 : center[2] = -5.61-0.08;
970 612 : }
971 612 : return kROCcenterOut;
972 : }
973 1224 : }
974 :
975 : void AliTPCParam::SetNominalGainSlopes(){
976 : /// Setting the nominal TPC gain slopes
977 : /// Nominal values were obtained as a mena values foe 2010,2011, and 2012 data
978 : /// Differntial values can be provided per year
979 :
980 72 : Float_t sector[72]={0};
981 36 : Float_t gainHV[72]={0};
982 36 : Float_t gainPT[72]={0};
983 : //
984 5256 : for (Int_t isec=0; isec<72; isec++){
985 2592 : sector[isec]=isec;
986 2592 : 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
987 2592 : gainPT[isec]=2.2; // change of the Gains dG/G per P/T change ()
988 : }
989 72 : fGainSlopesHV = new TGraphErrors(72,sector,gainHV,0,0);
990 72 : fGainSlopesPT = new TGraphErrors(72,sector,gainPT,0,0);
991 36 : fGainSlopesHV->SetName("GainSlopesHV");
992 36 : fGainSlopesPT->SetName("GainSlopesPT");
993 36 : }
994 :
995 :
996 : TVectorD * AliTPCParam::GetBetheBlochParamNa49(){
997 : /// Parameters of the BB for the Aleph parametrization AliMathBase::BetheBlochAleph
998 : /// Na49 parameters were used as first set of parameters for ALICE simulation
999 : /// (see TPC TDR for details)
1000 :
1001 0 : TVectorD v(5);
1002 0 : v(0)=0.76176e-1;
1003 0 : v(1)=10.632;
1004 0 : v(2)=0.13279e-4;
1005 0 : v(3)=1.8631;
1006 0 : v(4)=1.9479;
1007 0 : return new TVectorD(v);
1008 0 : }
1009 :
1010 : TVectorD * AliTPCParam::GetBetheBlochParamAlice(){
1011 : /// Parameters of the BB for the Aleph parametrization AliMathBase::BetheBlochAleph
1012 : /// Na49 parameters were used as first set of parameters for ALICE simulation
1013 : /// Second set was obtained from ALICE 2009-2013 data taking
1014 : /// (see TPC TDR for details)
1015 :
1016 72 : TVectorD v(5);
1017 72 : v[0] = 0.0851148;
1018 72 : v[1] = 9.25771;
1019 72 : v[2] = 2.6558e-05;
1020 72 : v[3] = 2.32742;
1021 72 : v[4] = 1.83039;
1022 72 : return new TVectorD(v);
1023 36 : }
1024 :
1025 : TVectorD * AliTPCParam::GetBetheBlochParamAliceMC(){
1026 : /// Parameters of the BB for the Aleph parametrization AliMathBase::BetheBlochAleph
1027 : /// dNdx parameterization
1028 :
1029 72 : TVectorD v(5);
1030 72 : v[0] =0.0820172 ;
1031 72 : v[1] =9.94795 ;
1032 72 : v[2] =8.97292e-05;
1033 72 : v[3] =2.05873 ;
1034 72 : v[4] =1.65272 ;
1035 :
1036 72 : return new TVectorD(v);
1037 36 : }
1038 :
1039 :
1040 : Double_t AliTPCParam::BetheBlochAleph(Double_t bg, Int_t type){
1041 : /// GetBetheBloch retur values for the parametrs regieter at poition type
1042 : /// Used for visualization and comparison purposes
1043 0 : if (bg<=0) return 0;
1044 : TVectorD * paramBB =0;
1045 0 : if (type==0) {
1046 0 : AliTPCParam* param = AliTPCcalibDB::Instance()->GetParameters();
1047 0 : if (param) paramBB=param->GetBetheBlochParameters();
1048 0 : }
1049 0 : if (type==1){
1050 0 : paramBB = (TVectorD*)fBBParam->At(type);
1051 0 : }
1052 0 : if (!paramBB) return 0;
1053 : //
1054 0 : return AliMathBase::BetheBlochAleph(bg,(*paramBB)(0),(*paramBB)(1),(*paramBB)(2),(*paramBB)(3),(*paramBB)(4));
1055 0 : }
1056 :
1057 :
1058 : void AliTPCParam::RegisterBBParam(TVectorD* param, Int_t position){
1059 : ///
1060 :
1061 0 : fBBParam->AddAt(param,position);
1062 0 : }
|