]>
Commit | Line | Data |
---|---|---|
4347b38f | 1 | /************************************************************************** |
c4bcfd14 | 2 | * Copyright(c) 2004, ALICE Experiment at CERN, All rights reserved. * |
4347b38f | 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 | /* $Id$ */ | |
17 | ||
c4bcfd14 | 18 | //__________________________________________________________________ |
4347b38f | 19 | // |
20 | // Utility class to help implement collection of FMD modules into | |
21 | // rings. This is used by AliFMDSubDetector and AliFMD. | |
22 | // | |
23 | // The AliFMD object owns the AliFMDRing objects, and the | |
24 | // AliFMDSubDetector objects reference these. That is, the AliFMDRing | |
25 | // objects are share amoung the AliFMDSubDetector objects. | |
26 | // | |
27 | // Latest changes by Christian Holm Christensen | |
28 | // | |
5edc364e | 29 | |
36bffea9 | 30 | #include <math.h> // fmod |
56b1929b | 31 | #include <AliLog.h> // ALILOG_H |
e802be3e | 32 | #include "AliFMDRing.h" // ALIFMDRING_H |
7e54281f | 33 | #include "AliFMD.h" // ALIFMD_H |
56b1929b | 34 | #include <TMath.h> // ROOT_TMath |
35 | #include <TH2.h> // ROOT_TH2 | |
36 | #include <TVirtualMC.h> // ROOT_TVirtualMC | |
37 | #include <TVector2.h> // ROOT_TVector2 | |
38 | #include <TBrowser.h> // ROOT_TBrowser | |
39 | #include <TString.h> // ROOT_TString | |
40 | #include <TArc.h> // ROOT_TArc | |
41 | #include <TObjArray.h> // ROOT_TObjArray | |
42 | #include <TXTRU.h> // ROOT_TXTRU | |
43 | #include <TNode.h> // ROOT_TNode | |
44 | #include <TRotMatrix.h> // ROOT_TRotMatrix | |
45 | #include <TList.h> // ROOT_TList | |
4347b38f | 46 | |
7e54281f | 47 | const Char_t* AliFMDRing::fgkRingFormat = "F%cRG"; |
48 | const Char_t* AliFMDRing::fgkVirtualFormat = "F%cV%c"; | |
49 | const Char_t* AliFMDRing::fgkActiveFormat = "F%cAC"; | |
50 | const Char_t* AliFMDRing::fgkSectorFormat = "F%cAP"; | |
51 | const Char_t* AliFMDRing::fgkStripFormat = "F%cAR"; | |
52 | const Char_t* AliFMDRing::fgkPrintboardFormat = "F%cP%c"; | |
42403906 | 53 | |
54 | ||
55 | //____________________________________________________________________ | |
925e6570 | 56 | ClassImp(AliFMDRing) |
4347b38f | 57 | |
58 | //____________________________________________________________________ | |
4347b38f | 59 | AliFMDRing::AliFMDRing(Char_t id, Bool_t detailed) |
60 | : fId(id), | |
61 | fDetailed(detailed), | |
c4bcfd14 | 62 | fActiveId(0), |
63 | fPrintboardBottomId(0), | |
64 | fPrintboardTopId(0), | |
65 | fRingId(0), | |
66 | fSectionId(0), | |
67 | fStripId(0), | |
68 | fVirtualBackId(0), | |
69 | fVirtualFrontId(0), | |
70 | fBondingWidth(0), | |
4347b38f | 71 | fWaferRadius(0), |
72 | fSiThickness(0), | |
73 | fLowR(0), | |
74 | fHighR(0), | |
75 | fTheta(0), | |
76 | fNStrips(0), | |
c4bcfd14 | 77 | fRingDepth(0), |
78 | fLegRadius(0), | |
79 | fLegLength(0), | |
80 | fLegOffset(0), | |
81 | fModuleSpacing(0), | |
82 | fPrintboardThickness(0), | |
4347b38f | 83 | fShape(0), |
84 | fRotMatricies(0) | |
42403906 | 85 | { |
86 | // Construct a alifmdring. | |
87 | // | |
88 | // id Id of the ring (either 'i' or 'o'). | |
c4bcfd14 | 89 | // detailed Whether the strips are made or not. |
90 | // | |
91 | } | |
92 | ||
93 | //____________________________________________________________________ | |
94 | AliFMDRing::AliFMDRing(const AliFMDRing& other) | |
95 | : TObject(other), | |
96 | fId(other.fId), | |
97 | fDetailed(other.fDetailed), | |
98 | fActiveId(other.fActiveId), | |
99 | fPrintboardBottomId(other.fPrintboardBottomId), | |
100 | fPrintboardTopId(other.fPrintboardTopId), | |
101 | fRingId(other.fRingId), | |
102 | fSectionId(other.fSectionId), | |
103 | fStripId(other.fStripId), | |
104 | fVirtualBackId(other.fVirtualBackId), | |
105 | fVirtualFrontId(other.fVirtualFrontId), | |
106 | fBondingWidth(other.fBondingWidth), | |
107 | fWaferRadius(other.fWaferRadius), | |
108 | fSiThickness(other.fSiThickness), | |
109 | fLowR(other.fLowR), | |
110 | fHighR(other.fHighR), | |
111 | fTheta(other.fTheta), | |
112 | fNStrips(other.fNStrips), | |
113 | fRingDepth(other.fRingDepth), | |
114 | fLegRadius(other.fLegRadius), | |
115 | fLegLength(other.fLegLength), | |
116 | fLegOffset(other.fLegOffset), | |
117 | fModuleSpacing(other.fModuleSpacing), | |
118 | fPrintboardThickness(other.fPrintboardThickness), | |
119 | fRotations(other.fRotations), | |
120 | fShape(other.fShape), | |
121 | fRotMatricies(other.fRotMatricies) | |
122 | { | |
123 | // Copy constructor of a AliFMDRing. | |
124 | } | |
125 | ||
126 | //____________________________________________________________________ | |
127 | AliFMDRing& | |
128 | AliFMDRing::operator=(const AliFMDRing& other) | |
129 | { | |
130 | // Assignment operator | |
131 | // | |
132 | fId = other.fId; | |
133 | fDetailed = other.fDetailed; | |
134 | fActiveId = other.fActiveId; | |
135 | fPrintboardBottomId = other.fPrintboardBottomId; | |
136 | fPrintboardTopId = other.fPrintboardTopId; | |
137 | fRingId = other.fRingId; | |
138 | fSectionId = other.fSectionId; | |
139 | fStripId = other.fStripId; | |
140 | fVirtualBackId = other.fVirtualBackId; | |
141 | fVirtualFrontId = other.fVirtualFrontId; | |
142 | fBondingWidth = other.fBondingWidth; | |
143 | fWaferRadius = other.fWaferRadius; | |
144 | fSiThickness = other.fSiThickness; | |
145 | fLowR = other.fLowR; | |
146 | fHighR = other.fHighR; | |
147 | fTheta = other.fTheta; | |
148 | fNStrips = other.fNStrips; | |
149 | fRingDepth = other.fRingDepth; | |
150 | fLegRadius = other.fLegRadius; | |
151 | fLegLength = other.fLegLength; | |
152 | fLegOffset = other.fLegOffset; | |
153 | fModuleSpacing = other.fModuleSpacing; | |
154 | fPrintboardThickness = other.fPrintboardThickness; | |
155 | fRotations = other.fRotations; | |
156 | if (other.fShape) { | |
157 | if (other.fShape->IsA() == TXTRU::Class()) | |
158 | ((TXTRU*)other.fShape)->Copy(*fShape); | |
159 | else | |
160 | fShape = 0; | |
161 | } | |
162 | if (other.fRotMatricies) { | |
163 | Int_t n = other.fRotMatricies->GetEntries(); | |
164 | if (!fRotMatricies) fRotMatricies = new TObjArray(n); | |
165 | else fRotMatricies->Expand(n); | |
166 | TIter next(other.fRotMatricies); | |
167 | TObject* o = 0; | |
168 | while ((o = next())) fRotMatricies->Add(o); | |
169 | } | |
170 | return *this; | |
42403906 | 171 | } |
172 | ||
c4bcfd14 | 173 | |
4347b38f | 174 | |
175 | //____________________________________________________________________ | |
176 | void | |
177 | AliFMDRing::Init() | |
178 | { | |
179 | // Initialize the ring object. | |
180 | // DebugGuard guard("AliFMDRing::Init"); | |
824466d5 | 181 | AliDebug(30, Form("\tInitializing ring %c", fId)); |
4347b38f | 182 | fPolygon.Clear(); |
183 | SetupCoordinates(); | |
184 | } | |
185 | ||
186 | //____________________________________________________________________ | |
187 | AliFMDRing::~AliFMDRing() | |
188 | { | |
42403906 | 189 | // Destructor - deletes shape and rotation matricies |
824466d5 | 190 | AliDebug(30, Form("\tDestructing ring %c", fId)); |
4347b38f | 191 | if (fShape) delete fShape; |
192 | if (fRotMatricies) delete fRotMatricies; | |
193 | } | |
194 | ||
195 | ||
196 | //____________________________________________________________________ | |
197 | void | |
198 | AliFMDRing::Browse(TBrowser* /* b */) | |
199 | { | |
200 | // DebugGuard guard("AliFMDRing::Browse"); | |
824466d5 | 201 | AliDebug(30, Form("\tBrowsing ring %c", fId)); |
4347b38f | 202 | } |
203 | ||
204 | ||
205 | //____________________________________________________________________ | |
206 | void | |
207 | AliFMDRing::SetupCoordinates() | |
208 | { | |
209 | // Calculates the parameters of the polygon shape. | |
210 | // | |
824466d5 | 211 | // |
212 | ||
4347b38f | 213 | // Get out immediately if we have already done all this |
214 | if (fPolygon.GetNVerticies() > 1) return; | |
824466d5 | 215 | AliDebug(10, Form("\tSetting up the coordinates for ring %c", fId)); |
4347b38f | 216 | |
c4bcfd14 | 217 | double tanTheta = TMath::Tan(fTheta * TMath::Pi() / 180.); |
218 | double tanTheta2 = TMath::Power(tanTheta,2); | |
4347b38f | 219 | double r2 = TMath::Power(fWaferRadius,2); |
c4bcfd14 | 220 | double yA = tanTheta * fLowR; |
4347b38f | 221 | double lr2 = TMath::Power(fLowR, 2); |
222 | double hr2 = TMath::Power(fHighR,2); | |
c4bcfd14 | 223 | double xD = fLowR + TMath::Sqrt(r2 - tanTheta2 * lr2); |
224 | double xD2 = TMath::Power(xD,2); | |
225 | //double xD_2 = fLowR - TMath::Sqrt(r2 - tanTheta2 * lr2); | |
56b1929b | 226 | double yB = TMath::Sqrt(r2 - hr2 + 2 * fHighR * xD - xD2); |
c4bcfd14 | 227 | double xC = ((xD + TMath::Sqrt(-tanTheta2 * xD2 + r2 |
228 | + r2 * tanTheta2)) | |
229 | / (1 + tanTheta2)); | |
230 | double yC = tanTheta * xC; | |
231 | ||
232 | fPolygon.AddVertex(fLowR, -yA); | |
233 | fPolygon.AddVertex(xC, -yC); | |
234 | fPolygon.AddVertex(fHighR, -yB); | |
235 | fPolygon.AddVertex(fHighR, yB); | |
236 | fPolygon.AddVertex(xC, yC); | |
237 | fPolygon.AddVertex(fLowR, yA); | |
4347b38f | 238 | } |
239 | ||
240 | //____________________________________________________________________ | |
241 | bool | |
242 | AliFMDRing::IsWithin(size_t moduleNo, double x, double y) const | |
243 | { | |
244 | // Checks if a point (x,y) is inside the module with number moduleNo | |
245 | // | |
246 | // DebugGuard guard("AliFMDRing::IsWithin"); | |
824466d5 | 247 | AliDebug(20, Form("\tChecking wether the hit at (%lf,%lf) in module %d " |
248 | "is within this ring (%c)", x, y, moduleNo, fId)); | |
4347b38f | 249 | bool ret = false; |
250 | double r2 = x * x + y * y; | |
251 | if (r2 < fHighR * fHighR && r2 > fLowR * fLowR) { | |
252 | // double point_angle = TMath::ATan2(y, x); | |
253 | // int n_modules = 360 / Int_t(fTheta * 2); | |
254 | double m_angle = (.5 + moduleNo) * 2 * fTheta; | |
255 | double m_radians = TMath::Pi() * m_angle / 180.; | |
256 | ||
257 | // Rotate the point. | |
258 | double xr = x * TMath::Cos(-m_radians) - y * TMath::Sin(-m_radians); | |
259 | double yr = x * TMath::Sin(-m_radians) + y * TMath::Cos(-m_radians); | |
260 | ||
261 | ret = fPolygon.Contains(xr,yr); | |
262 | } | |
263 | return ret; | |
264 | } | |
265 | ||
266 | ||
267 | ||
268 | ||
269 | //____________________________________________________________________ | |
270 | void | |
271 | AliFMDRing::Draw(Option_t* option) const | |
272 | { | |
273 | // Draw a the shape of the ring into a 2D histogram. Useful for | |
274 | // superimposing the actual shape of the ring onto a scatter plot of | |
275 | // hits in the detector. | |
276 | // | |
277 | // DebugGuard guard("AliFMDRing::Draw"); | |
824466d5 | 278 | AliDebug(20, Form("\tDrawing ring %c", fId)); |
4347b38f | 279 | // The unrotated coordinates of the polygon verticies |
280 | if (fPolygon.GetNVerticies() < 1) return; | |
281 | ||
282 | TVector2 v[6]; | |
283 | for (size_t i = 0; i < fPolygon.GetNVerticies(); i++) | |
284 | v[i] = fPolygon.GetVertex(i); | |
285 | ||
286 | Int_t nModules = 360 / Int_t(fTheta * 2); | |
287 | Double_t dTheta = fTheta * 2; | |
288 | ||
289 | TString opt(option); | |
290 | if (opt.Contains("B", TString::kIgnoreCase)) { | |
291 | opt.Remove(opt.Index("B", 1, TString::kIgnoreCase),1); | |
292 | TH1* null = new TH2F("null", "Null", | |
293 | 100, -fHighR * 1.1, fHighR * 1.1, | |
294 | 100, -fHighR * 1.1, fHighR * 1.1); | |
295 | null->SetStats(0); | |
296 | null->Draw(opt.Data()); | |
297 | } | |
298 | ||
299 | for (int i = 0; i < nModules; i++) { | |
300 | Double_t theta = (i + .5) * dTheta; | |
301 | AliFMDPolygon p; | |
302 | for (int j = 0; j < 6; j++) { | |
303 | TVector2 vr(v[j].Rotate(TMath::Pi() * theta / 180.)); | |
304 | if (!p.AddVertex(vr.X(),vr.Y())) { | |
305 | // std::cerr << "Draw of polygon " << i << " failed" << std::endl; | |
306 | break; | |
307 | } | |
308 | } | |
309 | p.Draw(opt.Data(), Form("MOD%c_%d", fId, i)); | |
310 | } | |
311 | if (opt.Contains("0", TString::kIgnoreCase)) { | |
312 | TArc* arcH = new TArc(0,0, fHighR); | |
313 | arcH->SetLineStyle(2); | |
314 | arcH->SetLineColor(4); | |
315 | arcH->Draw(); | |
316 | ||
317 | TArc* arcL = new TArc(0,0, fLowR); | |
318 | arcL->SetLineStyle(2); | |
319 | arcL->SetLineColor(4); | |
320 | arcL->Draw(); | |
321 | } | |
322 | } | |
323 | ||
324 | //____________________________________________________________________ | |
325 | void | |
326 | AliFMDRing::SetupGeometry(Int_t vacuumId, Int_t siId, Int_t pcbId, | |
327 | Int_t pbRotId, Int_t idRotId) | |
328 | { | |
329 | // Setup the geometry of the ring. It defines the volumes | |
330 | // RNGI or RNGO which can later be positioned in a sub-detector | |
331 | // volume. | |
332 | // | |
333 | // The hieracy of the RNGx volume is | |
334 | // | |
42403906 | 335 | // FRGx // Ring volume |
336 | // FVFx // Container of hybrid + legs | |
337 | // FACx // Active volume (si sensor approx) | |
338 | // FSEx // Section division | |
339 | // FSTx // Strip division | |
340 | // FPTx // Print board (bottom) | |
341 | // FPBx // Print board (top) | |
342 | // FLL // Support leg (long version) | |
343 | // FVBx // Container of hybrid + legs | |
344 | // FACx // Active volume (si sensor approx) | |
345 | // FSEx // Section division | |
346 | // FSTx // Strip division | |
347 | // FPTx // Print board (bottom) | |
348 | // FPBx // Print board (top) | |
349 | // FSL // Support leg (long version) | |
4347b38f | 350 | // |
351 | // Parameters: | |
352 | // | |
353 | // vacuumId Medium of inactive virtual volumes | |
354 | // siId Medium of Silicon sensor (active) | |
355 | // pcbId Medium of print boards | |
356 | // pbRotId Print board rotation matrix | |
357 | // idRotId Identity rotation matrix | |
358 | // | |
359 | // DebugGuard guard("AliFMDRing::SetupGeometry"); | |
824466d5 | 360 | AliDebug(10, Form("\tSetting up the geometry for ring %c", fId)); |
4347b38f | 361 | |
362 | const TVector2& bCorner = fPolygon.GetVertex(3); // Third corner | |
363 | const TVector2& aCorner = fPolygon.GetVertex(5); // First corner | |
364 | const TVector2& cCorner = fPolygon.GetVertex(4); // Second corner | |
365 | TString name; | |
366 | TString name2; | |
367 | Double_t dStrip = (bCorner.Mod() - aCorner.Mod()) / fNStrips; | |
368 | Double_t stripOff = aCorner.Mod(); | |
369 | Double_t rmin = fLowR; | |
370 | Double_t rmax = bCorner.Mod(); | |
371 | Double_t pars[10]; | |
372 | fRingDepth = (fSiThickness | |
373 | + fPrintboardThickness | |
374 | + fLegLength | |
375 | + fModuleSpacing); | |
376 | ||
377 | // Ring virtual volume | |
378 | pars[0] = rmin; | |
c4bcfd14 | 379 | pars[1] = rmax; |
4347b38f | 380 | pars[2] = fRingDepth / 2; |
c4bcfd14 | 381 | name = Form(fgkRingFormat, fId); |
4347b38f | 382 | fRingId = gMC->Gsvolu(name.Data(), "TUBE", vacuumId, pars, 3); |
383 | ||
384 | // Virtual volume for modules with long legs | |
385 | pars[1] = rmax; | |
386 | pars[3] = -fTheta; | |
387 | pars[4] = fTheta; | |
7e54281f | 388 | name = Form(fgkVirtualFormat, fId, 'F'); |
4347b38f | 389 | fVirtualFrontId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5); |
390 | ||
391 | // Virtual volume for modules with long legs | |
392 | pars[2] = (fRingDepth - fModuleSpacing) / 2; | |
7e54281f | 393 | name = Form(fgkVirtualFormat, fId, 'B'); |
4347b38f | 394 | fVirtualBackId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId, pars, 5); |
395 | ||
396 | // Virtual mother volume for silicon | |
397 | pars[2] = fSiThickness/2; | |
398 | name2 = name; | |
c4bcfd14 | 399 | name = Form(fgkActiveFormat, fId); |
4347b38f | 400 | fActiveId = gMC->Gsvolu(name.Data(), "TUBS", vacuumId , pars, 5); |
401 | ||
402 | if (fDetailed) { | |
403 | // Virtual sector volumes | |
404 | name2 = name; | |
c4bcfd14 | 405 | name = Form(fgkSectorFormat, fId); |
4347b38f | 406 | gMC->Gsdvn2(name.Data(), name2.Data(), 2, 2, -fTheta, vacuumId); |
407 | fSectionId = gMC->VolId(name.Data()); | |
408 | ||
409 | // Active strip volumes | |
410 | name2 = name; | |
c4bcfd14 | 411 | name = Form(fgkStripFormat, fId); |
42403906 | 412 | gMC->Gsdvt2(name.Data(), name2.Data(), dStrip, 1,stripOff, siId, fNStrips); |
4347b38f | 413 | fStripId = gMC->VolId(name.Data()); |
414 | } | |
415 | ||
416 | // Print-board on back of module | |
417 | pars[4] = TMath::Tan(TMath::Pi() * fTheta / 180) * fBondingWidth; | |
418 | // Top of the print board | |
419 | pars[0] = cCorner.Y() - pars[4]; | |
420 | pars[1] = bCorner.Y() - pars[4]; | |
421 | pars[2] = fPrintboardThickness / 2; // PCB half thickness | |
422 | pars[3] = (bCorner.X() - cCorner.X()) / 2; | |
7e54281f | 423 | name = Form(fgkPrintboardFormat, fId, 'T'); |
4347b38f | 424 | fPrintboardTopId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4); |
425 | ||
426 | // Bottom of the print board | |
427 | pars[0] = aCorner.Y() - pars[4]; | |
428 | pars[1] = cCorner.Y() - pars[4]; | |
429 | pars[3] = (cCorner.X() - aCorner.X()) / 2; | |
7e54281f | 430 | name = Form(fgkPrintboardFormat, fId, 'B'); |
4347b38f | 431 | fPrintboardBottomId = gMC->Gsvolu(name.Data(), "TRD1", pcbId, pars, 4); |
432 | ||
433 | // Define rotation matricies | |
434 | Int_t nModules = 360 / Int_t(fTheta * 2); | |
435 | Double_t dTheta = fTheta * 2; | |
436 | fRotations.Set(nModules); | |
437 | for (int i = 0; i < nModules; i++) { | |
438 | Double_t theta = (i + .5) * dTheta; | |
439 | Int_t idrot = 0; | |
440 | // Rotation matrix for virtual module volumes | |
441 | gMC->Matrix(idrot, 90, theta, 90, fmod(90 + theta, 360), 0, 0); | |
442 | fRotations[i] = idrot; | |
443 | } | |
444 | ||
445 | ||
446 | // Int_t nModules = 360 / Int_t(fTheta * 2); | |
447 | // Double_t dTheta = fTheta * 2; | |
448 | Double_t pbTopL = (bCorner.X() - cCorner.X()); | |
449 | Double_t pbBotL = (cCorner.X() - aCorner.X()); | |
450 | Double_t yoffset = ((TMath::Tan(TMath::Pi() * fTheta / 180) | |
451 | * fBondingWidth)); | |
452 | ||
453 | for (int i = 0; i < nModules; i++) { | |
c4bcfd14 | 454 | TString name2 = Form(fgkRingFormat, fId); |
4347b38f | 455 | |
456 | Int_t id = i; | |
457 | // Double_t theta = (i + .5) * dTheta; | |
458 | Bool_t isFront = (i % 2 == 1); | |
459 | Double_t dz = 0; | |
460 | Double_t w = fRingDepth - (isFront ? 0 : fModuleSpacing); | |
461 | ||
462 | // Place virtual module volume | |
7e54281f | 463 | name = Form(fgkVirtualFormat, fId, (isFront ? 'F' : 'B')); |
4347b38f | 464 | dz = (w - fRingDepth) / 2; |
824466d5 | 465 | gMC->Gspos(name.Data(), id, name2.Data(), 0., 0., dz,fRotations[i], |
466 | "ONLY"); | |
4347b38f | 467 | |
468 | // We only need to place the children once, they are copied when | |
469 | // we place the other virtual volumes. | |
470 | if (i > 1) continue; | |
471 | name2 = name; | |
472 | ||
473 | // Place active silicon wafer - this is put so that the front of | |
474 | // the silicon is on the edge of the virtual volume. | |
c4bcfd14 | 475 | name = Form(fgkActiveFormat, fId); |
4347b38f | 476 | dz = (w - fSiThickness) / 2; |
824466d5 | 477 | gMC->Gspos(name.Data(), id, name2.Data(),0.,0.,dz,idRotId, "ONLY"); |
4347b38f | 478 | |
479 | // Place print board. This is put immediately behind the silicon | |
7e54281f | 480 | name = Form(fgkPrintboardFormat, fId, 'T'); |
4347b38f | 481 | dz = w / 2 - fSiThickness - fPrintboardThickness / 2; |
482 | gMC->Gspos(name.Data(), id, name2.Data(), | |
483 | fLowR + pbBotL + pbTopL / 2, 0, dz, pbRotId, "ONLY"); | |
7e54281f | 484 | name = Form(fgkPrintboardFormat, fId, 'B'); |
4347b38f | 485 | gMC->Gspos(name.Data(), id, name2.Data(), |
486 | fLowR + pbBotL / 2, 0, dz, pbRotId, "ONLY"); | |
487 | ||
488 | // Support legs | |
489 | // This is put immediately behind the pringboard. | |
490 | dz = (w / 2 - fSiThickness - fPrintboardThickness | |
491 | - (fLegLength + (isFront ? fModuleSpacing : 0)) /2); | |
7e54281f | 492 | name = (isFront ? AliFMD::fgkLongLegName : AliFMD::fgkShortLegName); |
4347b38f | 493 | gMC->Gspos(name.Data(), id*10 + 1, name2.Data(), |
824466d5 | 494 | aCorner.X() + fLegOffset + fLegRadius, 0., dz, idRotId, "ONLY"); |
4347b38f | 495 | Double_t y = cCorner.Y() - yoffset - fLegOffset - fLegRadius; |
824466d5 | 496 | gMC->Gspos(name.Data(),id*10+2,name2.Data(),cCorner.X(),y,dz, |
497 | idRotId,"ONLY"); | |
498 | gMC->Gspos(name.Data(),id*10+3,name2.Data(),cCorner.X(),-y,dz, | |
499 | idRotId,"ONLY"); | |
4347b38f | 500 | } |
501 | } | |
502 | //____________________________________________________________________ | |
503 | void | |
504 | AliFMDRing::Geometry(const char* mother, Int_t baseId, Double_t z, | |
505 | Int_t /* pbRotId */, Int_t idRotId) | |
506 | { | |
507 | // Positions a RNGx volume inside a mother. | |
508 | // | |
509 | // Parameters | |
510 | // | |
511 | // mother Mother volume to position the RNGx volume in | |
512 | // baseId Base copy number | |
513 | // z Z coordinate where the front of the active silicon | |
514 | // should be in the mother volume, so we need to | |
515 | // subtract half the ring width. | |
516 | // idRotId Identity rotation matrix | |
517 | // | |
518 | // DebugGuard guard("AliFMDRing::Geometry"); | |
4347b38f | 519 | TString name; |
520 | Double_t offsetZ = (fSiThickness | |
521 | + fPrintboardThickness | |
522 | + fLegLength + fModuleSpacing) / 2; | |
c4bcfd14 | 523 | name = Form(fgkRingFormat, fId); |
824466d5 | 524 | AliDebug(10, Form("\tPlacing ring %s in %s at z=%lf-%lf=%lf (base ID: %d)", |
525 | name.Data(), mother, z, offsetZ, z-offsetZ, baseId)); | |
526 | gMC->Gspos(name.Data(), baseId, mother, 0., 0., z - offsetZ, idRotId, | |
527 | "ONLY"); | |
4347b38f | 528 | } |
529 | ||
530 | //____________________________________________________________________ | |
531 | void | |
532 | AliFMDRing::SimpleGeometry(TList* nodes, | |
533 | TNode* mother, | |
534 | Int_t colour, | |
535 | Double_t z, | |
536 | Int_t n) | |
537 | { | |
538 | // Make a simple geometry of the ring for event display. | |
539 | // | |
540 | // The simple geometry is made from ROOT TNode and TShape objects. | |
541 | // Note, that we cache the TShape and TRotMatrix objects used for | |
542 | // this. | |
543 | // | |
544 | // Parameters | |
545 | // | |
546 | // nodes List of nodes to register all create nodes in | |
547 | // mother Mother node to put the ring in. | |
548 | // colour Colour of the nodes | |
549 | // z Z position of the node in the mother volume | |
550 | // n Detector number | |
551 | // | |
552 | // DebugGuard guard("AliFMDRing::SimpleGeometry"); | |
4347b38f | 553 | SetupCoordinates(); |
554 | ||
824466d5 | 555 | AliDebug(10, Form("\tCreating simple geometry for " |
556 | "ring %c at z=%lf cm in %s", | |
557 | fId, z, mother->GetName())); | |
4347b38f | 558 | // If the shape hasn't been defined yet, we define it here. |
559 | if (!fShape) { | |
824466d5 | 560 | |
c4bcfd14 | 561 | TString name(Form(fgkActiveFormat, fId)); |
4347b38f | 562 | TString title(Form("Shape of modules in %c Rings", fId)); |
563 | Int_t n = fPolygon.GetNVerticies(); | |
564 | TXTRU* shape = new TXTRU(name.Data(), title.Data(), "void", n, 2); | |
565 | for (Int_t i = 0; i < n; i++) { | |
566 | const TVector2& v = fPolygon.GetVertex(i); | |
567 | shape->DefineVertex(i, v.X(), v.Y()); | |
568 | } | |
569 | shape->DefineSection(0, - fSiThickness / 2, 1, 0, 0); | |
570 | shape->DefineSection(1, + fSiThickness / 2, 1, 0, 0); | |
571 | fShape = shape; | |
572 | fShape->SetLineColor(colour); | |
573 | } | |
574 | ||
575 | Int_t nModules = 360 / Int_t(fTheta * 2); | |
576 | Double_t dTheta = fTheta * 2; | |
577 | ||
578 | // If the roation matricies hasn't been defined yet, we do so here | |
579 | if (!fRotMatricies) { | |
580 | fRotMatricies = new TObjArray(nModules); | |
581 | for (int i = 0; i < nModules; i++) { | |
582 | Double_t theta = (i + .5) * dTheta; | |
583 | TString name(Form("FMD_ring_%c_rot", fId)); | |
584 | TString title(Form("FMD Ring %c Rotation", fId)); | |
585 | TRotMatrix* rot = | |
586 | new TRotMatrix(name.Data(), title.Data(), | |
587 | 90, theta, 90, fmod(90 + theta, 360), 0, 0); | |
588 | fRotMatricies->AddAt(rot, i); | |
589 | } | |
590 | } | |
591 | ||
592 | Double_t offsetZ = (fSiThickness | |
593 | + fPrintboardThickness | |
594 | + fLegLength + fModuleSpacing) / 2; | |
595 | ||
596 | // Make all the nodes | |
597 | for (int i = 0; i < nModules; i++) { | |
598 | Bool_t isFront = (i % 2 == 1); | |
599 | mother->cd(); | |
600 | TRotMatrix* rot = static_cast<TRotMatrix*>(fRotMatricies->At(i)); | |
42403906 | 601 | TString name(Form("FAC%c_%d_%d", fId, n, i)); |
4347b38f | 602 | TString title(Form("Active FMD%d volume in %c Ring", n, fId)); |
603 | TNode* node = new TNode(name.Data(), title.Data(), fShape, | |
604 | 0, 0, | |
605 | z - offsetZ + (isFront ? fModuleSpacing : 0), | |
606 | rot); | |
607 | node->SetLineColor(colour); | |
608 | nodes->Add(node); | |
609 | } | |
610 | } | |
611 | ||
612 | ||
613 | ||
614 | //____________________________________________________________________ | |
615 | void | |
616 | AliFMDRing::Gsatt() | |
617 | { | |
618 | // Set drawing attributes for the RING | |
619 | // | |
620 | // DebugGuard guard("AliFMDRing::Gsatt"); | |
824466d5 | 621 | AliDebug(10, Form("\tSetting drawing attributes for Ring %c", fId)); |
4347b38f | 622 | TString name; |
c4bcfd14 | 623 | name = Form(fgkRingFormat,fId); |
4347b38f | 624 | gMC->Gsatt(name.Data(), "SEEN", 0); |
625 | ||
7e54281f | 626 | name = Form(fgkVirtualFormat, fId, 'F'); |
4347b38f | 627 | gMC->Gsatt(name.Data(), "SEEN", 0); |
628 | ||
7e54281f | 629 | name = Form(fgkVirtualFormat, fId, 'B'); |
4347b38f | 630 | gMC->Gsatt(name.Data(), "SEEN", 0); |
631 | ||
c4bcfd14 | 632 | name = Form(fgkActiveFormat,fId); |
4347b38f | 633 | gMC->Gsatt(name.Data(), "SEEN", 1); |
634 | ||
7e54281f | 635 | name = Form(fgkSectorFormat,fId); |
636 | gMC->Gsatt(name.Data(), "SEEN", 0); | |
637 | ||
638 | name = Form(fgkStripFormat,fId); | |
639 | gMC->Gsatt(name.Data(), "SEEN", 0); | |
640 | ||
641 | name = Form(fgkPrintboardFormat, fId, 'T'); | |
4347b38f | 642 | gMC->Gsatt(name.Data(), "SEEN", 1); |
643 | ||
7e54281f | 644 | name = Form(fgkPrintboardFormat, fId, 'B'); |
4347b38f | 645 | gMC->Gsatt(name.Data(), "SEEN", 1); |
646 | } | |
647 | ||
648 | // | |
649 | // EOF | |
650 | // |