25ef352d3f88a8eb0faf6bdfd0029a56290e943c
[u/mrichter/AliRoot.git] / TPC / AliTPCParam.cxx
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 $Log$
18 */
19
20 ///////////////////////////////////////////////////////////////////////
21 //  Manager and of geomety  classes for set: TPC                     //
22 //                                                                   //
23 //  !sectors are numbered from  0                                     //
24 //  !pad rows are numbered from 0                                     //
25 //  
26 //  12.6.   changed z relative 
27 //  Origin:  Marian Ivanov, Uni. of Bratislava, ivanov@fmph.uniba.sk // 
28 //                                                                   //  
29 ///////////////////////////////////////////////////////////////////////
30
31
32 #include <iostream.h>
33 #include <TMath.h>
34 #include <TObject.h>
35 #include "AliTPCSecGeo.h"
36 #include <AliTPCParam.h>
37
38
39 ClassImp(AliTPCParam)
40
41 const static  Int_t kMaxRows=600;
42
43
44 // default values  
45 const static   Int_t kMaxTBin =512; 
46
47
48 const static  Float_t kInnerRadiusLow = 89.45;
49 const static  Float_t kOuterRadiusLow = 143.725;
50 const static  Float_t kInnerRadiusUp  = 134.55;
51 const static  Float_t kOuterRadiusUp  = 248.275;
52
53 const static  Float_t kInnerAngle = 0.523598775; // 30 degrees
54 const static  Float_t kInnerAngleShift = 0;
55 const static  Float_t kOuterAngle = 0.261799387; //  15 degrees
56 const static  Float_t kOuterAngleShift = 0;
57
58 const static Float_t kPadPitchLength = 2.05;
59 const static Float_t kPadPitchWidth = 0.35;
60 const static Float_t kPadLength = 2.05;
61 const static Float_t kPadWidth = 0.35;
62
63 //  Number of wires per pad and wire-wire pitch
64 const static Int_t knWires = 5;
65 const static  Float_t  kDiffT = 2.2e-2; 
66 const static  Float_t  kDiffL = 2.2e-2; 
67 const static  Float_t  kDriftV  =2.85e6;
68
69 const static  Float_t  kOmegaTau = 0.145;
70 const static  Float_t  kAttCoef = 250.;
71 const static  Float_t  kOxyCont = 5.e-6;
72
73
74 const static  Float_t  kChipGain = 24;
75 const static  Float_t  kGasGain = 1e4;
76 const static  Float_t  kTSample = 2.e-7; //TSAMPLE
77 const static  Float_t  kTFWHM   = 2.5e-7;  //fwhm of charge distribution
78  
79 const static  Float_t  kNoise = 500;  //default noise = 1000 el 
80 const static  Int_t    kZeroSup=5;
81 const static  Float_t  kPadCoupling=0.5;
82 // 
83 const static  Float_t  kEdgeSectorSpace = 1.15;
84 const static  Float_t  kDegtoRad = 0.01745329251994;
85 const static  Float_t  kRadtoDeg = 57.29577951309;
86
87
88
89
90 //___________________________________________
91 AliTPCParam::AliTPCParam()
92 {   
93   //constructor set the default parameters
94   SetDefault();  
95 }
96
97
98 void  AliTPCParam::SetSectorAngles(Float_t innerangle, Float_t innershift, Float_t outerangle,
99                         Float_t outershift, Bool_t inDegree)
100 {
101   //
102   // set opening angles  
103   fInnerAngle = innerangle;       //opening angle of Inner sector
104   fInnerAngleShift = innershift;  //shift of first inner sector center to the 0
105   fOuterAngle = outerangle;       //opening angle of outer sector
106   fOuterAngleShift = outershift;  //shift of first sector center to the 0  
107   if (inDegree==kTRUE){
108     fInnerAngle *=kDegtoRad;
109     fInnerAngleShift *=kDegtoRad;
110     fOuterAngle *=kDegtoRad;
111     fOuterAngleShift *=kDegtoRad;
112   }    
113 }
114
115
116 void AliTPCParam::CRXYZtoXYZ(Float_t *xyz,
117                const Int_t &sector, const Int_t & padrow, Int_t option) const  
118 {  
119   //transform relative coordinates to absolute
120   Bool_t rel = ( (option&2)!=0);
121   Float_t row_first; 
122   row_first = (sector<=fNInnerSector) ? fPadRowLow[0] : fPadRowUp[0]; 
123   if (rel==kTRUE)  //if the position is relative to pad row  
124     {
125       xyz[0]+=row_first;
126       xyz[0]+=(Int_t) padrow*fPadPitchLength;
127     }  
128
129   xyz[2]=z_end-xyz[2];
130   if (sector<fNInnerSector) {
131     if ( sector>=(fNInnerSector>>1))    xyz[2]*=-1.;
132   } else {
133     if ( (sector-fNInnerSector) >= (fNOuterSector>>1) )    xyz[2]*=-1;
134   }
135
136   Float_t x1=xyz[0];
137   Float_t y1=xyz[1];
138   Float_t cos,sin;
139   AdjustAngles(sector,cos,sin);
140   xyz[0]= x1*cos - y1*sin;
141   xyz[1]= x1*sin + y1*cos;
142 }
143
144 void AliTPCParam::XYZtoCRXYZ(Float_t *xyz,
145                              Int_t &sector, Int_t & padrow, Int_t option)
146 {
147    //transform global position to the position relative to the sector padrow
148   //if option=0  X calculate absolute            calculate sector
149   //if option=1  X           absolute            use input sector
150   //if option=2  X           relative to pad row calculate sector
151   //if option=3  X           relative            use input sector
152   //!!!!!!!!! WE start to calculate rows from row = 0
153   
154   Bool_t rel = ( (option&2)!=0);  
155   //option 0 and 2  means that we don't have information about sector
156   //we calculate sector
157   if ((option&1)==0){
158     Float_t angle;
159     Float_t r = TMath::Sqrt(xyz[0]*xyz[0]+xyz[1]*xyz[1]);
160     if ((xyz[0]==0)&&(xyz[1]==0)) angle = 0;
161     else
162       {
163         angle =TMath::ASin(xyz[1]/r);
164         if   (xyz[0]<0)   angle=TMath::Pi()-angle;
165         if ( (xyz[0]>0) && (xyz[1]<0) ) angle=2*TMath::Pi()+angle;
166       }
167     //transform global position to the position relative to the sector padrow
168     //fistly calculate xyz[0] radius  for lover sector
169     //bacause in this moment we dont know in which sector we are
170     sector=Int_t((angle-fInnerAngleShift)/fInnerAngle);      
171     Float_t x1;
172     Float_t y1;
173     //firstly we suppose that we are in inner sector
174     Float_t cos,sin;
175     AdjustAngles(sector,cos,sin);
176
177     x1=xyz[0]*cos + xyz[1]*sin;
178     y1=-xyz[0]*sin + xyz[1]*cos;
179     if (x1>fOuterRadiusLow)
180       {
181         sector=Int_t((angle-fOuterAngleShift)/fOuterAngle)+fNInnerSector;
182         AdjustAngles(sector,cos,sin);        
183         x1=xyz[0]*cos + xyz[1]*sin;
184         y1=-xyz[0]*sin + xyz[1]*cos;      
185         if (xyz[2]<0)   sector+=(fNOuterSector>>1);            
186       }
187     else   
188       if (xyz[2]<0) sector+=(fNInnerSector>>1);    
189
190   if  (x1<fOuterRadiusLow)   
191     padrow =Int_t( (x1-fPadRowLow[0])/fPadPitchLength+0.5);
192   else
193     padrow = Int_t( (x1-fPadRowUp[0])/fPadPitchLength+0.5);
194   if (rel==kTRUE)
195       if (x1<fOuterRadiusLow)   x1-=padrow*fPadPitchLength+fPadRowLow[0];
196       else
197         x1-=padrow*fPadPitchLength+fPadRowUp[0];  
198    xyz[0]=x1;
199    xyz[1]=y1;    
200    xyz[2]=z_end-TMath::Abs(xyz[2]);  
201   }   //endif we don't have information about sector
202   else{
203     //if we have information about sector
204     Float_t cos,sin;
205     AdjustAngles(sector,cos,sin);   
206     Float_t x1;
207     Float_t y1;
208     //rotate to given sector
209     x1=xyz[0]*cos + xyz[1]*sin;
210     y1=-xyz[0]*sin + xyz[1]*cos; 
211     //calculate pad row number
212     if (sector<fNInnerSector) {
213       padrow =Int_t( (x1-fPadRowLow[0])/fPadPitchLength+1.5)-1;
214     }
215     else {
216       padrow =Int_t( (x1-fPadRowUp[0])/fPadPitchLength+1.5)-1;
217     }
218     //if we store relative position calculate position relative to pad row
219     if (rel==kTRUE){
220       if (sector<fNInnerSector)
221         x1-=padrow*fPadPitchLength+fPadRowLow[0];
222       else 
223         x1-=padrow*fPadPitchLength+fPadRowUp[0];
224     }      
225     xyz[0]=x1;
226     xyz[1]=y1;
227     xyz[2]=z_end-TMath::Abs(xyz[2]);  
228   }
229 }
230
231 void AliTPCParam::CRYZtoTimePad(const Float_t &y, const Float_t &z,
232                                 Float_t &time, Float_t &pad,
233                                 Int_t sector, Int_t padrow)
234 {
235   //transform position in cm to position in time slices and pads
236   Float_t  nofpads = GetNPads(sector,padrow);
237   Float_t padc=(nofpads+1)/2; // this is the "central" pad for a row
238   pad = y/(fPadPitchWidth)+padc;
239   time=z/fZWidth;  
240 }
241 void AliTPCParam::CRTimePadtoYZ(Float_t &y, Float_t &z,
242                                 const Float_t &time, const Float_t &pad,
243                                 Int_t sector, Int_t padrow)
244 {
245   //transform position in time slices and pads  to cm 
246    Float_t  nofpads = GetNPads(sector,padrow);
247    Float_t padc=(nofpads+1)/2; // this is the "central" pad for a row
248    y=(pad-padc)*fPadPitchWidth;
249    z=time*fZWidth;
250 }
251
252 Int_t AliTPCParam::GetWire(Float_t & x)
253 {
254   //
255   //return wire number of pad for electron at relative position x
256   //to the center of the pad
257   //and adjust x to the wire position
258   //we suppose that if the wire number is even the center wire
259   //is at center of pad
260   //
261   Float_t xrel= x/fWWPitch;
262   if ((fnWires>>1)==0) xrel+=1;
263   else  xrel+=0.5;
264   Int_t nw=Int_t(xrel);
265   if (xrel<0) nw-=1;
266   
267   x=(nw*fWWPitch);
268   if ((fnWires>>1)==0) x-=fWWPitch/2.;
269   return nw;
270 }
271
272 Int_t AliTPCParam::GetIndex(Int_t sector, Int_t row)
273 {
274   //
275   //give index of the given sector and pad row 
276   //no control if the sectors and rows  are reasonable !!!
277   //
278   if (sector<fNInnerSector) return sector*fnRowLow+row;
279   return (fNInnerSector*fnRowLow)+(sector-fNInnerSector)*fnRowUp+row;  
280 }
281
282 Bool_t   AliTPCParam::AdjustSectorRow(Int_t index, Int_t & sector, Int_t &row)
283 {
284   //
285   //return sector and padrow for given index
286   //if index is reasonable return true else return false
287   //
288   if ( (index<0) || (index>fNtRows))  return kFALSE;
289   Int_t outindex = fNInnerSector*fnRowLow;
290   if (index<outindex) {
291     sector = index/fnRowLow;
292     row    = index - sector*fnRowLow;
293     return kTRUE;
294   }
295   index-= outindex;
296   sector = index/fnRowUp;
297   row    = index - sector*fnRowUp;
298   return kTRUE;         
299
300
301
302
303 Int_t AliTPCParam::GetPadRow(Int_t isec, Float_t  &x)
304 {
305   //
306   //return the pad row for given x (transformed) 
307   //
308   Float_t row_first=GetPadRowRadii(isec,0);
309   Int_t row = Int_t(( x-row_first+1.5*fPadPitchLength)/fPadPitchLength)-1;
310   //Int_t will make from -0.5 0 but we want to make -1 so we add and after substract 1
311   x -=row* fPadPitchLength+row_first;
312   if (  (row<0)||(row>=GetNRow(isec))) return -1;
313   else return row;  
314 }
315
316 void AliTPCParam::SetDefault()
317 {
318   //set default TPC param   
319   fbStatus = kFALSE;
320   //set sector  parameters
321   fInnerRadiusLow = kInnerRadiusLow;
322   fOuterRadiusLow = kOuterRadiusLow;
323   fInnerRadiusUp  = kInnerRadiusUp;
324   fOuterRadiusUp  = kOuterRadiusUp;   
325   SetSectorAngles(kInnerAngle,kInnerAngleShift, kOuterAngle, kOuterAngleShift); 
326   // set default pad size and shape
327   fPadPitchLength  = kPadPitchLength;
328   fPadPitchWidth   = kPadPitchWidth;
329   fPadLength  = kPadLength;
330   fPadWidth   = kPadWidth;   
331   //
332   fnWires = knWires;
333   fWWPitch= kPadPitchLength/Float_t(knWires);
334   fDiffT  = kDiffT;
335   fDiffL  = kDiffL;
336   fOmegaTau = kOmegaTau;
337   fOxyCont  = kOxyCont;
338   fAttCoef  = kAttCoef;
339   fNoise  = kNoise;
340   fChipGain = kChipGain;
341   fGasGain = kGasGain;
342   fZeroSup= kZeroSup;
343   fPadCoupling= kPadCoupling;
344   fTSample =kTSample;
345   fTSigma  =kTFWHM/2.35; 
346   fDriftV=kDriftV;  
347   fMaxTBin = kMaxTBin;
348   fbStatus = Update();
349 }
350
351 void  AliTPCParam::AdjustAngles(Int_t isec, Float_t &cos, Float_t &sin) const
352 {
353   //
354   //set cosinus and sinus of rotation angles for sector isec
355   //
356   cos=fRotAngle[isec*2];
357   sin=fRotAngle[isec*2+1];
358 }
359           
360 Bool_t AliTPCParam::Update()
361 {
362   //
363   // update some calculated parameter which must be updated after changing "base"
364   // parameters 
365   // for example we can change size of pads and according this recalculate number
366   // of pad rows, number of of pads in given row ....
367   //
368   fbStatus = kFALSE;
369
370   Int_t i,j;  //loop variables because HP 
371   //-----------------Sector section------------------------------------------
372   //calclulate number of sectors
373   fNInnerSector = Int_t(4*TMath::Pi()/fInnerAngle+0.2); // number of inner sectors - factor 0.2 to don't
374   //be influnced by inprecision
375   if (fNInnerSector%2) return kFALSE;
376   fNOuterSector = Int_t(4*TMath::Pi()/fOuterAngle+0.2); 
377   if (fNOuterSector%2) return kFALSE;
378   fNSector  = fNInnerSector+fNOuterSector;
379   //calculate sin and cosine of rotations angle     
380   //sectors angles numbering from 0
381   j=fNInnerSector;
382   Float_t angle = fInnerAngleShift; 
383   for (i=0; i<fNInnerSector*2; i+=2, j+=2 , angle +=fInnerAngle){
384     fRotAngle[i]=TMath::Cos(angle);
385     fRotAngle[i+1]=TMath::Sin(angle);
386     fRotAngle[j] =  fRotAngle[i];
387     fRotAngle[j+1] =  fRotAngle[i+1];
388   }
389   angle = fOuterAngleShift; 
390   j=(fNInnerSector+fNOuterSector/2)*2;
391   for (i=fNInnerSector*2; i<fNSector*2; i+=2,j+=2, angle +=fOuterAngle){
392     fRotAngle[i]=TMath::Cos(angle);
393     fRotAngle[i+1]=TMath::Sin(angle);
394     fRotAngle[j] =  fRotAngle[i];
395     fRotAngle[j+1] =  fRotAngle[i+1];
396   }
397
398   
399   //----------------PAD section------------------------------------
400   //recalculate and check some geometric parameters 
401   if (0.001>fPadPitchLength){
402     cout<<"ERROR !!! Small pad pitch length \n"<<flush;
403     return kFALSE;
404   }
405   if (fPadPitchLength<fPadLength) {
406     cout<<"ERROR !!! Pitch length  smaller then length of pad \n"<<flush;
407     return kFALSE;
408   } 
409   fnRowUp   = Int_t((0.01+fOuterRadiusUp-fOuterRadiusLow)/fPadPitchLength)+1; 
410   if ( kMaxRows<fnRowUp) fnRowUp = kMaxRows;
411   if (1>fnRowUp) return kFALSE;
412
413   fnRowLow   = Int_t((0.01+fInnerRadiusUp-fInnerRadiusLow)/fPadPitchLength)+1;
414   if ( kMaxRows<fnRowLow) fnRowUp = kMaxRows;
415   if (1>fnRowLow) return kFALSE;
416   // adjust upper sectors pad row positions and pad numbers
417   for (i = 0;i<fnRowUp;i++) 
418     {
419        Float_t x  = fOuterRadiusLow +fPadPitchLength*(Float_t)i;
420        //Float_t y =  x*2*tan(alpha_up/2)-kEdgeSectorSpace;
421        Float_t y = (x-0.5*fPadPitchLength)*tan(fOuterAngle/2)-kEdgeSectorSpace
422        -fPadPitchWidth/2.;
423        fPadRowUp[i] = x;
424        fnPadsUp[i] = 1+2*(Int_t)(y/fPadPitchWidth) ;        
425        
426     }
427   // adjust lower sectors pad row positions and pad numbers 
428   for (i = 0;i<fnRowLow;i++) 
429     {
430        Float_t x  = fInnerRadiusLow +fPadPitchLength*(Float_t)i;
431        //  Float_t y =  x*2*tan(alpha_low/2)-kEdgeSectorSpace;
432        Float_t y = (x-0.5*fPadPitchLength)*tan(fInnerAngle/2)-kEdgeSectorSpace
433        -fPadPitchWidth/2.;
434        fPadRowLow[i] = x;
435        fnPadsLow[i] = 1+2*(Int_t)(y/fPadPitchWidth) ;
436          
437     }
438
439   //that variable are not writen to the file there are calculated
440   //
441   fWWPitch= fPadPitchLength/Float_t(fnWires);
442   fZWidth = fTSample*fDriftV;  
443   fNtRows = fNInnerSector*fnRowLow+fNOuterSector*fnRowUp;
444   fbStatus = kTRUE;
445   return kTRUE;
446 }
447
448
449
450 Bool_t AliTPCParam::GetStatus()
451 {
452   //get information about object consistency
453   return fbStatus;
454 }
455
456 Int_t AliTPCParam::GetNRowLow() const
457 {
458   //get the number of pad rows in low sector
459   return fnRowLow;
460 }
461 Int_t AliTPCParam::GetNRowUp() const
462 {
463   //get the number of pad rows in up sector
464   return fnRowUp;
465 }
466 Float_t AliTPCParam::GetPadRowRadiiLow(Int_t irow) const
467 {
468   //get the pad row (irow) radii
469   if ( !(irow<0) && (irow<fnRowLow) ) 
470     return  fPadRowLow[irow];
471   else
472     return 0;
473 }
474
475 Float_t AliTPCParam::GetPadRowRadiiUp(Int_t irow) const
476 {
477   //get the pad row (irow) radii
478  if ( !(irow<0) && (irow<fnRowUp) ) 
479     return  fPadRowUp[irow];
480   else
481     return 0;
482 }
483
484 Int_t AliTPCParam::GetNPadsLow(Int_t irow) const
485 {
486   //get the number of pads in row irow
487   if ( !(irow<0) && (irow<fnRowLow) ) 
488     return  fnPadsLow[irow];
489   else
490     return 0;
491 }
492
493
494 Int_t AliTPCParam::GetNPadsUp(Int_t irow) const
495 {
496   //get the number of pads in row irow
497   if ( !(irow<0) && (irow<fnRowUp) ) 
498     return  fnPadsUp[irow];
499   else
500     return 0;
501 }
502
503
504 void AliTPCParam::Streamer(TBuffer &R__b)
505 {
506    // Stream an object of class AliTPC.
507
508    if (R__b.IsReading()) {
509       Version_t R__v = R__b.ReadVersion(); if (R__v) { }
510       TObject::Streamer(R__b);
511       if (R__v < 2) return;
512       //sector parameters      
513       R__b >> fInnerRadiusLow;
514       R__b >> fInnerRadiusUp;
515       R__b >> fOuterRadiusLow;
516       R__b >> fOuterRadiusUp;
517       R__b >> fInnerAngle;
518       R__b >> fInnerAngleShift;
519       R__b >> fOuterAngle;
520       R__b >> fOuterAngleShift;
521       //pad parameters
522       R__b >> fPadPitchLength;
523       R__b >> fPadPitchWidth;
524       R__b >> fPadLength;
525       R__b >> fPadWidth;
526
527       R__b >> fnWires;
528       //gas parameters
529       R__b >>fDiffT;
530       R__b >>fDiffL;
531       R__b >>fGasGain;
532       R__b >>fDriftV;
533       R__b >>fOmegaTau;
534       R__b >>fOxyCont;
535       R__b >>fAttCoef;
536       
537       R__b >>fPadCoupling;
538       R__b >>fZeroSup;
539       R__b >>fNoise;
540       R__b >>fChipGain;
541       
542       R__b >>fTSample;
543       R__b >>fTSigma;     
544       //
545       Update();
546    } else {
547       R__b.WriteVersion(AliTPCParam::IsA());
548       TObject::Streamer(R__b);      
549       R__b << fInnerRadiusLow;
550       R__b << fInnerRadiusUp;
551       R__b << fOuterRadiusLow;
552       R__b << fOuterRadiusUp;
553       R__b << fInnerAngle;
554       R__b << fInnerAngleShift;
555       R__b << fOuterAngle;
556       R__b << fOuterAngleShift;
557
558       R__b << fPadPitchLength;
559       R__b << fPadPitchWidth;
560       R__b << fPadLength;
561       R__b << fPadWidth;
562
563       R__b << fnWires;
564       
565       R__b <<fDiffT;
566       R__b <<fDiffL;
567       R__b <<fGasGain;
568       R__b <<fDriftV;
569       R__b <<fOmegaTau;
570       R__b <<fOxyCont;
571       R__b <<fAttCoef;
572
573
574       R__b <<fPadCoupling;
575       R__b <<fZeroSup;
576       R__b <<fNoise;
577       R__b <<fChipGain;
578       
579       R__b <<fTSample;
580       R__b <<fTSigma;                              
581    }
582 }
583