Bug fix
[u/mrichter/AliRoot.git] / FMD / AliFMDRing.cxx
1 /**************************************************************************
2  * Copyright(c) 2004, 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 /* $Id$ */
16 /** @file    AliFMDRing.cxx
17     @author  Christian Holm Christensen <cholm@nbi.dk>
18     @date    Mon Mar 27 12:47:43 2006
19     @brief   FMD ring geometry parameters 
20 */
21 //__________________________________________________________________
22 //
23 // Utility class to help implement collection of FMD modules into
24 // rings.  This is used by AliFMDDetector and AliFMDGeometry.
25 // The AliFMDGeometry object owns the AliFMDRing objects, and the
26 // AliFMDDetector objects reference these.  That is, the AliFMDRing
27 // objects are share amoung the AliFMDDetector objects.
28 //
29 // Latest changes by Christian Holm Christensen
30 //
31
32 #include <TMath.h>              // ROOT_TMath
33 #include <TVector2.h>           // ROOT_TVector2
34
35 // #include <AliLog.h>          // ALILOG_H
36 #include "AliFMDRing.h"         // ALIFMDRING_H
37
38 //====================================================================
39 ClassImp(AliFMDRing)
40 #if 0
41   ; // This is here to keep Emacs for indenting the next line
42 #endif
43
44 //____________________________________________________________________
45 AliFMDRing::AliFMDRing(Char_t id) 
46   : TNamed(Form("FMD%c", id), "Forward multiplicity ring"), 
47     fId(id), 
48     fBondingWidth(0),
49     fWaferRadius(0),
50     fSiThickness(0),
51     fLowR(0),
52     fHighR(0),
53     fMinR(0),
54     fMaxR(0),
55     fTheta(0),
56     fNStrips(0),
57     fRingDepth(0),
58     fLegRadius(0),
59     fLegLength(0),
60     fLegOffset(0),
61     fModuleSpacing(0),
62     fPrintboardThickness(0),
63     fCopperThickness(0),
64     fChipThickness(0),
65     fSpacing(0),
66     fHoneycombThickness(0.),
67     fAlThickness(0.),
68     fVerticies(0), 
69     fSensorVerticies(0),
70     fHybridVerticies(0),
71     fFeetPositions(0)
72 {
73   // CTOR
74   SetBondingWidth();
75   SetWaferRadius();
76   SetSiThickness();
77   SetLegRadius();
78   SetLegLength();
79   SetLegOffset();
80   SetModuleSpacing();
81   SetPrintboardThickness();
82   SetCopperThickness();
83   SetChipThickness();
84   SetSpacing();
85   SetHoneycombThickness();
86   SetAlThickness();
87   
88   if (fId == 'I' || fId == 'i') {
89     SetLowR(4.3);
90     SetHighR(17.2);
91     SetTheta(36/2);
92     SetNStrips(512);
93     Double_t base = 0; // 4.1915;
94     fFeetPositions.Add(new TVector2( 0.0551687, 8.0534-base));
95     fFeetPositions.Add(new TVector2( 2.9993,   12.9457-base));
96     fFeetPositions.Add(new TVector2(-2.9062,   12.9508-base));
97     
98     fHybridVerticies.Add(new TVector2(0.0000,  4.1700));
99     fHybridVerticies.Add(new TVector2(1.0574,  4.1700));
100     fHybridVerticies.Add(new TVector2(4.6614, 15.2622));
101     fHybridVerticies.Add(new TVector2(0.9643, 17.4000));
102     fHybridVerticies.Add(new TVector2(0.0000, 17.4000));
103
104     fSensorVerticies.Add(new TVector2(0.0000,  4.1915));
105     fSensorVerticies.Add(new TVector2(1.5793,  4.1915));
106     fSensorVerticies.Add(new TVector2(5.2293, 15.4251));
107     fSensorVerticies.Add(new TVector2(1.9807, 17.3035));
108     fSensorVerticies.Add(new TVector2(0.0000, 17.3035));
109
110     fVerticies.Add(new TVector2(0.0000,  4.3000));
111     fVerticies.Add(new TVector2(1.3972,  4.3000));
112     fVerticies.Add(new TVector2(4.9895, 15.3560));
113     fVerticies.Add(new TVector2(1.8007, 17.2000));
114     fVerticies.Add(new TVector2(0.0000, 17.2000));
115   }
116   else if (fId == 'O' || fId == 'o') {
117     SetLowR(15.6);
118     SetHighR(28.0);
119     SetTheta(18/2);
120     SetNStrips(256);
121     Double_t base = 0; // 14.9104;
122     fFeetPositions.Add(new TVector2(-1.72540000, 20.6267-base));
123     fFeetPositions.Add(new TVector2( 1.72900000, 20.6267-base));
124     fFeetPositions.Add(new TVector2( 0.00177616, 26.6007-base));
125
126     fHybridVerticies.Add(new TVector2(0.0000, 14.9104));
127     fHybridVerticies.Add(new TVector2(2.0783, 14.9104));
128     fHybridVerticies.Add(new TVector2(3.9202, 26.5395));
129     fHybridVerticies.Add(new TVector2(0.6784, 28.2500));
130     fHybridVerticies.Add(new TVector2(0.0000, 28.2500));
131
132     fSensorVerticies.Add(new TVector2(0.0000, 15.0104));
133     fSensorVerticies.Add(new TVector2(2.5799, 15.0104));
134     fSensorVerticies.Add(new TVector2(4.4439, 26.7766));
135     fSensorVerticies.Add(new TVector2(1.8350, 28.1500));
136     fSensorVerticies.Add(new TVector2(0.0000, 28.1500));
137
138     fVerticies.Add(new TVector2(0.0000, 15.2104));
139     fVerticies.Add(new TVector2(2.4091, 15.2104));
140     fVerticies.Add(new TVector2(4.2231, 26.6638));
141     fVerticies.Add(new TVector2(1.8357, 27.9500));
142     fVerticies.Add(new TVector2(0.0000, 27.9500));
143   }
144 }
145
146 //____________________________________________________________________
147 void
148 AliFMDRing::Init()
149 {
150   // Initialize 
151 #if 0
152   Double_t tanTheta  = TMath::Tan(fTheta * TMath::Pi() / 180.);
153   Double_t tanTheta2 = TMath::Power(tanTheta,2);
154   Double_t r2        = TMath::Power(fWaferRadius,2);
155   Double_t yA        = tanTheta * fLowR;
156   Double_t lr2       = TMath::Power(fLowR, 2);
157   Double_t hr2       = TMath::Power(fHighR,2);
158   Double_t xD        = fLowR + TMath::Sqrt(r2 - tanTheta2 * lr2);
159   Double_t xD2       = TMath::Power(xD,2);
160   Double_t yB        = TMath::Sqrt(r2 - hr2 + 2 * fHighR * xD - xD2);
161   Double_t xC        = ((xD + TMath::Sqrt(-tanTheta2 * xD2 + r2
162                                           + r2 * tanTheta2)) 
163                         / (1 + tanTheta2));
164   Double_t yC        = tanTheta * xC;
165   
166   fVerticies.Expand(6);
167   fVerticies.AddAt(new TVector2(fLowR,  -yA), 0);
168   fVerticies.AddAt(new TVector2(xC,     -yC), 1);
169   fVerticies.AddAt(new TVector2(fHighR, -yB), 2);
170   fVerticies.AddAt(new TVector2(fHighR,  yB), 3);
171   fVerticies.AddAt(new TVector2(xC,      yC), 4);
172   fVerticies.AddAt(new TVector2(fLowR,   yA), 5);  
173 #endif
174
175   // A's length. Corresponds to distance from nominal beam line to the
176   // cornor of the active silicon element. 
177   fMinR = GetVertex(1)->Mod(); // GetVertex(5)->Mod();
178   // A's length. Corresponds to distance from nominal beam line to the
179   // cornor of the active silicon element. 
180   fMaxR = fHighR;
181
182   fRingDepth = (fSiThickness + fPrintboardThickness 
183                 + fCopperThickness + fChipThickness 
184                 + fLegLength + fModuleSpacing + fSpacing);
185 }
186
187 //____________________________________________________________________
188 TVector2*
189 AliFMDRing::GetVertex(Int_t i) const
190 {
191   // Get the i'th vertex of polygon shape
192   return static_cast<TVector2*>(fVerticies.At(i));
193 }
194
195 //____________________________________________________________________
196 TVector2*
197 AliFMDRing::GetSensorVertex(Int_t i) const
198 {
199   // Get the i'th vertex of polygon shape
200   return static_cast<TVector2*>(fSensorVerticies.At(i));
201 }
202
203 //____________________________________________________________________
204 TVector2*
205 AliFMDRing::GetHybridVertex(Int_t i) const
206 {
207   // Get the i'th vertex of polygon shape
208   return static_cast<TVector2*>(fHybridVerticies.At(i));
209 }
210
211 //____________________________________________________________________
212 TVector2*
213 AliFMDRing::GetFootPosition(Int_t i) const
214 {
215   // Get the i'th vertex of polygon shape
216   return static_cast<TVector2*>(fFeetPositions.At(i));
217 }
218
219 //____________________________________________________________________
220 Double_t
221 AliFMDRing::GetStripRadius(UShort_t strip) const
222 {
223   // Return the nominal strip radius 
224   Double_t rmax     = GetMaxR();
225   Double_t stripoff = GetMinR();
226   Double_t dstrip   = (rmax - stripoff) / GetNStrips();
227   return (strip + .5) * dstrip + stripoff; // fLowR
228 }
229  
230 //____________________________________________________________________
231 Double_t
232 AliFMDRing::GetModuleDepth() const
233 {
234   return (GetSiThickness() 
235           + GetSpacing() 
236           + GetPrintboardThickness()
237           + GetCopperThickness()
238           + GetChipThickness()
239           + GetLegLength());
240   
241 }
242
243 //____________________________________________________________________
244 Double_t
245 AliFMDRing::GetFullDepth() const
246 {
247   return (GetModuleDepth() 
248           + GetModuleSpacing()
249           + GetHoneycombThickness()
250           + GetFMDDPrintboardThickness()
251           + GetFMDDCopperThickness()
252           + GetFMDDChipThickness() 
253           + 0.5);
254 }
255
256 //____________________________________________________________________
257 void
258 AliFMDRing::Detector2XYZ(UShort_t sector,
259                          UShort_t strip, 
260                          Double_t& x, 
261                          Double_t& y, 
262                          Double_t& z) const
263 {
264   // Translate detector coordinates (this,sector,strip) to global
265   // coordinates (x,y,z)
266   if (sector >= GetNSectors()) {
267     Error("Detector2XYZ", "Invalid sector number %d (>=%d) in ring %c", 
268           sector, GetNSectors(), fId);
269     return;
270   }
271   if (strip >= GetNStrips()) {
272     Error("Detector2XYZ", "Invalid strip number %d (>=%d)", 
273           strip, GetNStrips(), fId);
274     return;
275   }
276   Double_t phi = Float_t(sector + .5) / GetNSectors() * 2 * TMath::Pi();
277   Double_t r   = Float_t(strip + .5) / GetNStrips() * (fHighR - fLowR) + fLowR;
278   x = r * TMath::Cos(phi);
279   y = r * TMath::Sin(phi);
280   if (((sector / 2) % 2) == 1) 
281     z += TMath::Sign(fModuleSpacing, z);
282 }
283
284 //____________________________________________________________________
285 Bool_t
286 AliFMDRing::XYZ2Detector(Double_t  x, 
287                          Double_t  y, 
288                          Double_t  z,
289                          UShort_t& sector,
290                          UShort_t& strip) const
291 {
292   // Translate global coordinates (x,y,z) to detector coordinates
293   // (this,sector,strip)
294   sector = strip = 0;
295   Double_t r = TMath::Sqrt(x * x + y * y);
296   Int_t str = Int_t((r - fMinR) / GetPitch());
297   if (str < 0 || str >= GetNStrips()) return kFALSE;
298
299   Double_t phi = TMath::ATan2(y, x) * 180. / TMath::Pi();
300   if (phi < 0) phi = 360. + phi;
301   Int_t sec = Int_t(phi / fTheta);
302   if (sec < 0 || sec >= GetNSectors()) return kFALSE;
303   if ((sec / 2) % 2 == 1) {
304     if (TMath::Abs(z - TMath::Sign(fModuleSpacing, z)) >= 0.01)
305       return kFALSE;
306   }
307   else if (TMath::Abs(z) >= 0.01) return kFALSE;
308
309   strip  = str;
310   sector = sec;
311   return kTRUE;
312 }
313 //____________________________________________________________________
314 Float_t 
315 AliFMDRing::GetStripLength(UShort_t strip) const 
316 {
317   if(strip >= GetNStrips())
318     Error("GetStripLength", "Invalid strip number %d (>=%d)", 
319           strip, GetNStrips(), fId);
320   
321   Float_t rad        = GetMaxR()-GetMinR();
322   
323   Float_t segment    = rad / GetNStrips();
324   
325   TVector2* corner1  = GetVertex(2);  
326   TVector2* corner2  = GetVertex(3);
327   
328   Float_t slope      = (corner1->Y() - corner2->Y()) / (corner1->X() - corner2->X());
329   Float_t constant   = (corner2->Y()*corner1->X()-(corner2->X()*corner1->Y())) / (corner1->X() - corner2->X());
330   Float_t radius     = GetMinR() + strip*segment;
331   
332   Float_t d          = TMath::Power(TMath::Abs(radius*slope),2) + TMath::Power(radius,2) - TMath::Power(constant,2);
333   
334   Float_t arclength  = GetBaseStripLength(strip);
335   if(d>0) {
336     
337     Float_t x        = (-1*TMath::Sqrt(d) -slope*constant) / (1+TMath::Power(slope,2));
338     Float_t y        = slope*x + constant;
339     Float_t theta    = TMath::ATan2(x,y);
340     
341     if(x < corner1->X() && y > corner1->Y()) {
342       arclength = radius*theta;                        //One sector since theta is by definition half-hybrid
343       
344     }
345     
346   }
347   
348   return arclength;
349   
350   
351 }
352 //____________________________________________________________________
353 Float_t 
354 AliFMDRing::GetBaseStripLength(UShort_t strip) const 
355 {  
356   Float_t rad             = GetMaxR()-GetMinR();
357   Float_t segment         = rad / GetNStrips();
358   Float_t basearc         = 2*TMath::Pi() / (0.5*GetNSectors()); // One hybrid: 36 degrees inner, 18 outer
359   Float_t radius          = GetMinR() + strip*segment;
360   Float_t basearclength   = 0.5*basearc * radius;                // One sector   
361   
362   return basearclength;
363 }
364 //
365 // EOF
366 //