]>
Commit | Line | Data |
---|---|---|
54e415a8 | 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 | **************************************************************************/ | |
54e415a8 | 15 | /* $Id$ */ |
c2fc1258 | 16 | /** @file AliFMDGeometryBuilder.cxx |
17 | @author Christian Holm Christensen <cholm@nbi.dk> | |
18 | @date Mon Mar 27 12:41:17 2006 | |
19 | @brief Class to build the FMD geometry | |
20 | */ | |
54e415a8 | 21 | //____________________________________________________________________ |
22 | // | |
02a27b50 | 23 | // Builder of FMD geometry. |
6169f936 | 24 | // |
02a27b50 | 25 | // This class takes care of actually building the geometry using the |
26 | // TGeo classes. Various parameters are fecthed from the | |
27 | // AliFMDGeometry manager. | |
54e415a8 | 28 | // Forward Multiplicity Detector based on Silicon wafers. This class |
29 | // contains the base procedures for the Forward Multiplicity detector | |
30 | // Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of | |
31 | // which has 1 or 2 rings of silicon sensors. | |
32 | // | |
54e415a8 | 33 | // |
9edefa04 | 34 | |
35 | #include <TArrayD.h> // ROOT_TArrayD | |
36 | #include <TGeoManager.h> // ROOT_TGeoManager | |
268f57b1 | 37 | #include <TGeoMatrix.h> // ROOT_TGeoMatrix |
9edefa04 | 38 | #include <TGeoTube.h> // ROOT_TGeoTube |
39 | #include <TGeoTube.h> // ROOT_TGeoTube | |
40 | #include <TGeoVolume.h> // ROOT_TGeoVolume | |
41 | #include <TGeoXtru.h> // ROOT_TGeoXtru | |
42 | #include <TMath.h> | |
43 | #include <TVector2.h> // ROOT_TVector2 | |
44 | //#include <TGeoMaterial.h> // ROOT_TGeoMaterial | |
45 | //#include <TGeoMedium.h> // ROOT_TGeoMedium | |
46 | //#include <TGeoPcon.h> // ROOT_TGeoPcon | |
47 | //#include <TGeoPolygon.h> // ROOT_TGeoPolygon | |
48 | ||
54e415a8 | 49 | #include "AliFMDGeometryBuilder.h" // ALIFMDGEOSIMULATOR_H |
50 | #include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H | |
51 | #include "AliFMDDetector.h" // ALIFMDDETECTOR_H | |
52 | #include "AliFMDRing.h" // ALIFMDRING_H | |
53 | #include "AliFMD1.h" // ALIFMD1_H | |
54 | #include "AliFMD2.h" // ALIFMD2_H | |
55 | #include "AliFMD3.h" // ALIFMD3_H | |
6169f936 | 56 | // #include "AliFMD.h" // ALIFMD_H |
f95a63c4 | 57 | #include "AliFMDDebug.h" // ALILOG_H |
54e415a8 | 58 | |
59 | //==================================================================== | |
60 | ClassImp(AliFMDGeometryBuilder) | |
61 | #if 0 | |
62 | ; // This is here to keep Emacs for indenting the next line | |
63 | #endif | |
64 | ||
65 | //____________________________________________________________________ | |
66 | const Char_t* AliFMDGeometryBuilder::fgkActiveName = "F%cAC"; | |
bf000c32 | 67 | const Char_t* AliFMDGeometryBuilder::fgkSectorName = "F%cSC"; |
54e415a8 | 68 | const Char_t* AliFMDGeometryBuilder::fgkStripName = "F%cST"; |
bf000c32 | 69 | const Char_t* AliFMDGeometryBuilder::fgkSensorName = "F%cSE"; |
70 | const Char_t* AliFMDGeometryBuilder::fgkPCBName = "F%cPB"; | |
71 | const Char_t* AliFMDGeometryBuilder::fgkCuName = "F%cCU"; | |
72 | const Char_t* AliFMDGeometryBuilder::fgkChipName = "F%cCH"; | |
54e415a8 | 73 | const Char_t* AliFMDGeometryBuilder::fgkLongLegName = "F%cLL"; |
74 | const Char_t* AliFMDGeometryBuilder::fgkShortLegName = "F%cSL"; | |
bf000c32 | 75 | const Char_t* AliFMDGeometryBuilder::fgkFrontVName = "F%cFH"; |
76 | const Char_t* AliFMDGeometryBuilder::fgkBackVName = "F%cBH"; | |
77 | const Char_t* AliFMDGeometryBuilder::fgkRingTopName = "F%cTV"; | |
78 | const Char_t* AliFMDGeometryBuilder::fgkRingBotName = "F%cBV"; | |
79 | const Char_t* AliFMDGeometryBuilder::fgkHCName = "F%dH%c"; | |
80 | const Char_t* AliFMDGeometryBuilder::fgkIHCName = "F%dI%c"; | |
54e415a8 | 81 | const Char_t* AliFMDGeometryBuilder::fgkNoseName = "F3SN"; |
82 | const Char_t* AliFMDGeometryBuilder::fgkBackName = "F3SB"; | |
83 | const Char_t* AliFMDGeometryBuilder::fgkBeamName = "F3SL"; | |
84 | const Char_t* AliFMDGeometryBuilder::fgkFlangeName = "F3SF"; | |
bf000c32 | 85 | const Char_t* AliFMDGeometryBuilder::fgkFMDName = "F%dM%c"; |
54e415a8 | 86 | |
87 | //____________________________________________________________________ | |
88 | AliFMDGeometryBuilder::AliFMDGeometryBuilder() | |
b5ee4425 | 89 | : TTask("FMD", "Geomtry builder"), |
90 | fActiveId(0), | |
91 | fDetailed(kTRUE), | |
54e415a8 | 92 | fUseAssembly(kTRUE), |
b5ee4425 | 93 | fSectorOff(0), |
94 | fModuleOff(0), | |
95 | fRingOff(0), | |
96 | fDetectorOff(0), | |
54e415a8 | 97 | fSi(0), |
98 | fC(0), | |
99 | fAl(0), | |
100 | fPCB(0), | |
101 | fChip(0), | |
b5ee4425 | 102 | fAir(0), |
103 | fPlastic(0), | |
104 | fCopper(0) | |
54e415a8 | 105 | { |
106 | // Default constructor | |
088f8e79 | 107 | fActiveId.Set(2); |
54e415a8 | 108 | } |
109 | ||
110 | //____________________________________________________________________ | |
111 | AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) | |
112 | : TTask("FMD", "Geometry builder"), | |
b5ee4425 | 113 | fActiveId(0), |
54e415a8 | 114 | fDetailed(detailed), |
115 | fUseAssembly(kTRUE), | |
b5ee4425 | 116 | fSectorOff(0), |
117 | fModuleOff(0), | |
118 | fRingOff(0), | |
119 | fDetectorOff(0), | |
54e415a8 | 120 | fSi(0), |
121 | fC(0), | |
122 | fAl(0), | |
123 | fPCB(0), | |
124 | fChip(0), | |
b5ee4425 | 125 | fAir(0), |
126 | fPlastic(0), | |
127 | fCopper(0) | |
54e415a8 | 128 | { |
129 | // Normal constructor | |
130 | // | |
131 | // Parameters: | |
132 | // | |
133 | // fmd Pointer to AliFMD object | |
134 | // detailed Whether to make a detailed simulation or not | |
135 | // | |
088f8e79 | 136 | fActiveId.Set(2); |
54e415a8 | 137 | } |
138 | ||
139 | ||
140 | //____________________________________________________________________ | |
141 | TGeoVolume* | |
142 | AliFMDGeometryBuilder::RingGeometry(AliFMDRing* r) | |
143 | { | |
144 | // Setup the geometry of a ring. The defined TGeoVolume is | |
145 | // returned, and should be used when setting up the rest of the | |
146 | // volumes. | |
147 | // | |
148 | // | |
149 | // Parameters: | |
150 | // | |
151 | // r Pointer to ring geometry object | |
152 | // | |
153 | // Returns: | |
154 | // pointer to ring volume | |
155 | // | |
156 | if (!r) { | |
157 | AliError("Didn't get a ring object"); | |
158 | return 0; | |
159 | } | |
160 | Char_t id = r->GetId(); | |
161 | Double_t siThick = r->GetSiThickness(); | |
02a27b50 | 162 | const Int_t knv = r->GetNVerticies(); |
54e415a8 | 163 | TVector2* a = r->GetVertex(5); |
164 | TVector2* b = r->GetVertex(3); | |
165 | TVector2* c = r->GetVertex(4); | |
166 | Double_t theta = r->GetTheta(); | |
167 | Double_t off = (TMath::Tan(TMath::Pi() * theta / 180) | |
168 | * r->GetBondingWidth()); | |
169 | Double_t rmax = b->Mod(); | |
170 | Double_t rmin = r->GetLowR(); | |
171 | Double_t pcbThick = r->GetPrintboardThickness(); | |
bf000c32 | 172 | Double_t cuThick = r->GetCopperThickness(); |
173 | Double_t chipThick= r->GetChipThickness(); | |
54e415a8 | 174 | Double_t modSpace = r->GetModuleSpacing(); |
175 | Double_t legr = r->GetLegRadius(); | |
176 | Double_t legl = r->GetLegLength(); | |
177 | Double_t legoff = r->GetLegOffset(); | |
178 | Int_t ns = r->GetNStrips(); | |
179 | Double_t stripoff = a->Mod(); | |
180 | Double_t dstrip = (rmax - stripoff) / ns; | |
181 | Double_t space = r->GetSpacing(); | |
02a27b50 | 182 | TArrayD xs(knv); |
183 | TArrayD ys(knv); | |
184 | for (Int_t i = 0; i < knv; i++) { | |
54e415a8 | 185 | // Reverse the order |
02a27b50 | 186 | TVector2* vv = r->GetVertex(knv - 1 - i); |
54e415a8 | 187 | if (!vv) { |
02a27b50 | 188 | AliError(Form("Failed to get vertex # %d", knv - 1 - i)); |
54e415a8 | 189 | continue; |
190 | } | |
191 | xs[i] = vv->X(); | |
192 | ys[i] = vv->Y(); | |
193 | } | |
194 | ||
195 | // Shape of actual sensor | |
bf000c32 | 196 | TGeoXtru* sensorShape = new TGeoXtru(2); |
02a27b50 | 197 | sensorShape->DefinePolygon(knv, xs.fArray, ys.fArray); |
bf000c32 | 198 | sensorShape->DefineSection(0, - siThick/2); |
199 | sensorShape->DefineSection(1, siThick/2); | |
200 | TGeoVolume* sensorVolume = new TGeoVolume(Form(fgkSensorName, id), | |
201 | sensorShape, fSi); | |
202 | sensorVolume->VisibleDaughters(kFALSE); | |
203 | Int_t sid = sensorVolume->GetNumber(); | |
54e415a8 | 204 | fSectorOff = -1; |
205 | fModuleOff = 1; | |
206 | fRingOff = 2; | |
207 | fDetectorOff = 3; | |
208 | if (fDetailed) { | |
209 | fSectorOff = 1; | |
bf000c32 | 210 | fModuleOff = 3; |
211 | fRingOff = 4; | |
212 | fDetectorOff = 5; | |
54e415a8 | 213 | // Virtual volume shape to divide - This volume is only defined if |
214 | // the geometry is set to be detailed. | |
bf000c32 | 215 | TGeoTubeSeg* activeShape = new TGeoTubeSeg(rmin, rmax, siThick/2, |
216 | - theta, theta); | |
54e415a8 | 217 | TGeoVolume* activeVolume = new TGeoVolume(Form(fgkActiveName, id), |
218 | activeShape,fSi); | |
219 | TGeoVolume* sectorVolume = activeVolume->Divide(Form(fgkSectorName,id), | |
220 | 2, 2, -theta,0,0,"N"); | |
221 | TGeoVolume* stripVolume = sectorVolume->Divide(Form(fgkStripName, id), | |
222 | 1, ns, stripoff, dstrip, | |
223 | 0, "SX"); | |
224 | sid = stripVolume->GetNumber(); | |
bf000c32 | 225 | sensorVolume->AddNodeOverlap(activeVolume, 0); |
54e415a8 | 226 | } |
227 | ||
228 | switch (id) { | |
bf000c32 | 229 | case 'i': case 'I': fActiveId[0] = sid; break; |
230 | case 'o': case 'O': fActiveId[1] = sid; break; | |
54e415a8 | 231 | } |
232 | ||
233 | // Shape of Printed circuit Board | |
02a27b50 | 234 | for (Int_t i = 0; i < knv / 2; i++) ys[i] -= off; |
235 | for (Int_t i = knv / 2; i < knv; i++) ys[i] += off; | |
bf000c32 | 236 | TGeoXtru* pcbShape = new TGeoXtru(2); |
02a27b50 | 237 | pcbShape->DefinePolygon(knv, xs.fArray, ys.fArray); |
54e415a8 | 238 | pcbShape->DefineSection(0, - pcbThick/2); |
239 | pcbShape->DefineSection(1, pcbThick/2); | |
bf000c32 | 240 | TGeoVolume* pcbVolume = new TGeoVolume(Form(fgkPCBName, id), |
241 | pcbShape, fPCB); | |
242 | ||
243 | // Copper layer | |
244 | TGeoXtru* cuShape = new TGeoXtru(2); | |
245 | cuShape->DefinePolygon(6, xs.fArray, ys.fArray); | |
246 | cuShape->DefineSection(0, - cuThick/2); | |
247 | cuShape->DefineSection(1, cuThick/2); | |
248 | TGeoVolume* cuVolume = new TGeoVolume(Form(fgkCuName,id),cuShape,fCopper); | |
249 | ||
250 | // Chip layer | |
251 | TGeoXtru* chipShape = new TGeoXtru(2); | |
252 | chipShape->DefinePolygon(6, xs.fArray, ys.fArray); | |
253 | chipShape->DefineSection(0, - chipThick/2); | |
254 | chipShape->DefineSection(1, chipThick/2); | |
255 | TGeoVolume* chipVolume = new TGeoVolume(Form(fgkChipName,id), | |
256 | chipShape,fChip); | |
54e415a8 | 257 | |
258 | // Short leg shape | |
259 | TGeoTube* shortLegShape = new TGeoTube(0, legr, legl / 2); | |
260 | TGeoVolume* shortLegVolume = new TGeoVolume(Form(fgkShortLegName, id), | |
261 | shortLegShape, fPlastic); | |
262 | ||
263 | // Long leg shape | |
264 | TGeoTube* longLegShape = new TGeoTube(0, legr, (legl + modSpace) / 2); | |
265 | TGeoVolume* longLegVolume = new TGeoVolume(Form(fgkLongLegName, id), | |
266 | longLegShape, fPlastic); | |
267 | ||
bf000c32 | 268 | |
54e415a8 | 269 | // Back container volume |
bf000c32 | 270 | TGeoVolume* backVolume = new TGeoVolumeAssembly(Form(fgkBackVName, id)); |
54e415a8 | 271 | Double_t x = 0; |
272 | Double_t y = 0; | |
bf000c32 | 273 | Double_t z = pcbThick / 2; |
274 | backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x,y,z)); | |
275 | z += (pcbThick + cuThick) / 2; | |
276 | backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z)); | |
277 | z += (cuThick + chipThick) / 2; | |
278 | backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z)); | |
54e415a8 | 279 | x = a->X() + legoff + legr; |
280 | y = 0; | |
281 | z += pcbThick / 2 + legl / 2; | |
bf000c32 | 282 | backVolume->AddNode(shortLegVolume, 0, new TGeoTranslation(x,y,z)); |
54e415a8 | 283 | x = c->X(); |
284 | y = c->Y() - legoff - legr - off; | |
bf000c32 | 285 | backVolume->AddNode(shortLegVolume, 1, new TGeoTranslation(x,y,z)); |
54e415a8 | 286 | y = -y; |
bf000c32 | 287 | backVolume->AddNode(shortLegVolume, 2, new TGeoTranslation(x,y,z)); |
54e415a8 | 288 | |
289 | // Front container volume | |
bf000c32 | 290 | TGeoVolume* frontVolume = new TGeoVolumeAssembly(Form(fgkFrontVName, id)); |
54e415a8 | 291 | x = 0; |
292 | y = 0; | |
bf000c32 | 293 | z = pcbThick / 2; |
294 | frontVolume->AddNode(pcbVolume, 1, new TGeoTranslation(x,y,z)); | |
295 | z += (pcbThick + cuThick) / 2; | |
296 | frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, z)); | |
297 | z += (cuThick + chipThick) / 2; | |
298 | frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, z)); | |
54e415a8 | 299 | x = a->X() + legoff + legr; |
300 | y = 0; | |
301 | z += pcbThick / 2 + (legl + modSpace)/ 2; | |
bf000c32 | 302 | frontVolume->AddNode(longLegVolume, 0, new TGeoTranslation(x,y,z)); |
54e415a8 | 303 | x = c->X(); |
304 | y = c->Y() - legoff - legr - off; | |
bf000c32 | 305 | frontVolume->AddNode(longLegVolume, 1, new TGeoTranslation(x,y,z)); |
54e415a8 | 306 | y = -y; |
bf000c32 | 307 | frontVolume->AddNode(longLegVolume, 2, new TGeoTranslation(x,y,z)); |
54e415a8 | 308 | |
bf000c32 | 309 | // Half ring mother volumes. |
310 | TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id)); | |
311 | TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id)); | |
312 | TGeoVolume* halfRing = ringTopVolume; | |
54e415a8 | 313 | |
bf000c32 | 314 | // Adding modules to half-rings |
315 | Int_t nmod = r->GetNModules(); | |
f95a63c4 | 316 | AliFMDDebug(10, ("making %d modules in ring %c", nmod, id)); |
54e415a8 | 317 | for (Int_t i = 0; i < nmod; i++) { |
bf000c32 | 318 | if (i == nmod / 2) halfRing = ringBotVolume; |
319 | Bool_t front = (i % 2 == 0); | |
320 | Double_t z1 = siThick / 2 + (i % 2) * modSpace; | |
321 | Double_t z2 = z1 + siThick / 2 + space; | |
322 | Double_t th = (2 * i + 1) * theta; | |
323 | TGeoVolume* vol = (front ? frontVolume : backVolume); | |
f95a63c4 | 324 | AliFMDDebug(20, ("Placing copy %d of %s and %s in %s at z=%f and %f, " |
bf000c32 | 325 | "and theta=%f", i, sensorVolume->GetName(), |
326 | vol->GetName(), halfRing->GetName(), z1, z2, th)); | |
327 | TGeoMatrix* mat1 = new TGeoCombiTrans(0,0,z1,0); | |
328 | mat1->RotateZ(th); | |
329 | halfRing->AddNode(sensorVolume, i, mat1); | |
330 | TGeoMatrix* mat2 = new TGeoCombiTrans(0,0,z2,0); | |
331 | mat2->RotateZ(th); | |
332 | halfRing->AddNode(vol, i, mat2); | |
54e415a8 | 333 | } |
334 | ||
bf000c32 | 335 | return 0; |
54e415a8 | 336 | } |
337 | ||
338 | //____________________________________________________________________ | |
339 | TGeoVolume* | |
340 | AliFMDGeometryBuilder::DetectorGeometry(AliFMDDetector* d, | |
bf000c32 | 341 | TGeoVolume* topMother, |
342 | TGeoVolume* botMother, | |
343 | Double_t zMother, | |
344 | TGeoVolume* innerTop, | |
345 | TGeoVolume* innerBot, | |
346 | TGeoVolume* outerTop, | |
347 | TGeoVolume* outerBot) | |
54e415a8 | 348 | { |
349 | // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries. | |
350 | // This includes putting the Honeycomb support plates and the rings | |
351 | // into the mother volumes. | |
352 | // | |
353 | // Parameeters: | |
354 | // d The detector geometry to use | |
355 | // mother The mother volume of the detector | |
356 | // zmother The midpoint in global coordinates of detector vol. | |
357 | // inner Pointer to inner ring volume | |
358 | // outer Pointer to outer ring volume | |
359 | // | |
360 | // Returns: | |
361 | // Pointer to mother (detector volume) | |
362 | // | |
363 | if (!d) return 0; | |
364 | // Loop over the defined rings | |
365 | for (int i = 0; i < 2; i++) { | |
366 | AliFMDRing* r = 0; | |
367 | Double_t lowr = 0; | |
368 | Double_t highr = 0; | |
369 | Double_t rz = 0; | |
bf000c32 | 370 | TGeoVolume* tvol = 0; |
371 | TGeoVolume* bvol = 0; | |
54e415a8 | 372 | switch (i) { |
373 | case 0: | |
374 | r = d->GetInner(); | |
375 | lowr = d->GetInnerHoneyLowR(); | |
376 | highr = d->GetInnerHoneyHighR(); | |
377 | rz = d->GetInnerZ(); | |
bf000c32 | 378 | tvol = innerTop; |
379 | bvol = innerBot; | |
54e415a8 | 380 | break; |
381 | case 1: | |
382 | r = d->GetOuter(); | |
383 | lowr = d->GetOuterHoneyLowR(); | |
384 | highr = d->GetOuterHoneyHighR(); | |
385 | rz = d->GetOuterZ(); | |
bf000c32 | 386 | tvol = outerTop; |
387 | bvol = outerBot; | |
54e415a8 | 388 | break; |
389 | } | |
390 | if (!r) continue; | |
391 | Char_t c = r->GetId(); | |
392 | Int_t id = d->GetId(); | |
393 | Double_t hcThick = d->GetHoneycombThickness(); | |
394 | Double_t alThick = d->GetAlThickness(); | |
bf000c32 | 395 | Double_t z = TMath::Abs(rz - zMother); |
396 | ||
54e415a8 | 397 | // Place ring in mother volume |
bf000c32 | 398 | // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0); |
f95a63c4 | 399 | AliFMDDebug(5, ("Placing volumes %s and %s in %s and %s at z=%f", |
bf000c32 | 400 | tvol->GetName(), bvol->GetName(), |
401 | topMother->GetName(), botMother->GetName(), z)); | |
402 | topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z)); | |
403 | botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z)); | |
54e415a8 | 404 | |
54e415a8 | 405 | // Top of Honeycomb |
bf000c32 | 406 | TGeoTubeSeg* hcSha = new TGeoTubeSeg(lowr, highr, hcThick/2, 0, 180); |
407 | TGeoVolume* hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl); | |
54e415a8 | 408 | // Air in top of honeycomb |
bf000c32 | 409 | TGeoTubeSeg* ihcSha = new TGeoTubeSeg(lowr+alThick, highr - alThick, |
410 | (hcThick-alThick)/2, 0, 180); | |
411 | TGeoVolume* ihcVol = new TGeoVolume(Form(fgkIHCName,id,c),ihcSha,fAir); | |
412 | hcVol->AddNode(ihcVol, 0); | |
413 | hcVol->VisibleDaughters(kFALSE); | |
414 | hcVol->SetVisibility(kTRUE); | |
415 | ||
416 | z += (r->GetSiThickness() + | |
417 | r->GetSpacing() + | |
418 | r->GetPrintboardThickness() + | |
419 | r->GetCopperThickness() + | |
420 | r->GetChipThickness() + | |
421 | r->GetModuleSpacing() + | |
422 | r->GetLegLength() + | |
423 | hcThick / 2); | |
424 | ||
f95a63c4 | 425 | AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f", |
bf000c32 | 426 | hcVol->GetName(), topMother->GetName(), |
427 | botMother->GetName(), z)); | |
428 | // Add to top | |
429 | topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z)); | |
430 | ||
431 | // Add to bottom | |
432 | TGeoMatrix* bhcMatrix = new TGeoCombiTrans(0,0,z,0); | |
433 | bhcMatrix->RotateZ(180); | |
434 | botMother->AddNode(hcVol, 1, bhcMatrix); | |
54e415a8 | 435 | } |
bf000c32 | 436 | return 0; |
54e415a8 | 437 | } |
438 | ||
439 | //____________________________________________________________________ | |
440 | TGeoVolume* | |
bf000c32 | 441 | AliFMDGeometryBuilder::FMD1Geometry(AliFMD1* fmd1, |
442 | TGeoVolume* innerTop, | |
443 | TGeoVolume* innerBot) | |
54e415a8 | 444 | { |
445 | // Setup the FMD1 geometry. The FMD1 only has one ring, and no | |
446 | // special support as it is at the momement. | |
447 | // | |
448 | // See also AliFMDGeometryBuilder::DetectorGeometry | |
449 | // | |
bf000c32 | 450 | if (!fmd1 || !innerTop || !innerBot) return 0; |
451 | Double_t z = fmd1->GetInnerZ(); | |
452 | TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
453 | fmd1->GetId(), 'T')); | |
454 | TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
455 | fmd1->GetId(), 'B')); | |
54e415a8 | 456 | |
bf000c32 | 457 | // Basic detector geometry |
458 | DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, | |
459 | innerTop, innerBot, 0, 0); | |
460 | ||
461 | // Must add this after filling the assembly. | |
462 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
c1b9c050 | 463 | // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z); |
464 | TGeoRotation* rot = new TGeoRotation("FMD1 rotatation"); | |
0b1b84c9 | 465 | rot->RotateZ(-90); |
c1b9c050 | 466 | TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot); |
f95a63c4 | 467 | AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", |
bf000c32 | 468 | fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z)); |
469 | top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix); | |
470 | top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix); | |
471 | ||
472 | return 0; | |
54e415a8 | 473 | } |
474 | ||
475 | //____________________________________________________________________ | |
476 | TGeoVolume* | |
477 | AliFMDGeometryBuilder::FMD2Geometry(AliFMD2* fmd2, | |
bf000c32 | 478 | TGeoVolume* innerTop, |
479 | TGeoVolume* innerBot, | |
480 | TGeoVolume* outerTop, | |
481 | TGeoVolume* outerBot) | |
54e415a8 | 482 | { |
483 | // Setup the FMD2 geometry. The FMD2 has no | |
484 | // special support as it is at the momement. | |
485 | // | |
486 | // See also AliFMDGeometryBuilder::DetectorGeometry | |
487 | // | |
bf000c32 | 488 | if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0; |
489 | Double_t z = fmd2->GetOuterZ(); | |
490 | TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
491 | fmd2->GetId(), 'T')); | |
492 | TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
493 | fmd2->GetId(), 'B')); | |
54e415a8 | 494 | |
bf000c32 | 495 | DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, |
496 | innerTop, innerBot, outerTop, outerBot); | |
497 | ||
498 | // Must be done after filling the assemblies | |
54e415a8 | 499 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); |
bf000c32 | 500 | TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z); |
f95a63c4 | 501 | AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", |
bf000c32 | 502 | fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z)); |
503 | top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix); | |
504 | top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix); | |
54e415a8 | 505 | |
bf000c32 | 506 | return 0; |
54e415a8 | 507 | } |
508 | ||
509 | //____________________________________________________________________ | |
510 | TGeoVolume* | |
511 | AliFMDGeometryBuilder::FMD3Geometry(AliFMD3* fmd3, | |
bf000c32 | 512 | TGeoVolume* innerTop, |
513 | TGeoVolume* innerBot, | |
514 | TGeoVolume* outerTop, | |
515 | TGeoVolume* outerBot) | |
54e415a8 | 516 | { |
517 | // Setup the FMD3 geometry. The FMD2 has a rather elaborate support | |
518 | // structure, as the support will also support the vacuum | |
519 | // beam-pipe. | |
520 | // | |
521 | // See also AliFMDGeometryBuilder::DetectorGeometry | |
522 | // | |
bf000c32 | 523 | if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0; |
54e415a8 | 524 | Double_t nlen = fmd3->GetNoseLength(); |
525 | Double_t nz = fmd3->GetNoseZ(); | |
526 | Double_t noser1 = fmd3->GetNoseLowR(); | |
527 | Double_t noser2 = fmd3->GetNoseHighR(); | |
528 | Double_t conel = fmd3->GetConeLength(); | |
529 | Double_t backl = fmd3->GetBackLength(); | |
530 | Double_t backr1 = fmd3->GetBackLowR(); | |
531 | Double_t backr2 = fmd3->GetBackHighR(); | |
532 | Double_t zdist = conel - backl - nlen; | |
533 | Double_t tdist = backr2 - noser2; | |
534 | Double_t beaml = TMath::Sqrt(zdist * zdist + tdist * tdist); | |
535 | Double_t theta = -180. * TMath::ATan2(tdist, zdist) / TMath::Pi(); | |
54e415a8 | 536 | Double_t flanger = fmd3->GetFlangeR(); |
bf000c32 | 537 | Double_t z = fmd3->GetInnerZ(); // fmd3->GetZ(); |
54e415a8 | 538 | Double_t zi; |
539 | ||
bf000c32 | 540 | TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(Form(fgkFMDName, |
541 | fmd3->GetId(), 'T')); | |
542 | TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(Form(fgkFMDName, | |
543 | fmd3->GetId(), 'B')); | |
544 | ||
54e415a8 | 545 | |
bf000c32 | 546 | DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, z, |
547 | innerTop, innerBot, outerTop, outerBot); | |
548 | ||
549 | ||
54e415a8 | 550 | // Nose volume |
bf000c32 | 551 | TGeoTubeSeg* noseShape = new TGeoTubeSeg(noser1, noser2, nlen / 2, 0, 180); |
54e415a8 | 552 | TGeoVolume* noseVolume = new TGeoVolume(fgkNoseName, noseShape, fC); |
bf000c32 | 553 | zi = -nz + nlen / 2 + z; |
554 | ||
555 | fmd3TopVolume->AddNode(noseVolume, 0, new TGeoTranslation(0, 0, zi)); | |
556 | TGeoMatrix* nmatrix = new TGeoCombiTrans(0, 0, zi, 0); | |
557 | nmatrix->RotateZ(180); | |
558 | fmd3BotVolume->AddNode(noseVolume, 1, nmatrix); | |
54e415a8 | 559 | |
560 | // Back | |
bf000c32 | 561 | TGeoTubeSeg* backShape = new TGeoTubeSeg(backr1, backr2, backl / 2, 0, 180); |
54e415a8 | 562 | TGeoVolume* backVolume = new TGeoVolume(fgkBackName, backShape, fC); |
bf000c32 | 563 | zi = -nz + conel - backl / 2 + z; |
564 | fmd3TopVolume->AddNode(backVolume, 0, new TGeoTranslation(0, 0, zi)); | |
565 | TGeoMatrix* bmatrix = new TGeoCombiTrans(0, 0, zi, 0); | |
566 | bmatrix->RotateZ(180); | |
567 | fmd3BotVolume->AddNode(backVolume, 1, bmatrix); | |
568 | ||
54e415a8 | 569 | |
570 | Int_t n; | |
571 | Double_t r; | |
572 | // The flanges | |
573 | TGeoBBox* flangeShape = new TGeoBBox((flanger - backr2) / 2, | |
574 | fmd3->GetBeamWidth() / 2, | |
575 | backl / 2); | |
576 | TGeoVolume* flangeVolume = new TGeoVolume(fgkFlangeName, flangeShape, fC); | |
bf000c32 | 577 | n = fmd3->GetNFlange(); |
578 | r = backr2 + (flanger - backr2) / 2; | |
579 | TGeoVolume* mother = fmd3TopVolume; | |
54e415a8 | 580 | for (Int_t i = 0; i < n; i++) { |
bf000c32 | 581 | if (i >= n / 2) mother = fmd3BotVolume; |
582 | Double_t phi = 360. / n * i + 180. / n; | |
583 | Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi); | |
584 | Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi); | |
f95a63c4 | 585 | AliFMDDebug(15, ("Placing flange %d in %s at (%f,%f,%f) r=%f, phi=%f", |
bf000c32 | 586 | i, mother->GetName(), x, y, zi, r, phi)); |
587 | TGeoRotation* rot = new TGeoRotation; | |
54e415a8 | 588 | rot->RotateZ(phi); |
bf000c32 | 589 | TGeoMatrix* matrix = new TGeoCombiTrans(x, y, zi, rot); |
590 | mother->AddNode(flangeVolume, i, matrix); | |
54e415a8 | 591 | } |
592 | ||
593 | // The Beams | |
594 | TGeoBBox* beamShape = new TGeoBBox(fmd3->GetBeamThickness() / 2, | |
595 | fmd3->GetBeamWidth() / 2 - .1, | |
596 | beaml / 2); | |
597 | TGeoVolume* beamVolume = new TGeoVolume(fgkBeamName, beamShape, fC); | |
bf000c32 | 598 | n = fmd3->GetNBeam(); |
599 | r = noser2 + tdist / 2; | |
600 | zi = - nz + nlen + zdist / 2 + z; | |
601 | mother = fmd3TopVolume; | |
54e415a8 | 602 | for (Int_t i = 0; i < n; i++) { |
bf000c32 | 603 | if (i >= n / 2) mother = fmd3BotVolume; |
604 | Double_t phi = 360. / n * i; | |
605 | Double_t x = r * TMath::Cos(TMath::Pi() / 180 * phi); | |
606 | Double_t y = r * TMath::Sin(TMath::Pi() / 180 * phi); | |
54e415a8 | 607 | TGeoRotation* rot = new TGeoRotation(Form("FMD3 beam rotation %d", i)); |
608 | // Order is important | |
609 | rot->RotateY(-theta); | |
610 | rot->RotateZ(phi); | |
bf000c32 | 611 | TGeoMatrix* matrix = new TGeoCombiTrans(Form("FMD3 beam trans %d", i), |
54e415a8 | 612 | x, y, zi, rot); |
bf000c32 | 613 | mother->AddNode(beamVolume, i, matrix); |
54e415a8 | 614 | } |
615 | ||
bf000c32 | 616 | z = fmd3->GetInnerZ(); |
617 | TGeoRotation* rot = new TGeoRotation("FMD3 rotatation"); | |
618 | rot->RotateY(180); | |
619 | TGeoVolume* top = gGeoManager->GetVolume("ALIC"); | |
620 | TGeoMatrix* mmatrix = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot); | |
f95a63c4 | 621 | AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", |
bf000c32 | 622 | fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z)); |
623 | top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix); | |
624 | top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix); | |
625 | ||
626 | return 0; | |
54e415a8 | 627 | } |
628 | ||
629 | //____________________________________________________________________ | |
630 | void | |
631 | AliFMDGeometryBuilder::Exec(Option_t*) | |
632 | { | |
633 | // Setup up the FMD geometry. | |
f95a63c4 | 634 | AliFMDDebug(1, ("\tGeometry options: %s", |
bf000c32 | 635 | (fDetailed ? "divided into strips" : "one volume"))); |
54e415a8 | 636 | if (!gGeoManager) { |
637 | AliFatal("No TGeoManager defined"); | |
638 | return; | |
639 | } | |
640 | ||
641 | fSi = gGeoManager->GetMedium("FMD_Si$"); | |
642 | fC = gGeoManager->GetMedium("FMD_Carbon$"); | |
643 | fAl = gGeoManager->GetMedium("FMD_Aluminum$"); | |
644 | fChip = gGeoManager->GetMedium("FMD_Si Chip$"); | |
645 | fAir = gGeoManager->GetMedium("FMD_Air$"); | |
646 | fPCB = gGeoManager->GetMedium("FMD_PCB$"); | |
647 | fPlastic = gGeoManager->GetMedium("FMD_Plastic$"); | |
648 | fCopper = gGeoManager->GetMedium("FMD_Copper$"); | |
649 | ||
650 | if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper) { | |
651 | AliError("Failed to get some or all tracking mediums"); | |
652 | return; | |
653 | } | |
654 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
bf000c32 | 655 | AliFMDRing* inner = fmd->GetInner(); |
656 | AliFMDRing* outer = fmd->GetOuter(); | |
657 | RingGeometry(inner); | |
658 | RingGeometry(outer); | |
659 | TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, | |
660 | inner->GetId())); | |
661 | TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, | |
662 | inner->GetId())); | |
663 | TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, | |
664 | outer->GetId())); | |
665 | TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, | |
666 | outer->GetId())); | |
667 | ||
668 | FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot); | |
669 | FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot); | |
670 | FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot); | |
54e415a8 | 671 | #ifndef USE_PRE_MOVE |
672 | fmd->SetSectorOff(fSectorOff); | |
673 | fmd->SetModuleOff(fModuleOff); | |
674 | fmd->SetRingOff(fRingOff); | |
675 | fmd->SetDetectorOff(fDetectorOff); | |
676 | fmd->SetActive(fActiveId.fArray, fActiveId.fN); | |
677 | #endif | |
678 | // fmd->ExtractGeomInfo(); | |
679 | ||
680 | } | |
681 | ||
682 | ||
683 | //____________________________________________________________________ | |
684 | // | |
685 | // EOF | |
686 | // |