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