Increased error checking and possibility to extract some diagnostics
[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
35 #include <TArrayD.h>            // ROOT_TArrayD
36 #include <TGeoManager.h>        // ROOT_TGeoManager
37 #include <TGeoMatrix.h>         // ROOT_TGeoMatrix
38 #include <TGeoTube.h>           // ROOT_TGeoTube
39 #include <TGeoTrd1.h>           // ROOT_TGeoTrd1
40 #include <TGeoCone.h>           // ROOT_TGeoTrd1
41 #include <TGeoVolume.h>         // ROOT_TGeoVolume
42 #include <TGeoXtru.h>           // ROOT_TGeoXtru
43 #include <TGeoPcon.h>           // ROOT_TGeoPcon
44 #include <TGeoTorus.h>          // ROOT_TGeoTorus
45 #include <TGeoCompositeShape.h>
46 #include <TMath.h>
47 #include <TVector2.h>           // ROOT_TVector2
48 #include <TVector3.h>           // ROOT_TVector3
49 //#include <TGeoMaterial.h>     // ROOT_TGeoMaterial
50 //#include <TGeoMedium.h>               // ROOT_TGeoMedium
51 //#include <TGeoPcon.h>         // ROOT_TGeoPcon
52 //#include <TGeoPolygon.h>      // ROOT_TGeoPolygon
53
54 #include "AliFMDGeometryBuilder.h"      // ALIFMDGEOSIMULATOR_H
55 #include "AliFMDGeometry.h"     // ALIFMDGEOMETRY_H
56 #include "AliFMDDetector.h"     // ALIFMDDETECTOR_H
57 #include "AliFMDRing.h"         // ALIFMDRING_H
58 #include "AliFMD1.h"            // ALIFMD1_H
59 #include "AliFMD2.h"            // ALIFMD2_H
60 #include "AliFMD3.h"            // ALIFMD3_H
61 // #include "AliFMD.h"          // ALIFMD_H
62 #include "AliFMDDebug.h"                // ALILOG_H
63 #include <iostream>
64
65 //====================================================================
66 ClassImp(AliFMDGeometryBuilder)
67 #if 0
68   ; // This is here to keep Emacs for indenting the next line
69 #endif
70
71 //____________________________________________________________________
72 const Char_t* AliFMDGeometryBuilder::fgkActiveName      = "F%cAC";
73 const Char_t* AliFMDGeometryBuilder::fgkSectorName      = "F%cSC";
74 const Char_t* AliFMDGeometryBuilder::fgkStripName       = "F%cST";
75 const Char_t* AliFMDGeometryBuilder::fgkSensorName      = "F%cSE";
76 const Char_t* AliFMDGeometryBuilder::fgkPCBName         = "F%cPB";
77 const Char_t* AliFMDGeometryBuilder::fgkCuName          = "F%cCU";
78 const Char_t* AliFMDGeometryBuilder::fgkChipName        = "F%cCH";
79 const Char_t* AliFMDGeometryBuilder::fgkLongLegName     = "F%cLL";
80 const Char_t* AliFMDGeometryBuilder::fgkShortLegName    = "F%cSL";
81 const Char_t* AliFMDGeometryBuilder::fgkFrontVName      = "F%cFH";
82 const Char_t* AliFMDGeometryBuilder::fgkBackVName       = "F%cBH";
83 const Char_t* AliFMDGeometryBuilder::fgkRingTopName     = "F%cTV";
84 const Char_t* AliFMDGeometryBuilder::fgkRingBotName     = "F%cBV";
85 const Char_t* AliFMDGeometryBuilder::fgkHCName          = "F%dH%c";
86 const Char_t* AliFMDGeometryBuilder::fgkIHCName         = "F%dI%c";
87 const Char_t* AliFMDGeometryBuilder::fgkNoseName        = "F3SN";
88 const Char_t* AliFMDGeometryBuilder::fgkBackName        = "F%dSB";
89 const Char_t* AliFMDGeometryBuilder::fgkTopName         = "F%dSU";
90 const Char_t* AliFMDGeometryBuilder::fgkBeamName        = "F%dSL";
91 const Char_t* AliFMDGeometryBuilder::fgkFlangeName      = "F%dSF";
92 const Char_t* AliFMDGeometryBuilder::fgkFMDDCuName      = "F%cDC";
93 const Char_t* AliFMDGeometryBuilder::fgkFMDDPCBName     = "F%cDP";
94 const Char_t* AliFMDGeometryBuilder::fgkFMDDChipName    = "F%cDI";
95 const Char_t* AliFMDGeometryBuilder::fgkFMDDName        = "F%cDD";
96 const Char_t* AliFMDGeometryBuilder::fgkFMDName         = "F%dM%c";
97
98 //____________________________________________________________________
99 AliFMDGeometryBuilder::AliFMDGeometryBuilder() 
100   : TTask("FMD", "Geomtry builder"),
101     fActiveId(0),
102     fDetailed(kTRUE),
103     fUseAssembly(kTRUE),
104     fSectorOff(0),
105     fModuleOff(0),
106     fRingOff(0),
107     fDetectorOff(0),
108     fSi(0),
109     fC(0),
110     fAl(0),
111     fPCB(0),
112     fChip(0),
113     fAir(0),
114     fPlastic(0),
115     fCopper(0),
116     fSteel(0)
117 {
118   // Default constructor
119   fActiveId.Set(2);
120 }
121
122 //____________________________________________________________________
123 AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
124   : TTask("FMD", "Geometry builder"),
125     fActiveId(0),
126     fDetailed(detailed),
127     fUseAssembly(kTRUE),
128     fSectorOff(0),
129     fModuleOff(0),
130     fRingOff(0),
131     fDetectorOff(0),
132     fSi(0),
133     fC(0),
134     fAl(0),
135     fPCB(0),
136     fChip(0),
137     fAir(0),
138     fPlastic(0),
139     fCopper(0),
140     fSteel(0)
141 {
142   // Normal constructor
143   // 
144   // Parameters: 
145   // 
146   //      fmd           Pointer to AliFMD object 
147   //      detailed      Whether to make a detailed simulation or not 
148   // 
149   fActiveId.Set(2);
150 }
151
152 //____________________________________________________________________
153 TGeoShape*
154 AliFMDGeometryBuilder::MakeXTRU(const TObjArray& verticies, 
155                                 Double_t thick) const
156 {
157   // 
158   // Make a polygonic extrusion shape based on verticies passed in @a
159   // verticies 
160   // 
161   // Parameters:
162   //    verticies List of verticies
163   //    thick     Thickness
164   // 
165   // Return:
166   //    newly allocated polygonic extrusion shape
167   //
168   TArrayD xs(6);
169   TArrayD ys(6);
170   for (Int_t i = 0; i < 3; i++) { 
171     TVector2* v = static_cast<TVector2*>(verticies.At(i+1));
172     xs[i]     =  v->Y();
173     ys[i]     = -v->X();
174     xs[6-1-i] =  v->Y();
175     ys[6-1-i] =  v->X();
176   }
177   TGeoXtru* shape = new TGeoXtru(2);
178   shape->DefinePolygon(xs.fN, xs.fArray, ys.fArray);
179   shape->DefineSection(0, -thick/2);
180   shape->DefineSection(1, +thick/2);
181   
182   return shape;
183 }
184
185 //____________________________________________________________________
186 TGeoVolume*
187 AliFMDGeometryBuilder::RingGeometry(const AliFMDRing* r) 
188 {
189   // Setup the geometry of a ring.    The defined TGeoVolume is
190   // returned, and should be used when setting up the rest of the
191   // volumes. 
192   // 
193   // 
194   // Parameters:
195   //
196   //     r              Pointer to ring geometry object 
197   // 
198   // Returns:
199   //    pointer to ring volume 
200   //
201   if (!r) { 
202     AliError("Didn't get a ring object");
203     return 0;
204   }
205   Char_t        id       = r->GetId();
206   Char_t        rng      = toupper(id);
207   const Char_t* lName    = (rng == 'I' ? "inner" : "outer");
208   Double_t siThick  = r->GetSiThickness();
209   Double_t pcbThick = r->GetPrintboardThickness();
210   Double_t cuThick  = r->GetCopperThickness();
211   Double_t chipThick= r->GetChipThickness();
212   Double_t modSpace = r->GetModuleSpacing();
213   Double_t theta    = r->GetTheta();
214   
215   //------------------------------------------------------------------
216   // Sensor
217   // Physical sensor
218   TGeoShape* sensorShape = MakeXTRU(r->GetSensorVerticies(), siThick);
219   sensorShape->SetName(Form("FMD%c_physical_sensor", id));
220   sensorShape->SetTitle(Form("FMD %s physical sensor", lName));
221   TString sensorName = TString::Format(fgkSensorName, id);
222   TGeoVolume* sensorVolume = new TGeoVolume(sensorName, sensorShape, fSi);
223   sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
224   sensorVolume->VisibleDaughters(kFALSE);
225   Int_t sid = sensorVolume->GetNumber();
226
227   fSectorOff   = -1;
228   fModuleOff   = 1;
229   fRingOff     = 2;
230   fDetectorOff = 3;
231   if (fDetailed) {
232     fSectorOff   = 1;
233     fModuleOff   = 4;
234     fRingOff     = 5;
235     fDetectorOff = 6;
236     // Virtual volume shape to divide - This volume is only defined if
237     // the geometry is set to be detailed. 
238     TGeoTubeSeg* activeShape = new TGeoTubeSeg(r->GetLowR(),
239                                                r->GetHighR(), 
240                                                siThick / 2, 
241                                                - theta, 
242                                                + theta);
243     activeShape->SetName(Form(fgkActiveName, id));
244     activeShape->SetTitle(Form("FMD %s active area", lName));
245     TString activeName = TString::Format(fgkActiveName, id);
246     TGeoVolume* activeVolume = new TGeoVolume(activeName,activeShape,fSi);
247     activeVolume->SetTitle(Form("FMD %s active area", lName));
248     TString sectorName = TString::Format(fgkSectorName,id);
249     TGeoVolume* sectorVolume = activeVolume->Divide(sectorName, 2, 2, -theta,
250                                                     0,0,"N");
251
252     Int_t    ns       = r->GetNStrips();
253     Double_t stripoff = r->GetLowR(); // 0; // a->Mod();
254     Double_t dstrip   = (r->GetHighR() - stripoff) / ns;
255
256     sectorVolume->SetTitle(Form("FMD %s sector", lName));
257     TString stripName = TString::Format(fgkStripName, id);
258     TGeoVolume* stripVolume  = sectorVolume->Divide(stripName, 
259                                                     1, ns, stripoff, dstrip, 
260                                                     0, "SX");
261     stripVolume->SetTitle(Form("FMD %s strip", lName));
262     sid = stripVolume->GetNumber();
263     sensorVolume->AddNodeOverlap(activeVolume, 0);
264   }
265   
266   switch (rng) {
267   case 'I': fActiveId[0] = sid; break;
268   case 'O': fActiveId[1] = sid; break;
269   }
270
271   //------------------------------------------------------------------
272   // Hybrid
273   // PCB layer of hybrid 
274   TGeoShape* pcbShape = MakeXTRU(r->GetHybridVerticies(), pcbThick);
275   pcbShape->SetName(Form("FMD%c_hybrid_pcb", id));
276   pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
277   TString pcbName = TString::Format(fgkPCBName, id);
278   TGeoVolume* pcbVolume = new TGeoVolume(pcbName, pcbShape, fPCB);
279   pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
280
281   // Copper layer
282   TGeoShape* cuShape = MakeXTRU(r->GetHybridVerticies(), cuThick);
283   cuShape->SetName(Form("FMD%c_hybrid_copper", id));
284   cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
285   TString cuName = TString::Format(fgkCuName,id);
286   TGeoVolume* cuVolume = new TGeoVolume(cuName,cuShape,fCopper);
287   cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
288
289   // Chip layer
290   TGeoShape* chipShape = MakeXTRU(r->GetHybridVerticies(), chipThick);
291   chipShape->SetName(Form("FMD%c_hybrid_chip", id));
292   chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
293   TString chipName = TString::Format(fgkChipName,id);
294   TGeoVolume* chipVolume = new TGeoVolume(chipName,chipShape,fChip);
295   chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
296
297   //------------------------------------------------------------------
298   // Legs
299   Double_t      legr     = r->GetLegRadius();
300   Double_t      legl     = r->GetLegLength();
301   Double_t      lege     = .05;
302
303   // Short leg shape 
304   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, (legl-lege) / 2);
305   shortLegShape->SetName(Form(fgkShortLegName, id));
306   shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
307   TString shortLegName = TString::Format(fgkShortLegName, id);
308   TGeoVolume* shortLegVolume = new TGeoVolume(shortLegName, 
309                                               shortLegShape, fCopper);
310   shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
311   // Long leg shape
312   TGeoTube*   longLegShape   = new TGeoTube(0, legr, 
313                                             (legl - lege + modSpace) / 2);
314   longLegShape->SetName(Form(fgkLongLegName, id));
315   longLegShape->SetTitle(Form("FMD %s long support foot", lName));
316   TString longLegName = TString::Format(fgkLongLegName, id);
317   TGeoVolume* longLegVolume = new TGeoVolume(longLegName, 
318                                               longLegShape, fCopper);
319   longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
320   
321
322
323   //------------------------------------------------------------------
324   // Placement of module volumes in assemblies 
325   TArrayD xfs(3);
326   TArrayD yfs(3);
327   for (Int_t i = 0; i < 3; i++) { 
328     TVector2* vv = r->GetFootPosition(i);
329     // TVector2  uu = vv->Rotate(TMath::Pi()/2);
330     xfs[i]       = vv->Y();
331     yfs[i]       = vv->X();
332   }
333
334   // Back container volume 
335   TGeoVolume* backVolume     = new TGeoVolumeAssembly(Form(fgkBackVName, id));
336   backVolume->SetTitle(Form("FMD %s back module", lName));
337   TGeoVolume* frontVolume    = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
338   frontVolume->SetTitle(Form("FMD %s front module", lName));
339
340   Double_t space    = r->GetSpacing();
341   Double_t x        = 0;
342   Double_t y        = 0;
343   Double_t zb       = siThick / 2;
344   Double_t zf       = siThick / 2;
345   backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zb));
346   frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zf));
347   zb         += siThick / 2 + space + pcbThick / 2;
348   zf         += siThick / 2 + space + pcbThick / 2;
349   backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zb));
350   frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zf));
351   zb         += (pcbThick + cuThick) / 2;
352   zf         += (pcbThick + cuThick) / 2;
353   backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zf));
354   frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zb));
355   zb         += (cuThick + chipThick) / 2;
356   zf         += (cuThick + chipThick) / 2;
357   backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zb));
358   frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zf));
359   zb         += pcbThick / 2 + (legl)/ 2  - lege;
360   zf         += pcbThick / 2 + (legl + modSpace)/ 2 - lege;
361   for (Int_t i = 0; i < 3; i++) { 
362     x          =  xfs[i]; // a->X() + legoff + legr;
363     y          =  yfs[i]; // 0;
364     backVolume->AddNode(shortLegVolume, i, new TGeoTranslation(x,y,zb));
365     frontVolume->AddNode(longLegVolume, i, new TGeoTranslation(x,y,zf));
366   }
367
368   //------------------------------------------------------------------
369   // FMDD 
370   Double_t ddlr = r->GetFMDDLowR();
371   Double_t ddhr = r->GetFMDDHighR();
372   Double_t ddpt = r->GetFMDDPrintboardThickness();
373   Double_t ddct = r->GetFMDDCopperThickness();
374   Double_t ddit = r->GetFMDDChipThickness();
375   Double_t ddt  = ddpt + ddct + ddit;
376   
377   TString    pcbdName(Form(fgkFMDDPCBName, id));
378   TString    cudName(Form(fgkFMDDCuName, id));
379   TString    chipdName(Form(fgkFMDDChipName, id));
380   new TGeoTubeSeg(Form("%s_inner", pcbdName.Data()),  ddlr, ddhr, ddpt/2,0,180);
381   new TGeoTubeSeg(Form("%s_inner", cudName.Data()),   ddlr, ddhr, ddct/2,0,180);
382   new TGeoTubeSeg(Form("%s_inner", chipdName.Data()), ddlr, ddhr, ddit/2,0,180);
383   
384   Double_t clipWX = 0;
385   Double_t clipWY = 0;
386   Double_t clipY  = 1;
387   
388   if (rng == 'I') { 
389     clipWX = ddhr;
390     clipWY = ddhr/2;
391   }
392   else { 
393     clipWX = ddlr+3;
394     clipWY = ddhr/2;
395   }
396   
397   new TGeoBBox(Form("%s_clip",  pcbdName.Data()), clipWX, clipWY, ddpt);
398   new TGeoBBox(Form("%s_clip",  cudName.Data()),  clipWX, clipWY, ddct);
399   new TGeoBBox(Form("%s_clip",  chipdName.Data()),clipWX, clipWY, ddit);
400   TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
401                                                     pcbdName.Data()), 
402                                                0, clipWY+clipY, 0);
403   trans->RegisterYourself();
404   TGeoShape* fmddPcbShape = 
405     new TGeoCompositeShape(pcbdName.Data(), 
406                            Form("%s_inner*%s_clip:%s_trans",
407                                 pcbdName.Data(), 
408                                 pcbdName.Data(), 
409                                 pcbdName.Data())); 
410   TGeoShape* fmddCuShape = 
411     new TGeoCompositeShape(cudName.Data(), 
412                            Form("%s_inner*%s_clip:%s_trans",
413                                 cudName.Data(), 
414                                 cudName.Data(), 
415                                 pcbdName.Data()));
416   TGeoShape* fmddChipShape = 
417     new TGeoCompositeShape(chipdName.Data(), 
418                            Form("%s_inner*%s_clip:%s_trans",
419                                 chipdName.Data(), 
420                                 chipdName.Data(), 
421                                 pcbdName.Data()));
422   fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
423   fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
424   fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
425
426   TString fmddPcbName = TString::Format(fgkFMDDPCBName, id);
427   TGeoVolume* fmddPcbVolume = new TGeoVolume(fmddPcbName,
428                                               fmddPcbShape, fPCB);
429   TString fmddCuName = TString::Format(fgkFMDDCuName, id);
430   TGeoVolume* fmddCuVolume = new TGeoVolume(fmddCuName,
431                                               fmddCuShape, fCopper);
432   TString fmddChipName = TString::Format(fgkFMDDChipName, id);
433   TGeoVolume* fmddChipVolume = new TGeoVolume(fmddChipName,
434                                               fmddChipShape, fChip);
435   fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
436   fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
437   fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
438
439   //------------------------------------------------------------------
440   // Half ring mother volumes. 
441   TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
442   TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
443   TGeoVolume* halfRing      = ringTopVolume;
444   ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
445   ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
446   
447   //------------------------------------------------------------------
448   // Adding modules to half-rings
449   Int_t    nmod =  r->GetNModules();
450   AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
451   for (Int_t i = 0; i < nmod; i++) {
452     if (i == nmod / 2) halfRing = ringBotVolume;
453     Bool_t      front =  (i % 2 == (rng == 'I' ? 1 : 0));
454     TGeoVolume* vol   =  (front ? frontVolume : backVolume);
455     // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
456     Double_t    z1    =  (front ? -1 : 1) * modSpace / 2;
457     // Double_t z1    =  (front ? 0 : modSpace);
458     Double_t    th    =  (2 * i + 1) * theta;
459     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
460     mat1->RotateZ(th);
461     mat1->SetName(Form("FMD%c_module_%02d", id, i));
462     mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
463     halfRing->AddNode(vol, i, mat1);
464   }
465
466   //------------------------------------------------------------------
467   // Add the FMDD 
468   Double_t zi = r->GetFullDepth() - ddt;
469   Int_t    n  = 2;
470   for (Int_t i = 0; i  < n; i++) {
471     halfRing             = (i == 0 ? ringTopVolume : ringBotVolume);
472     Double_t      phi    = 360. / n * i;
473     TGeoRotation* rot    = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
474     rot->RotateZ(phi);
475     rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
476     Double_t z =  zi + ddpt / 2;
477     halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
478     z          += (ddpt + ddct) / 2;
479     halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
480     z          += (ddct + ddit) / 2;
481     halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
482   }
483   
484
485   return 0;
486 }
487
488
489 //____________________________________________________________________
490 TGeoShape*
491 AliFMDGeometryBuilder::HoneycombShape(Int_t id, Char_t ring,
492                                       double r1, double r2, 
493                                       double w, double t, double c)
494 {
495   // Make a honey comb shape from passed parameters.
496   // Parameters: 
497   //   id       Detector identifier (1,2, or 3)
498   //   ring     Ring identifier ('I' or 'O')
499   //   r1       Inner radius
500   //   r2       Outer radius
501   //   w        width 
502   //   t        Thickness of material 
503   //   c        Clearing from horizontal. 
504   // Return 
505   //   Pointer to newly allocated composite shape. 
506   TString      form  = Form("FMD%d%c_%%c_%%c", id, ring);
507   double       a1    = TMath::ATan2(c, r1) * 180  / TMath::Pi();
508
509   TString      fn    = Form(form.Data(),'F','1');
510   TString      bn    = Form(form.Data(),'B','1');
511   TString      cn    = Form(form.Data(),'C','O');
512   TString      in    = Form(form.Data(),'R','I');
513   TString      on    = Form(form.Data(),'R','O');
514   TString      en    = Form(form.Data(),'E','X');
515   double       y     = c;
516   double       x     = r1 * TMath::Cos(TMath::Pi()*a1/180);
517   new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
518   new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
519   new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
520   new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
521   new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
522   new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
523     
524   TString          ftn = Form(form.Data(),'F','T');
525   TString          btn = Form(form.Data(),'F','B');
526   TString          ltn = Form(form.Data(),'C','L');
527   TString          rtn = Form(form.Data(),'C','R');
528   TString          etn = Form(form.Data(),'E','X');
529   (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
530   (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
531   (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
532   (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
533   (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
534   
535   TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s", 
536                     fn.Data(),ftn.Data(),
537                     bn.Data(),btn.Data(),
538                     in.Data(),on.Data(),
539                     cn.Data(),ltn.Data(),
540                     cn.Data(),rtn.Data(),
541                     en.Data(),etn.Data()));
542   TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
543   shape->SetName(Form(fgkHCName,id,ring));
544   shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
545   return shape;
546 }
547
548 //____________________________________________________________________
549 TGeoVolume* 
550 AliFMDGeometryBuilder::TensionBox()
551 {
552   // 
553   // Get the tension box volume
554   // 
555   // 
556   // Return:
557   //    
558   //
559   static TGeoVolumeAssembly* tensionBox = 0;
560   if (tensionBox) return tensionBox;
561   
562   TGeoBBox* tensionEndS = new TGeoBBox("FMD_tension_end", .6, 3,  .25);
563   TGeoBBox* tensionTopS = new TGeoBBox("FMD_tension_top", .1, .5, 3.5);
564   TGeoVolume* tensionEndV = new TGeoVolume("FMD_tension_end", tensionEndS,fAl);
565   TGeoVolume* tensionTopV = new TGeoVolume("FMD_tension_top", tensionTopS,fAl);
566   tensionBox = new TGeoVolumeAssembly("FMD_tension_box");
567   tensionBox->AddNode(tensionEndV, 1, new TGeoTranslation(.6, 0,   -3.75));
568   tensionBox->AddNode(tensionEndV, 2, new TGeoTranslation(.6, 0,   +3.75));
569   tensionBox->AddNode(tensionTopV, 1, new TGeoTranslation(0.1, +2.5, 0));
570   tensionBox->AddNode(tensionTopV, 2, new TGeoTranslation(0.1, -2.5, 0));
571   tensionBox->AddNode(tensionTopV, 3, new TGeoTranslation(1.1, +2.5, 0));
572   tensionBox->AddNode(tensionTopV, 4, new TGeoTranslation(1.1, -2.5, 0));
573   return tensionBox;
574 }
575
576
577 //____________________________________________________________________
578 TGeoVolume*
579 AliFMDGeometryBuilder::DetectorGeometry(const AliFMDDetector* d, 
580                                         TGeoVolume* topMother, 
581                                         TGeoVolume* botMother, 
582                                         Double_t    zMother, 
583                                         TGeoVolume* innerTop, 
584                                         TGeoVolume* innerBot, 
585                                         TGeoVolume* outerTop, 
586                                         TGeoVolume* outerBot) 
587 {
588   // Common stuff for setting up the FMD1, FMD2, and FMD3 geometries.
589   // This includes putting the Honeycomb support plates and the rings
590   // into the mother volumes.   
591   // 
592   // Parameeters:
593   //    d         The detector geometry to use 
594   //    mother    The mother volume of the detector 
595   //    zmother   The midpoint in global coordinates of detector vol.
596   //    inner     Pointer to inner ring volume 
597   //    outer     Pointer to outer ring volume
598   //
599   // Returns:
600   //    Pointer to mother (detector volume) 
601   // 
602   if (!d) return 0;
603   // Loop over the defined rings 
604   for (int i = 0; i < 2; i++) {
605     AliFMDRing* r     = 0;
606     Double_t    lowr  = 0;
607     Double_t    highr = 0;
608     Double_t    rz    = 0;
609     TGeoVolume* tvol  = 0;
610     TGeoVolume* bvol  = 0;
611     switch (i) {
612     case 0: 
613       r      = d->GetInner();
614       lowr   = d->GetInnerHoneyLowR();
615       highr  = d->GetInnerHoneyHighR();
616       rz     = d->GetInnerZ();
617       tvol   = innerTop;
618       bvol   = innerBot;
619       break;
620     case 1: 
621       r      = d->GetOuter();
622       lowr   = d->GetOuterHoneyLowR();
623       highr  = d->GetOuterHoneyHighR();
624       rz     = d->GetOuterZ();
625       tvol   = outerTop;
626       bvol   = outerBot;
627       break;
628     }
629     if (!r) continue;
630     Char_t   c       = r->GetId();
631     Int_t    id      = d->GetId();
632     Double_t hcThick = r->GetHoneycombThickness();
633     Double_t alThick = r->GetAlThickness();
634     Double_t z       = TMath::Abs(rz - zMother);
635
636     // Place ring in mother volume
637     // TGeoMatrix*matrix=new TGeoTranslation(Form("FMD%d%c trans",id,c),0,0,0);
638     AliFMDDebug(2, ("Placing volumes %s and %s in %s and %s at z=%f", 
639                      tvol->GetName(), bvol->GetName(), 
640                      topMother->GetName(), botMother->GetName(), z));
641     topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
642     botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
643
644     // Honeycomp 
645     TGeoShape*   hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
646     TGeoVolume*  hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
647     hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
648     
649     z += (r->GetModuleDepth() 
650           + r->GetModuleSpacing() / 2
651           + r->GetHoneycombThickness() / 2);
652
653     AliFMDDebug(15, ("Placing a copy of %s in %s and %s at z=%f", 
654                       hcVol->GetName(), topMother->GetName(), 
655                       botMother->GetName(), z));
656     // Add to top 
657     topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
658
659     // Add to bottom
660     TGeoMatrix*   bhcMatrix = new TGeoCombiTrans(0,0,z,0);
661     bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
662     bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
663     bhcMatrix->RotateZ(180);
664     botMother->AddNode(hcVol, 1, bhcMatrix);
665   }
666   return 0;
667 }
668
669 //____________________________________________________________________
670 TGeoVolume*
671 AliFMDGeometryBuilder::FMD1Geometry(const AliFMD1* fmd1, 
672                                     TGeoVolume* innerTop, 
673                                     TGeoVolume* innerBot) 
674 {
675   // Setup the FMD1 geometry.  The FMD1 only has one ring, and no
676   // special support as it is at the momement. 
677   // 
678   // See also AliFMDGeometryBuilder::DetectorGeometry 
679   // 
680   if (!fmd1 || !innerTop || !innerBot) return 0;
681   AliFMDRing* r             = fmd1->GetInner();
682   Double_t    z             = fmd1->GetInnerZ();  
683   
684   // `Top' or `Outside' master volume
685   TString fmd1TopName = TString::Format(fgkFMDName, fmd1->GetId(), 'T');
686   TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(fmd1TopName);
687   fmd1TopVolume->SetTitle("FMD1 top half");
688
689   // `Bottom' or `Inside' master volume
690   TString fmd1BotName = TString::Format(fgkFMDName, fmd1->GetId(), 'B');
691   TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(fmd1BotName);
692   fmd1BotVolume->SetTitle("FMD1 bottom half");
693   
694   // Basic detector geometry 
695   DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, 
696                    innerTop, innerBot, 0, 0);
697
698   Double_t lidP[][3] = { {  0.00,  4.20, 20.95 }, 
699                          {  0.15,  4.20, 20.95 }, 
700                          {  0.15, 20.80, 20.95 }, 
701                          {  3.00, 20.80, 20.95 }, 
702                          {  3.00, 20.80, 22.30 }, 
703                          {  3.15, 20.80, 22.30 }, 
704                          {  3.15, 20.95, 24.65 },
705                          {  3.30, 20.95, 24.65 }, 
706                          {  3.30, 24.50, 24.65 }, 
707                          {  6.80, 24.50, 24.65 },
708                          {  6.80, 24.50, 26.00 },
709                          {  6.95, 24.50, 26.00 } };
710   Double_t  lidZStart = lidP[11][0];
711   TGeoPcon* lidBaseS  = new TGeoPcon("FMD1_lid_base", 0, 180, 12);
712   for (size_t i = 0; i < 12; i++) 
713     lidBaseS->DefineSection(i, lidP[i][0] - lidZStart, lidP[i][1], lidP[i][2]);
714   
715   
716   Double_t lidH[][2] = { {  7.84903, 24.15680  }, 
717                          { 20.54900, 14.92970  },
718                          { 21.99700, 12.70000  },
719                          { 25.26090,  2.65502  } };
720   Double_t lidHR = .53 / 2;
721   Double_t lidHL = 0.16;
722   
723   new TGeoTube("FMD1_lid_hole", 0, lidHR, lidHL/2);
724   TString lidComp("FMD1_lid_base-(");
725   TGeoTranslation* trans = 0;
726   for (size_t i = 0; i < 4; i++) { 
727     trans = new TGeoTranslation(-lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
728     trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+0)));
729     trans->RegisterYourself();
730     trans = new TGeoTranslation(+lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
731     trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+1)));
732     trans->RegisterYourself();
733     lidComp.Append(Form("FMD1_lid_hole:FMD1_lid_hole_mat%d+" 
734                         "FMD1_lid_hole:FMD1_lid_hole_mat%d%c", 
735                         int(2 * i), int(2 * i + 1), int(i == 3 ? ')' : '+')));
736   }
737   TGeoCompositeShape* lidS = new TGeoCompositeShape(lidComp.Data());
738   lidS->SetName("FMD1_lid");
739   TGeoVolume* lidV = new TGeoVolume("FMD1_lid", lidS, fC);
740   lidV->SetTransparency(63);
741   
742   // Place top cover
743   Double_t lidZ = (lidZStart - 
744                    (3.3 - r->GetModuleDepth() - r->GetModuleSpacing() / 2));
745   AliFMDDebug(1, ("FMD1 lid offset in Z=%f", lidZ));
746
747   for (Int_t i = 0; i  < 2; i++) {
748     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
749     Double_t      phi    = 360. / 2 * i;
750     TGeoRotation* rot    = new TGeoRotation(Form("FMD1_lid_rot%d",i));
751     rot->RotateZ(phi);
752     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1_lid_mat%d", i),
753                                               0, 0, lidZ, rot);
754     mother->AddNode(lidV, i, matrix);    
755   }
756
757   // Must add this after filling the assembly.
758   TGeoVolume* top    = gGeoManager->GetVolume("ALIC");
759   // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
760   TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
761   rot->RotateZ(90);
762   TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
763
764   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
765                    fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
766   top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
767   top->AddNode(fmd1BotVolume, fmd1->GetId(), matrix);
768
769
770   // Survey points on V0A (screw holes for the FMD) 
771   const Double_t icb[] = { +12.700, -21.997, 324.670 };
772   const Double_t ict[] = { +12.700, +21.997, 324.670 };
773   const Double_t ocb[] = { -12.700, -21.997, 324.670 };
774   const Double_t oct[] = { -12.700, +21.997, 324.670 };
775
776   TGeoTube* surveyShape = new TGeoTube("FMD1_survey_marker", 
777                                         0, .2, .001);
778
779   TGeoMatrix* outMat = matrix;
780 #if 0
781   if (gGeoManager->cd("/ALIC_1/F1MT_1")) 
782     outMat = gGeoManager->GetCurrentMatrix();
783   else 
784     AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
785 #endif
786
787   Double_t loct[3], locb[3];
788   outMat->MasterToLocal(oct, loct);
789   outMat->MasterToLocal(ocb, locb);
790   TGeoVolume* vOct = new TGeoVolume("V0L_OCT", surveyShape, fPlastic);
791   TGeoVolume* vOcb = new TGeoVolume("V0L_OCB", surveyShape, fPlastic);
792   
793   fmd1TopVolume->AddNode(vOct, 1, new TGeoTranslation(loct[0],loct[1],loct[2]));
794   fmd1TopVolume->AddNode(vOcb, 1, new TGeoTranslation(locb[0],locb[1],locb[2]));
795     
796   
797   TGeoMatrix* inMat = matrix;
798 #if 0
799   if (gGeoManager->cd("/ALIC_1/F1MT_1")) 
800     inMat = gGeoManager->GetCurrentMatrix();
801   else 
802     AliWarning("Couldn't cd to /ALIC_1/F1MT_1");
803 #endif
804
805   Double_t lict[3], licb[3];
806   inMat->MasterToLocal(ict, lict);
807   inMat->MasterToLocal(icb, licb);
808   TGeoVolume* vIct = new TGeoVolume("V0L_ICT", surveyShape, fPlastic);
809   TGeoVolume* vIcb = new TGeoVolume("V0L_ICB", surveyShape, fPlastic);
810   
811   fmd1BotVolume->AddNode(vIct, 1, new TGeoTranslation(lict[0],lict[1],lict[2]));
812   fmd1BotVolume->AddNode(vIcb, 1, new TGeoTranslation(licb[0],licb[1],licb[2]));
813
814   return 0;
815 }
816
817 //____________________________________________________________________
818 TGeoVolume*
819 AliFMDGeometryBuilder::FMD2Geometry(const AliFMD2* fmd2, 
820                                     TGeoVolume* innerTop, 
821                                     TGeoVolume* innerBot, 
822                                     TGeoVolume* outerTop,
823                                     TGeoVolume* outerBot) 
824 {
825   // Setup the FMD2 geometry.  The FMD2 has no
826   // special support as it is at the momement. 
827   // 
828   // See also AliFMDGeometryBuilder::DetectorGeometry 
829   // 
830   if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
831   AliFMDRing* ring          = fmd2->GetOuter();
832   Double_t    z             = fmd2->GetOuterZ();  
833   Double_t    framelr       = 32.01;  // fmd2->GetOuterHoneyHighR()+0.5;
834   Double_t    framehr       = 33.611; // fmd2->GetOuterHoneyHighR()+1.8;
835   Double_t    framel        = 14.8; // framehz - framelz;
836   // Double_t    backth        = 0.3;
837   Double_t    backth        = 0.03;
838   Double_t    framelz       = -(2.38 
839                                 - ring->GetModuleDepth() 
840                                 - ring->GetModuleSpacing() / 2);
841   // Double_t    framelz       = -0.8;
842   // Double_t    framehz       = framelz + backth + framel;
843   Double_t    coverlr       = 4.3; // fmd2->GetInner()->GetLowR()+1;
844   Double_t    coverhr       = framehr; //  - 1;
845   
846   TString fmd2TopName = TString::Format(fgkFMDName, fmd2->GetId(), 'T');
847   TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(fmd2TopName);
848   TString fmd2BotName = TString::Format(fgkFMDName, fmd2->GetId(), 'B');
849   TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(fmd2BotName);
850   fmd2TopVolume->SetTitle("FMD2 top half");
851   fmd2BotVolume->SetTitle("FMD2 bottom half");
852   
853   DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, 
854                    innerTop, innerBot, outerTop, outerBot);
855
856   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("FMD2_support");
857   TGeoShape*  cylinderShape   = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
858   TGeoVolume* cylinderVolume  = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
859                                                cylinderShape, fC);
860   TGeoShape*  coverShape      = new TGeoTubeSeg(coverlr,coverhr,backth/2,0,180);
861   TGeoVolume* coverVolume     = new TGeoVolume(Form(fgkTopName, fmd2->GetId()), 
862                                                coverShape, fC);
863   cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
864   cylinderShape->SetTitle("FMD2 cylinder");
865   cylinderVolume->SetTitle("FMD2 cylinder");
866   cylinderVolume->SetTransparency(63);
867   coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
868   coverShape->SetTitle("FMD2 cover");
869   coverVolume->SetTitle("FMD2 cover");
870   coverVolume->SetTransparency(63);
871   
872   TGeoTranslation* trans = 0;
873   support->AddNode(coverVolume,1, new TGeoTranslation(0,0,backth/2));
874   support->AddNode(cylinderVolume, 1, new TGeoTranslation(0,0,backth+framel/2));
875   
876
877   Double_t    f1l            = 15.6085;
878   Double_t    f1w            = 6;
879   Double_t    f1d            = 1;
880   Int_t       nFiducialHoles = 4;
881   Double_t    precHoles[][2] = { { 32.4948, 29.6663 },
882                                  { 33.9104, 31.0819 },
883                                  { 34.8177, 33.4035 }, 
884                                  { 35.5028, 32.6744 } };
885   Double_t    precRadius     = .25;
886   Double_t    flangeA        = TMath::Pi()/4;
887   
888   new TGeoBBox("FMD2_flange_base", f1l/2, f1w/2, f1d/2);
889   new TGeoTube("FMD2_fiducial_hole", 0, precRadius, f1d/2+.1);
890   Double_t         flangeX        = framehr + f1l/2;
891   TVector2         flangeC(flangeX * TMath::Cos(flangeA), 
892                            flangeX * TMath::Sin(flangeA));
893   TString          flangeComb("FMD2_flange_base-(");  
894   new TGeoBBox("FMD2_flange_slit", 7./2, 1.5/2, f1d/2+.1);
895   trans = new TGeoTranslation(-f1l/2+1+7./2, +.5+1.5/2, 0);
896   trans->SetName("FMD2_flange_slit_mat1");
897   trans->RegisterYourself();
898   trans = new TGeoTranslation(-f1l/2+1+7./2, -.5-1.5/2, 0);
899   trans->SetName("FMD2_flange_slit_mat2");
900   trans->RegisterYourself();
901   flangeComb.Append("FMD2_flange_slit:FMD2_flange_slit_mat1+"
902                     "FMD2_flange_slit:FMD2_flange_slit_mat2+");
903   for (Int_t i = 0; i < nFiducialHoles; i++) { 
904     TVector2         v(precHoles[i][0], precHoles[i][1]);
905     v                   -= flangeC;
906     TVector2         r  =  v.Rotate(-flangeA);
907     TGeoTranslation* t1 =  new TGeoTranslation(r.X(),  r.Y(), 0);
908     TGeoTranslation* t2 =  new TGeoTranslation(r.X(), -r.Y(), 0);
909     t1->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+0));
910     t2->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+1));
911     t1->RegisterYourself();
912     t2->RegisterYourself();
913     flangeComb.Append(Form("FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d+"
914                            "FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d%c",
915                            2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
916   }
917   // Final flange shape, and at to full shape 
918   TGeoCompositeShape* flangeS = new TGeoCompositeShape(flangeComb.Data());
919   flangeS->SetName("FMD2_flange");
920   TGeoVolume* flangeV = new TGeoVolume("FMD2_flange", flangeS, fAl);
921   
922   Double_t f2l = 7;
923   Double_t f2d = 12.5;
924   Double_t f2w = 1;
925
926   new TGeoBBox("FMD2_flange_spacer_base", f2l/2, f2w/2, f2d/2);
927   new TGeoTube("FMD2_flange_spacer_hole", 0, 2.5, f2w/2+.1);
928   TGeoRotation* holeRot = new TGeoRotation();
929   holeRot->RotateY(90);
930   holeRot->RotateZ(90);
931   TGeoCombiTrans* combo = 0;
932   combo = new TGeoCombiTrans(0, 0, f2d/2-.5-2.5, holeRot);
933   combo->SetName("FMD2_flange_spacer_hole_mat1");
934   combo->RegisterYourself();
935   combo = new TGeoCombiTrans(0, 0, -f2d/2+.5+2.5, holeRot);
936   combo->SetName("FMD2_flange_spacer_hole_mat2");
937   combo->RegisterYourself();
938   TString spacerComp("FMD2_flange_spacer_base-("
939                      "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat1+"
940                      "FMD2_flange_spacer_hole:FMD2_flange_spacer_hole_mat2)");
941   TGeoCompositeShape* spacerS = new TGeoCompositeShape(spacerComp.Data());
942   TGeoVolume*         spacerV = new TGeoVolume("FMD2_flange_spacer",
943                                                spacerS, fAl);
944
945   Double_t            extraL  = framehr-framelr;
946   TGeoBBox*           extraS  = new TGeoBBox("FMD2_flange_extra", 
947                                              extraL/2, f1w/2, f1d/2);
948   TGeoVolume*         extraV  = new TGeoVolume("FMD2_flange_extra", extraS,fAl);
949   TGeoVolumeAssembly* wingV   = new TGeoVolumeAssembly("FMD2_wing");
950   TGeoVolume*         tension = TensionBox();
951   TGeoTube*           wireS   = new TGeoTube(0, .05, (framehr-coverlr)/2);
952   TGeoVolume*         wireV   = new TGeoVolume("FMD2_tension_wire", 
953                                                wireS, fSteel);
954   wingV->AddNode(flangeV, 1, new TGeoTranslation(f1l/2,    0, f1d/2));
955   wingV->AddNode(flangeV, 2, new TGeoTranslation(f1l/2,    0, -f2d-f1d/2));
956   wingV->AddNode(extraV, 1, new TGeoCombiTrans(-extraL/2, 0, f1d/2, 0));
957   wingV->AddNode(spacerV, 1, new TGeoTranslation(1+f2l/2,-f2w/2+f1w/2,
958                                                  -f2d/2));
959   wingV->AddNode(spacerV, 2, new TGeoTranslation(1+f2l/2,+f2w/2-f1w/2,
960                                                  -f2d/2));
961   TGeoRotation* tensionR = new TGeoRotation;
962   tensionR->RotateY(90);
963   wingV->AddNode(tension, 1, new TGeoCombiTrans(4, 0, f1d+1.2, tensionR));
964   TGeoRotation* wireR = new TGeoRotation;
965   wireR->RotateY(90);
966   wingV->AddNode(wireV, 1, new TGeoCombiTrans(-(framehr-coverlr)/2, 0, f1d+1,
967                                               wireR));
968   
969   TGeoCombiTrans* extraM1 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
970   extraM1->RotateZ(45);
971   extraM1->RegisterYourself();
972   extraM1->SetName("FMD2_back_cover_slit1");
973   TGeoCombiTrans* extraM2 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
974   extraM2->RotateZ(135);
975   extraM2->RegisterYourself();
976   extraM2->SetName("FMD2_back_cover_slit2");
977   TString coverComp(Form(fgkTopName, fmd2->GetId()));
978   coverComp.Append("-(FMD2_flange_extra:FMD2_back_cover_slit1"
979                    "+FMD2_flange_extra:FMD2_back_cover_slit2)");
980   TGeoCompositeShape* cover2Shape = new TGeoCompositeShape(coverComp.Data());
981   cover2Shape->SetName("FMD2_back_cover");
982   TGeoVolume* cover2Volume = new TGeoVolume("FMD2_back_cover", cover2Shape,fC);
983   support->AddNode(cover2Volume,2, 
984                    new TGeoTranslation(0,0,backth+framel+backth/2));
985
986   TGeoCombiTrans* trans1 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
987   TGeoCombiTrans* trans2 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
988   trans1->RotateZ(45);
989   trans2->RotateZ(135);
990   support->AddNode(wingV, 1, trans1);
991   support->AddNode(wingV, 2, trans2);
992   AliFMDDebug(1, ("FMD2 support offset is %f", framelz));
993   
994   for (Int_t i = 0; i  < 2; i++) {
995     TGeoVolume*   mother = (i < 1 ? fmd2TopVolume : fmd2BotVolume);
996     
997     Double_t      phi    = 360. / 2 * i;
998     TGeoRotation* rot    = new TGeoRotation(Form("FMD2 support rot %d",i)); 
999     rot->RotateZ(phi);
1000     TGeoMatrix*   matrix = new TGeoCombiTrans(0, 0, framelz, rot);
1001     mother->AddNode(support, i, matrix);    
1002   }
1003   
1004   // Must be done after filling the assemblies 
1005   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
1006   TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
1007   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
1008                    fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
1009   top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
1010   top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
1011
1012
1013   return 0;
1014 }
1015   
1016 //____________________________________________________________________
1017 TGeoVolume*
1018 AliFMDGeometryBuilder::FMD3Geometry(const AliFMD3* fmd3, 
1019                                     TGeoVolume* innerTop, 
1020                                     TGeoVolume* innerBot, 
1021                                     TGeoVolume* outerTop,
1022                                     TGeoVolume* outerBot) 
1023 {
1024   // Setup the FMD3 geometry.  The FMD2 has a rather elaborate support
1025   // structure, as the support will also support the vacuum
1026   // beam-pipe. 
1027   // 
1028   // See also AliFMDGeometryBuilder::DetectorGeometry 
1029   // 
1030   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
1031
1032   //__________________________________________________________________
1033   // Basic detector set-up.
1034   TString fmd3TopName = TString::Format(fgkFMDName, fmd3->GetId(), 'T');
1035   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(fmd3TopName);
1036   TString fmd3BotName = TString::Format(fgkFMDName, fmd3->GetId(), 'B');
1037   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(fmd3BotName);
1038   fmd3TopVolume->SetTitle("FMD3 top half");
1039   fmd3BotVolume->SetTitle("FMD3 bottom half");
1040   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(), 
1041                    innerTop, innerBot, outerTop, outerBot);
1042
1043   //__________________________________________________________________
1044   // Mother for all support material
1045   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
1046   support->SetTitle("FMD3 support");
1047
1048   //__________________________________________________________________
1049   // Base of cone
1050   const TObjArray& radii    = fmd3->ConeRadii();
1051   Int_t            nRadii   = radii.GetEntriesFast();
1052   TGeoPcon*        coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
1053   TVector3*        r5       = 0;
1054   TVector3*        r4       = 0;
1055   for (Int_t i = 0; i < nRadii; i++) { 
1056     TVector3* v = static_cast<TVector3*>(radii.At(i));
1057     coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
1058     if      (i == 5) r5 = v;
1059     else if (i == 4) r4 = v;
1060   }
1061   TString          coneComb("(FMD3_cone_base");
1062
1063   //__________________________________________________________________
1064   // Flanges 
1065   double    flangeDepth    = fmd3->GetFlangeDepth() / 2;
1066   double    flangeLength   = fmd3->GetFlangeLength() / 2;
1067   double    flangeWidth    = fmd3->GetFlangeWidth() / 2;
1068   new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
1069
1070   // Fiducial holes 
1071   const TObjArray& fiducialHoles  = fmd3->FiducialHoles();
1072   double           fiducialRadius = fmd3->GetFiducialRadius();
1073 #if 0
1074   TGeoTube*        fiducialShape  = 
1075 #endif
1076     new TGeoTube("FMD3_fiducial_hole", 0, fiducialRadius, flangeDepth+.1);
1077   Int_t            nFiducialHoles = fiducialHoles.GetEntriesFast();
1078   double           flangeAngle    = TMath::Pi() / 4;
1079   double           flangeX        = r5->Y()+flangeLength;
1080   TVector2         flangeC(flangeX * TMath::Cos(flangeAngle), 
1081                            flangeX * TMath::Sin(flangeAngle));
1082   TString          flangeComb("FMD3_flange_base-(");
1083 #if 0// For debugging geometry 
1084   TGeoVolume* fiducialVolume = new TGeoVolume("FMD3_fiducial", fiducialShape);
1085   fiducialVolume->SetLineColor(kGreen);
1086 #endif
1087   for (Int_t i = 0; i < nFiducialHoles; i++) { 
1088     TVector2&        v  =  *(static_cast<TVector2*>(fiducialHoles.At(i)));
1089     v                   -= flangeC;
1090     TVector2         r  =  v.Rotate(-flangeAngle);
1091     TGeoTranslation* t1 =  new TGeoTranslation(r.X(),  r.Y(), 0);
1092     TGeoTranslation* t2 =  new TGeoTranslation(r.X(), -r.Y(), 0);
1093     t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
1094     t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
1095     t1->RegisterYourself();
1096     t2->RegisterYourself();
1097     flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
1098                            "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
1099                            2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
1100 #if 0 // For debugging geometry 
1101     support->AddNode(fiducialVolume, 2*i+0, t1);
1102     support->AddNode(fiducialVolume, 2*i+1, t2);
1103 #endif
1104   }
1105   
1106   // Final flange shape, and at to full shape 
1107   TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
1108   flangeShape->SetName("FMD3_flange");
1109   for (Int_t i = 0; i < 2; i++) { 
1110     TGeoRotation* rot = new TGeoRotation();
1111     rot->RotateZ((i+.5)*90);
1112     TVector2 v(flangeX, 0);
1113     TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
1114     TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
1115                                                r4->X()+flangeDepth, rot);
1116     trans->SetName(Form("FMD3_flange_matrix%d", i));
1117     trans->RegisterYourself();
1118     coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
1119   }
1120   coneComb.Append(")-(");
1121   
1122   //__________________________________________________________________
1123   // Holes 
1124   Double_t holeL  = fmd3->GetHoleLength()/2;
1125   Double_t holeD  = fmd3->GetHoleDepth()/2;
1126   Double_t holeLW = fmd3->GetHoleLowWidth()/2;
1127   Double_t holeHW = fmd3->GetHoleHighWidth()/2;
1128   Double_t holeA  = fmd3->GetConeOuterAngle();
1129   Double_t holeA2 = TMath::Pi() - fmd3->GetConeOuterAngle();
1130   Double_t holeO  = fmd3->GetHoleOffset();
1131   Double_t holeZ  = (holeO
1132                      + holeL * TMath::Cos(holeA)
1133                      - holeD * TMath::Sin(holeA2));
1134   Double_t holeX  = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ())
1135                      - holeD * TMath::Sin(holeA2));
1136   new TGeoTrd1("FMD3_cone_hole", holeLW, holeHW, holeD, holeL);
1137   TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate", 
1138                                       holeLW, holeHW, .033, holeL);
1139   TGeoRotation* holeRot = new TGeoRotation();
1140   holeRot->SetName("FMD3_cone_hole_rotation");
1141   holeRot->RotateZ(90);
1142   holeRot->RotateY(holeA*180/TMath::Pi());
1143   TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
1144   holeBaseTrans->SetName("FMD3_cone_hole_base_matrix");
1145   // TGeoRotation* plateRot = new TGeoRotation();
1146   // plateRot->SetName("FMD3_cone_plate_rotation");
1147   // plateRot->RotateZ(90);
1148   // plateRot->RotateY(plateA*180/TMath::Pi());
1149   // TGeoCombiTrans* plateBaseTrans = new 
1150   //                  TGeoCombiTrans(plateX,0,plateZ,plateRot);
1151   TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate", 
1152                                            plateShape, fAl);
1153   plateShape->SetTitle("FMD3 cooling plate");
1154   plateVolume->SetTitle("FMD3 cooling plate");
1155   for (Int_t i = 0; i < 4; i++) { 
1156     Double_t        ang   = 360. / 8 * (i + .5);
1157     TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
1158     trans->RotateZ(ang);
1159     trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
1160     trans->RegisterYourself();
1161     trans = new TGeoCombiTrans(*holeBaseTrans);
1162     trans->RotateZ(ang);
1163     trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
1164     coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
1165     support->AddNode(plateVolume, i, trans);
1166   }
1167   
1168   //__________________________________________________________________
1169   // Bolts
1170   Double_t boltRadius = fmd3->GetBoltRadius();
1171   Double_t boltLength = fmd3->GetBoltLength() / 2;
1172   Double_t boltZ1     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
1173   Double_t boltZ2     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
1174   Double_t boltXE     = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
1175   Double_t boltX1     = (fmd3->ConeR(boltZ1) - boltXE);
1176   Double_t boltX2     = (fmd3->ConeR(boltZ2) - boltXE);
1177   
1178   new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
1179   TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
1180   TGeoRotation* boltRot = new TGeoRotation();
1181   boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
1182   TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
1183   TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
1184   TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
1185   TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
1186   boltTrans3->RotateZ(180);
1187   boltTrans4->RotateZ(180);
1188   boltTrans1->SetName("FMD3_bolt_matrix1");
1189   boltTrans2->SetName("FMD3_bolt_matrix2");
1190   boltTrans3->SetName("FMD3_bolt_matrix3");
1191   boltTrans4->SetName("FMD3_bolt_matrix4");
1192   boltTrans1->RegisterYourself();
1193   boltTrans2->RegisterYourself();
1194   boltTrans3->RegisterYourself();
1195   boltTrans4->RegisterYourself();
1196   coneComb.Append("FMD3_bolt_hole:FMD3_bolt_matrix1"
1197                   "+FMD3_bolt_hole:FMD3_bolt_matrix2"
1198                   "+FMD3_bolt_hole:FMD3_bolt_matrix3"
1199                   "+FMD3_bolt_hole:FMD3_bolt_matrix4");
1200   TGeoVolume*     boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
1201   support->AddNode(boltVolume, 1, boltTrans1);
1202   support->AddNode(boltVolume, 2, boltTrans2);
1203   boltShape->SetTitle("FMD3 steering bolt");
1204   boltVolume->SetTitle("FMD3 steering bolt");
1205   
1206   //__________________________________________________________________
1207   // Cut-outs for tension wheel sheeve 
1208   new TGeoBBox("FMD3_sheeve_hole", .55, .75, 1.16);
1209   Double_t        sheeveHoleZ = fmd3->GetInnerZ() + fmd3->GetNoseZ() - .75;
1210   Double_t        sheeveHoleR = fmd3->ConeR(sheeveHoleZ) - .55 + .2572222;
1211   TGeoCombiTrans* sheeveMat1  = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1212   TGeoCombiTrans* sheeveMat2  = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
1213   sheeveMat1->RotateZ(45);
1214   sheeveMat2->RotateZ(135);
1215   sheeveMat1->SetName("FMD3_sheeve_hole_matrix1");
1216   sheeveMat2->SetName("FMD3_sheeve_hole_matrix2");
1217   sheeveMat1->RegisterYourself();
1218   sheeveMat2->RegisterYourself();
1219   coneComb.Append("+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix1"
1220                   "+FMD3_sheeve_hole:FMD3_sheeve_hole_matrix2)");
1221   
1222   //__________________________________________________________________
1223   // Sheeve boxes 
1224   Double_t       sheeveL     = 1.15;
1225   TGeoBBox*      sheeveSideS = new TGeoBBox("FMD3_sheeve_side",
1226                                            .55, .25, 1.15);
1227   TGeoBBox*      sheeveBackS = new TGeoBBox("FMD3_sheeve_back", 
1228                                             .55, .25, .15);
1229   TGeoBBox*      sheeveWingS = new TGeoBBox("FMD3_sheeve_wing", 
1230                                             .15, .15, 1.15);
1231   TGeoPcon*      sheeveWheelS = new TGeoPcon("FMD3_sheeve_wheel", 0, 360, 9);
1232   Double_t       sheeveInnerR = 0; // .2;
1233   Double_t       sheeveR      = .875;
1234   Double_t       sheeveWheelZ = .95;
1235   sheeveWheelS->DefineSection(0, -.25,   sheeveInnerR, 1);
1236   sheeveWheelS->DefineSection(1, -.125,  sheeveInnerR, 1);
1237   sheeveWheelS->DefineSection(2, -.125,  sheeveInnerR, sheeveWheelZ);
1238   sheeveWheelS->DefineSection(3, -.0625, sheeveInnerR, sheeveR+.02);
1239   sheeveWheelS->DefineSection(4, 0.000,  sheeveInnerR, sheeveR);
1240   sheeveWheelS->DefineSection(5, +.0625, sheeveInnerR, sheeveR+.02);
1241   sheeveWheelS->DefineSection(6, +.125,  sheeveInnerR, sheeveWheelZ);
1242   sheeveWheelS->DefineSection(7, +.125,  sheeveInnerR, 1);
1243   sheeveWheelS->DefineSection(8, +.25,   sheeveInnerR, 1);
1244   TGeoVolume*    sheeveSideV = new TGeoVolume("FMD3_sheeve_side", 
1245                                               sheeveSideS, fPlastic);
1246   TGeoVolume*    sheeveBackV = new TGeoVolume("FMD3_sheeve_back", 
1247                                               sheeveBackS, fPlastic);
1248   TGeoVolume*    sheeveWingV = new TGeoVolume("FMD3_sheeve_wing", 
1249                                               sheeveWingS, fPlastic);
1250   TGeoVolume*    sheeveWheelV= new TGeoVolume("FMD3_sheeve_wheel", 
1251                                               sheeveWheelS, fPlastic);
1252   TGeoVolumeAssembly* sheeveBox = new TGeoVolumeAssembly("FMD3_sheeve_box");
1253   sheeveBox->AddNode(sheeveSideV, 1, new TGeoTranslation(0, -.5, 0));
1254   sheeveBox->AddNode(sheeveSideV, 2, new TGeoTranslation(0, +.5, 0));
1255   sheeveBox->AddNode(sheeveBackV, 1, new TGeoTranslation(0, 0, 2.0+.15-1.15));
1256   sheeveBox->AddNode(sheeveWingV, 1, new TGeoTranslation(.55-.15, -.90, 0));
1257   sheeveBox->AddNode(sheeveWingV, 2, new TGeoTranslation(.55-.15, +.90, 0));
1258   TGeoRotation*   sheeveWheelR = new TGeoRotation;
1259   sheeveWheelR->RotateX(90);
1260   TGeoCombiTrans* sheeveWheelM = new TGeoCombiTrans(0, 0, sheeveWheelZ-sheeveL,
1261                                                     sheeveWheelR);
1262   sheeveBox->AddNode(sheeveWheelV, 1, sheeveWheelM);
1263   support->AddNode(sheeveBox, 1, sheeveMat1);
1264   support->AddNode(sheeveBox, 2, sheeveMat2);
1265   
1266   
1267
1268   //__________________________________________________________________
1269   // Final cone
1270   TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
1271   coneShape->SetName("FMD3_cone");
1272   coneShape->SetTitle("FMD3 cone");
1273   TGeoVolume*  coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
1274   coneVolume->SetLineColor(kRed);
1275   support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
1276
1277   //__________________________________________________________________
1278   // Tension boxes. 
1279   TGeoVolume*     tensionBox = TensionBox();
1280   Double_t        tensionH  = .6;
1281   Double_t        tensionL  = 4;
1282   Double_t        tensionZ  = 23.654;
1283   Double_t        tensionR  = fmd3->ConeR(fmd3->GetInnerZ() + fmd3->GetNoseZ() 
1284                                           -  tensionZ);
1285   Double_t        tensionAr = fmd3->GetConeOuterAngle();
1286   Double_t        tensionA  = tensionAr * 180 / TMath::Pi();
1287   TGeoRotation*   tensionQ  = new TGeoRotation;
1288   tensionQ->RotateY(tensionA);
1289   TGeoCombiTrans* tensionM1 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1290   TGeoCombiTrans* tensionM2 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
1291   tensionM1->RotateZ(45);
1292   tensionM2->RotateZ(135);
1293   support->AddNode(tensionBox, 1, tensionM1);
1294   support->AddNode(tensionBox, 2, tensionM2);
1295   
1296   // Double_t         tensionHR    = 0.15;
1297   Double_t         wireT        = .1/2;
1298   Double_t         wireZ1       = (tensionZ
1299                                    - tensionL * TMath::Cos(tensionAr) 
1300                                    - tensionH * TMath::Sin(tensionAr));
1301   Double_t         wireR1       = (tensionR 
1302                                    - tensionL * TMath::Sin(tensionAr) 
1303                                    + tensionH * TMath::Cos(tensionAr));
1304   AliFMDDebug(10, ("Wire Z1: %f=%f-%f*cos(%f)-%f*sin(%f)", 
1305                   wireZ1, tensionZ, tensionL, tensionAr, tensionH, tensionAr));
1306   AliFMDDebug(10, ("Wire R1: %f=%f-%f*sin(%f)-%f*cos(%f)", 
1307                   wireR1, tensionR, tensionL, tensionAr, tensionH, tensionAr));
1308   
1309   Double_t         wireStartA   = 42.3 * TMath::Pi() / 180;
1310   Double_t         wireZ2       = (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1311                                    // - sheeveL - 
1312                                    - wireT * TMath::Sin(wireStartA));
1313   /* (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
1314                                    - wireT * TMath::Sin(wireStartA) 
1315                                    - sheeveL); */
1316   AliFMDDebug(10, ("wireZ2=%f=%f*(1-%f)", wireZ2, sheeveWheelZ, 
1317                   TMath::Sin(wireStartA)));
1318   Double_t         wireR2       = (sheeveHoleR + 
1319                                    sheeveWheelZ * TMath::Cos(wireStartA) + 
1320                                    wireT * TMath::Cos(wireStartA));
1321   Double_t         wireDR       = wireR1-wireR2;
1322   Double_t         wireDZ       = wireZ1-wireZ2;
1323   Double_t         wireL        = TMath::Sqrt(wireDR*wireDR+wireDZ*wireDZ)-.01;
1324   Double_t         wireAngle    = TMath::ATan2(wireDR,wireDZ);
1325   TGeoTube*        wireShape    = new TGeoTube("FMD3_wire", 0, wireT, wireL/2);
1326   TGeoVolume*      wireVolume   = new TGeoVolume("FMD3_wire", wireShape,fSteel);
1327   TGeoRotation*    wireRot      = new TGeoRotation();
1328   wireRot->RotateY(180/TMath::Pi()*wireAngle);
1329   Double_t         wireR        = wireR2 + wireDR / 2;
1330   Double_t         wireZ        = wireZ2 + wireDZ / 2;
1331   TGeoCombiTrans*  wireM1       = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1332   TGeoCombiTrans*  wireM2       = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
1333   wireM1->RotateZ(45);
1334   wireM2->RotateZ(135);
1335   support->AddNode(wireVolume, 1, wireM1);
1336   support->AddNode(wireVolume, 2, wireM2);
1337
1338
1339   TGeoTorus*       wireTS  = new TGeoTorus(sheeveWheelZ+wireT, 0, wireT, 0, 
1340                                            90-wireStartA*180/TMath::Pi());
1341   TGeoVolume*      wireTV  = new TGeoVolume("FMD3_bend_wire",wireTS,fSteel);
1342   TGeoRotation*    wireTR  = new TGeoRotation;
1343   wireTR->RotateY(90);
1344   wireTR->RotateZ(-90);
1345   Double_t         wireTZ  = sheeveWheelZ;
1346   TGeoCombiTrans*  wireTM1 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1347   TGeoCombiTrans*  wireTM2 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
1348   wireTM1->RotateZ(45);
1349   wireTM2->RotateZ(135);
1350   support->AddNode(wireTV, 1, wireTM1);
1351   support->AddNode(wireTV, 2, wireTM2);
1352
1353   Double_t         colarR = 4.05;
1354   Double_t         wireEL = sheeveHoleR - colarR;
1355   TGeoTube*        wireES = new TGeoTube("FMD3_end_wire", 0, wireT, wireEL/2);
1356   TGeoVolume*      wireEV = new TGeoVolume("FMD3_end_wire", wireES, fSteel);
1357   TGeoRotation*    wireER = new TGeoRotation;
1358   wireER->RotateY(90);
1359   TGeoCombiTrans*  wireEM1 = new TGeoCombiTrans(colarR+wireEL/2,0,
1360                                                 -wireT,wireER);
1361   TGeoCombiTrans*  wireEM2 = new TGeoCombiTrans(colarR+wireEL/2,0,
1362                                                 -wireT,wireER);
1363   wireEM1->RotateZ(45);
1364   wireEM2->RotateZ(135);
1365   support->AddNode(wireEV, 1, wireEM1);
1366   support->AddNode(wireEV, 2, wireEM2);
1367   
1368   
1369
1370   
1371   //__________________________________________________________________
1372   // Place support volumes in half-detector volumes 
1373   Double_t         z  = fmd3->GetInnerZ();
1374   AliFMDDebug(1, ("FMD3 support at z=%f", -fmd3->GetNoseZ()));
1375   TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
1376   fmd3TopVolume->AddNode(support, 1, t1);
1377   TGeoCombiTrans*  t2 = new TGeoCombiTrans(*t1);
1378   t2->RotateZ(180);
1379   fmd3BotVolume->AddNode(support, 2, t2);
1380
1381   TGeoRotation*   rot        = new TGeoRotation("FMD3 rotatation");
1382   rot->RotateY(180);
1383   TGeoVolume*     top        = gGeoManager->GetVolume("ALIC");
1384   TGeoMatrix* mmatrix        = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
1385   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
1386                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
1387   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
1388   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
1389
1390   return 0;
1391 }
1392
1393
1394 //____________________________________________________________________
1395 void
1396 AliFMDGeometryBuilder::Exec(Option_t*) 
1397 {
1398   // Setup up the FMD geometry. 
1399   AliFMDDebug(1, ("\tGeometry options: %s",
1400                     (fDetailed  ? "divided into strips" : "one volume")));
1401   if (!gGeoManager) {
1402     AliFatal("No TGeoManager defined");
1403     return;
1404   }
1405
1406   fSi      = gGeoManager->GetMedium("FMD_Si$");
1407   fC       = gGeoManager->GetMedium("FMD_Carbon$");
1408   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
1409   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
1410   fAir     = gGeoManager->GetMedium("FMD_Air$");
1411   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
1412   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
1413   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
1414   fSteel   = gGeoManager->GetMedium("FMD_Steel$");
1415
1416   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
1417     AliError("Failed to get some or all tracking mediums");
1418     return;
1419   }    
1420   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
1421   AliFMDRing* inner = fmd->GetInner();
1422   AliFMDRing* outer = fmd->GetOuter();
1423   RingGeometry(inner);
1424   RingGeometry(outer);
1425   TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1426                                                      inner->GetId()));
1427   TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1428                                                      inner->GetId()));
1429   TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
1430                                                      outer->GetId()));
1431   TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
1432                                                      outer->GetId()));
1433   
1434   FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
1435   FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
1436   FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
1437 #ifndef USE_PRE_MOVE
1438   fmd->SetSectorOff(fSectorOff);
1439   fmd->SetModuleOff(fModuleOff);
1440   fmd->SetRingOff(fRingOff);
1441   fmd->SetDetectorOff(fDetectorOff);
1442   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
1443 #endif
1444   // fmd->ExtractGeomInfo();
1445   
1446 }
1447
1448
1449 //____________________________________________________________________
1450 //
1451 // EOF
1452 //