Export hit structure header
[u/mrichter/AliRoot.git] / FMD / AliFMDRing.cxx
... / ...
CommitLineData
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//====================================================================
39ClassImp(AliFMDRing)
40#if 0
41 ; // This is here to keep Emacs for indenting the next line
42#endif
43
44//____________________________________________________________________
45AliFMDRing::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 // Constructor
74 //
75 // Parameters:
76 // id Type of ring (either 'I' or 'O')
77 //
78 SetBondingWidth();
79 SetWaferRadius();
80 SetSiThickness();
81 SetLegRadius();
82 SetLegLength();
83 SetLegOffset();
84 SetModuleSpacing();
85 SetPrintboardThickness();
86 SetCopperThickness();
87 SetChipThickness();
88 SetSpacing();
89 SetHoneycombThickness();
90 SetAlThickness();
91
92 if (fId == 'I' || fId == 'i') {
93 SetLowR(4.3);
94 SetHighR(17.2);
95 SetTheta(36/2);
96 SetNStrips(512);
97 Double_t base = 0; // 4.1915;
98 fFeetPositions.Add(new TVector2( 0.0551687, 8.0534-base));
99 fFeetPositions.Add(new TVector2( 2.9993, 12.9457-base));
100 fFeetPositions.Add(new TVector2(-2.9062, 12.9508-base));
101
102 fHybridVerticies.Add(new TVector2(0.0000, 4.1700));
103 fHybridVerticies.Add(new TVector2(1.0574, 4.1700));
104 fHybridVerticies.Add(new TVector2(4.6614, 15.2622));
105 fHybridVerticies.Add(new TVector2(0.9643, 17.4000));
106 fHybridVerticies.Add(new TVector2(0.0000, 17.4000));
107
108 fSensorVerticies.Add(new TVector2(0.0000, 4.1915));
109 fSensorVerticies.Add(new TVector2(1.5793, 4.1915));
110 fSensorVerticies.Add(new TVector2(5.2293, 15.4251));
111 fSensorVerticies.Add(new TVector2(1.9807, 17.3035));
112 fSensorVerticies.Add(new TVector2(0.0000, 17.3035));
113
114 fVerticies.Add(new TVector2(0.0000, 4.3000));
115 fVerticies.Add(new TVector2(1.3972, 4.3000));
116 fVerticies.Add(new TVector2(4.9895, 15.3560));
117 fVerticies.Add(new TVector2(1.8007, 17.2000));
118 fVerticies.Add(new TVector2(0.0000, 17.2000));
119 }
120 else if (fId == 'O' || fId == 'o') {
121 SetLowR(15.6);
122 SetHighR(28.0);
123 SetTheta(18/2);
124 SetNStrips(256);
125 Double_t base = 0; // 14.9104;
126 fFeetPositions.Add(new TVector2(-1.72540000, 20.6267-base));
127 fFeetPositions.Add(new TVector2( 1.72900000, 20.6267-base));
128 fFeetPositions.Add(new TVector2( 0.00177616, 26.6007-base));
129
130 fHybridVerticies.Add(new TVector2(0.0000, 14.9104));
131 fHybridVerticies.Add(new TVector2(2.0783, 14.9104));
132 fHybridVerticies.Add(new TVector2(3.9202, 26.5395));
133 fHybridVerticies.Add(new TVector2(0.6784, 28.2500));
134 fHybridVerticies.Add(new TVector2(0.0000, 28.2500));
135
136 fSensorVerticies.Add(new TVector2(0.0000, 15.0104));
137 fSensorVerticies.Add(new TVector2(2.5799, 15.0104));
138 fSensorVerticies.Add(new TVector2(4.4439, 26.7766));
139 fSensorVerticies.Add(new TVector2(1.8350, 28.1500));
140 fSensorVerticies.Add(new TVector2(0.0000, 28.1500));
141
142 fVerticies.Add(new TVector2(0.0000, 15.2104));
143 fVerticies.Add(new TVector2(2.4091, 15.2104));
144 fVerticies.Add(new TVector2(4.2231, 26.6638));
145 fVerticies.Add(new TVector2(1.8357, 27.9500));
146 fVerticies.Add(new TVector2(0.0000, 27.9500));
147 }
148}
149
150//____________________________________________________________________
151void
152AliFMDRing::Init()
153{
154 // Initialize
155 //
156 // All derived quantities are calculated here.
157 //
158#if 0
159 Double_t tanTheta = TMath::Tan(fTheta * TMath::Pi() / 180.);
160 Double_t tanTheta2 = TMath::Power(tanTheta,2);
161 Double_t r2 = TMath::Power(fWaferRadius,2);
162 Double_t yA = tanTheta * fLowR;
163 Double_t lr2 = TMath::Power(fLowR, 2);
164 Double_t hr2 = TMath::Power(fHighR,2);
165 Double_t xD = fLowR + TMath::Sqrt(r2 - tanTheta2 * lr2);
166 Double_t xD2 = TMath::Power(xD,2);
167 Double_t yB = TMath::Sqrt(r2 - hr2 + 2 * fHighR * xD - xD2);
168 Double_t xC = ((xD + TMath::Sqrt(-tanTheta2 * xD2 + r2
169 + r2 * tanTheta2))
170 / (1 + tanTheta2));
171 Double_t yC = tanTheta * xC;
172
173 fVerticies.Expand(6);
174 fVerticies.AddAt(new TVector2(fLowR, -yA), 0);
175 fVerticies.AddAt(new TVector2(xC, -yC), 1);
176 fVerticies.AddAt(new TVector2(fHighR, -yB), 2);
177 fVerticies.AddAt(new TVector2(fHighR, yB), 3);
178 fVerticies.AddAt(new TVector2(xC, yC), 4);
179 fVerticies.AddAt(new TVector2(fLowR, yA), 5);
180#endif
181
182 // A's length. Corresponds to distance from nominal beam line to the
183 // cornor of the active silicon element.
184 fMinR = GetVertex(1)->Mod(); // GetVertex(5)->Mod();
185 // A's length. Corresponds to distance from nominal beam line to the
186 // cornor of the active silicon element.
187 fMaxR = fHighR;
188
189 fRingDepth = (fSiThickness + fPrintboardThickness
190 + fCopperThickness + fChipThickness
191 + fLegLength + fModuleSpacing + fSpacing);
192}
193
194//____________________________________________________________________
195TVector2*
196AliFMDRing::GetVertex(Int_t i) const
197{
198 // Get the i'th vertex of polygon shape
199 //
200 // the polygon shape describes the shape of the rings' sensors
201 //
202 // Parameters:
203 // i The vertex number to get (from 0 to 5)
204 return static_cast<TVector2*>(fVerticies.At(i));
205}
206
207//____________________________________________________________________
208TVector2*
209AliFMDRing::GetSensorVertex(Int_t i) const
210{
211 // Get the i'th vertex of polygon shape
212 //
213 // the polygon shape describes the shape of the rings' sensors
214 //
215 // Parameters:
216 // i The vertex number to get (from 0 to 5)
217 return static_cast<TVector2*>(fSensorVerticies.At(i));
218}
219
220//____________________________________________________________________
221TVector2*
222AliFMDRing::GetHybridVertex(Int_t i) const
223{
224 // Get the i'th vertex of polygon shape
225 //
226 // the polygon shape describes the shape of the rings' hybrid cards
227 //
228 // Parameters:
229 // i The vertex number to get (from 0 to 5)
230 return static_cast<TVector2*>(fHybridVerticies.At(i));
231}
232
233//____________________________________________________________________
234TVector2*
235AliFMDRing::GetFootPosition(Int_t i) const
236{
237 // Get the i'th vertex of polygon shape
238 //
239 // The feet are attached to the hybrid cards
240 //
241 // Parameters:
242 // i The foot number to get (from 0 to 2)
243 return static_cast<TVector2*>(fFeetPositions.At(i));
244}
245
246//____________________________________________________________________
247Double_t
248AliFMDRing::GetStripRadius(UShort_t strip) const
249{
250 // Return the nominal strip radius
251 //
252 // Parameter
253 // strip Strip number (0-511 for inners, 0-255 for outers)
254 Double_t rmax = GetMaxR();
255 Double_t stripoff = GetMinR();
256 Double_t dstrip = (rmax - stripoff) / GetNStrips();
257 return (strip + .5) * dstrip + stripoff; // fLowR
258}
259
260//____________________________________________________________________
261Double_t
262AliFMDRing::GetModuleDepth() const
263{
264 // Get the total depth of a module (sensor + hybrid card)
265 //
266 // The depth is the sum of
267 //
268 // The silicon thickness
269 // The thickness of spacers between the silicon and hybrid
270 // The thickness of the hybrid PCB
271 // The thickness of the copper layer in the PCB
272 // The thickness of the chip layer in the PCB
273 // The height of the legs
274 return (GetSiThickness()
275 + GetSpacing()
276 + GetPrintboardThickness()
277 + GetCopperThickness()
278 + GetChipThickness()
279 + GetLegLength());
280
281}
282
283//____________________________________________________________________
284Double_t
285AliFMDRing::GetFullDepth() const
286{
287 // Get the full depth of this ring, including the honeycomb,
288 // digitizer and card.
289 return (GetModuleDepth()
290 + GetModuleSpacing()
291 + GetHoneycombThickness()
292 + GetFMDDPrintboardThickness()
293 + GetFMDDCopperThickness()
294 + GetFMDDChipThickness()
295 + 0.5);
296}
297
298//____________________________________________________________________
299void
300AliFMDRing::Detector2XYZ(UShort_t sector,
301 UShort_t strip,
302 Double_t& x,
303 Double_t& y,
304 Double_t& z) const
305{
306 // Translate detector coordinates (this,sector,strip) to global
307 // coordinates (x,y,z)
308 //
309 // Parameters
310 // sector Sector number in this ring
311 // strip Strip number in this ring
312 // x On return, the global X coordinate
313 // y On return, the global Y coordinate
314 // z On return, the z coordinate in the ring plane
315 //
316 // The ring plane is the plane half way between the two sensor
317 // layers.
318 if (sector >= GetNSectors()) {
319 Error("Detector2XYZ", "Invalid sector number %d (>=%d) in ring %c",
320 sector, GetNSectors(), fId);
321 return;
322 }
323 if (strip >= GetNStrips()) {
324 Error("Detector2XYZ", "Invalid strip number %d (>=%d) for ring type '%c'",
325 strip, GetNStrips(), fId);
326 return;
327 }
328 Double_t phi = Float_t(sector + .5) / GetNSectors() * 2 * TMath::Pi();
329 Double_t r = Float_t(strip + .5) / GetNStrips() * (fHighR - fLowR) + fLowR;
330 x = r * TMath::Cos(phi);
331 y = r * TMath::Sin(phi);
332 if (((sector / 2) % 2) == 1)
333 z += TMath::Sign(fModuleSpacing, z);
334}
335
336//____________________________________________________________________
337Bool_t
338AliFMDRing::XYZ2Detector(Double_t x,
339 Double_t y,
340 Double_t z,
341 UShort_t& sector,
342 UShort_t& strip) const
343{
344 // Translate global coordinates (x,y,z) to detector coordinates
345 // (this,sector,strip)
346 //
347 // Parameters:
348 // x Global x coordinate
349 // y Global y coordinate
350 // z Global y coordinate
351 // sector On return, the sector number in this ring
352 // strip On return, the strip number in this ring
353 //
354 sector = strip = 0;
355 Double_t r = TMath::Sqrt(x * x + y * y);
356 Int_t str = Int_t((r - fMinR) / GetPitch());
357 if (str < 0 || str >= GetNStrips()) return kFALSE;
358
359 Double_t phi = TMath::ATan2(y, x) * 180. / TMath::Pi();
360 if (phi < 0) phi = 360. + phi;
361 Int_t sec = Int_t(phi / fTheta);
362 if (sec < 0 || sec >= GetNSectors()) return kFALSE;
363 if ((sec / 2) % 2 == 1) {
364 if (TMath::Abs(z - TMath::Sign(fModuleSpacing, z)) >= 0.01)
365 return kFALSE;
366 }
367 else if (TMath::Abs(z) >= 0.01) return kFALSE;
368
369 strip = str;
370 sector = sec;
371 return kTRUE;
372}
373//____________________________________________________________________
374Float_t
375AliFMDRing::GetStripLength(UShort_t strip) const
376{
377 // Get the length of a strip
378 //
379 // Parameters:
380 // strip Strip number (0-511 for inners, 0-255 for outers)
381 //
382 if(strip >= GetNStrips())
383 Error("GetStripLength", "Invalid strip number %d (>=%d) for ring type %c",
384 strip, GetNStrips(), fId);
385
386 Float_t rad = GetMaxR()-GetMinR();
387
388 Float_t segment = rad / GetNStrips();
389
390 TVector2* corner1 = GetVertex(2);
391 TVector2* corner2 = GetVertex(3);
392
393 Float_t slope = ((corner1->Y() - corner2->Y()) /
394 (corner1->X() - corner2->X()));
395 Float_t constant = ((corner2->Y() * corner1->X() -
396 (corner2->X()*corner1->Y())) /
397 (corner1->X() - corner2->X()));
398 Float_t radius = GetMinR() + strip*segment;
399
400 Float_t d = (TMath::Power(TMath::Abs(radius*slope),2) +
401 TMath::Power(radius,2) - TMath::Power(constant,2));
402
403 Float_t arclength = GetBaseStripLength(strip);
404 if(d>0) {
405 Float_t x = ((-1 * TMath::Sqrt(d) -slope*constant) /
406 (1 + TMath::Power(slope,2)));
407 Float_t y = slope*x + constant;
408 Float_t theta = TMath::ATan2(x,y);
409
410 if(x < corner1->X() && y > corner1->Y()) {
411 //One sector since theta is by definition half-hybrid
412 arclength = radius*theta;
413 }
414 }
415
416 return arclength;
417
418
419}
420//____________________________________________________________________
421Float_t
422AliFMDRing::GetBaseStripLength(UShort_t strip) const
423{
424 // Get the basic strip length
425 //
426 // Parameters:
427 // strip Strip number
428 Float_t rad = GetMaxR()-GetMinR();
429 Float_t segment = rad / GetNStrips();
430 Float_t basearc = 2*TMath::Pi() / (0.5*GetNSectors());
431 Float_t radius = GetMinR() + strip*segment;
432 Float_t basearclength = 0.5*basearc * radius;
433
434 return basearclength;
435}
436//
437// EOF
438//