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