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