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