LCOV - code coverage report
Current view: top level - FMD/FMDbase - AliFMDGeometryBuilder.cxx (source / functions) Hit Total Coverage
Test: coverage.info Lines: 809 835 96.9 %
Date: 2016-06-14 17:26:59 Functions: 12 14 85.7 %

          Line data    Source code
       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          12 : 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           0 :   : TTask("FMD", "Geomtry builder"),
     101           0 :     fActiveId(0),
     102           0 :     fDetailed(kTRUE),
     103           0 :     fUseAssembly(kTRUE),
     104           0 :     fSectorOff(0),
     105           0 :     fModuleOff(0),
     106           0 :     fRingOff(0),
     107           0 :     fDetectorOff(0),
     108           0 :     fSi(0),
     109           0 :     fC(0),
     110           0 :     fAl(0),
     111           0 :     fPCB(0),
     112           0 :     fChip(0),
     113           0 :     fAir(0),
     114           0 :     fPlastic(0),
     115           0 :     fCopper(0),
     116           0 :     fSteel(0)
     117           0 : {
     118             :   // Default constructor
     119           0 :   fActiveId.Set(2);
     120           0 : }
     121             : 
     122             : //____________________________________________________________________
     123             : AliFMDGeometryBuilder::AliFMDGeometryBuilder(Bool_t detailed) 
     124           1 :   : TTask("FMD", "Geometry builder"),
     125           1 :     fActiveId(0),
     126           1 :     fDetailed(detailed),
     127           1 :     fUseAssembly(kTRUE),
     128           1 :     fSectorOff(0),
     129           1 :     fModuleOff(0),
     130           1 :     fRingOff(0),
     131           1 :     fDetectorOff(0),
     132           1 :     fSi(0),
     133           1 :     fC(0),
     134           1 :     fAl(0),
     135           1 :     fPCB(0),
     136           1 :     fChip(0),
     137           1 :     fAir(0),
     138           1 :     fPlastic(0),
     139           1 :     fCopper(0),
     140           1 :     fSteel(0)
     141           3 : {
     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           1 :   fActiveId.Set(2);
     150           2 : }
     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          16 :   TArrayD xs(6);
     169           8 :   TArrayD ys(6);
     170          64 :   for (Int_t i = 0; i < 3; i++) { 
     171          48 :     TVector2* v = static_cast<TVector2*>(verticies.At(i+1));
     172          48 :     xs[i]     =  v->Y();
     173          48 :     ys[i]     = -v->X();
     174          48 :     xs[6-1-i] =  v->Y();
     175          48 :     ys[6-1-i] =  v->X();
     176             :   }
     177          16 :   TGeoXtru* shape = new TGeoXtru(2);
     178           8 :   shape->DefinePolygon(xs.fN, xs.fArray, ys.fArray);
     179           8 :   shape->DefineSection(0, -thick/2);
     180           8 :   shape->DefineSection(1, +thick/2);
     181             :   
     182           8 :   return shape;
     183           8 : }
     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           4 :   if (!r) { 
     202           0 :     AliError("Didn't get a ring object");
     203           0 :     return 0;
     204             :   }
     205           2 :   Char_t        id       = r->GetId();
     206           2 :   Char_t        rng      = toupper(id);
     207           2 :   const Char_t* lName    = (rng == 'I' ? "inner" : "outer");
     208           2 :   Double_t siThick  = r->GetSiThickness();
     209           2 :   Double_t pcbThick = r->GetPrintboardThickness();
     210           2 :   Double_t cuThick  = r->GetCopperThickness();
     211           2 :   Double_t chipThick= r->GetChipThickness();
     212           2 :   Double_t modSpace = r->GetModuleSpacing();
     213           2 :   Double_t theta    = r->GetTheta();
     214             :   
     215             :   //------------------------------------------------------------------
     216             :   // Sensor
     217             :   // Physical sensor
     218           2 :   TGeoShape* sensorShape = MakeXTRU(r->GetSensorVerticies(), siThick);
     219           2 :   sensorShape->SetName(Form("FMD%c_physical_sensor", id));
     220           2 :   sensorShape->SetTitle(Form("FMD %s physical sensor", lName));
     221           2 :   TString sensorName = TString::Format(fgkSensorName, id);
     222           6 :   TGeoVolume* sensorVolume = new TGeoVolume(sensorName, sensorShape, fSi);
     223           4 :   sensorVolume->SetTitle(Form("FMD %s Sensor", lName));
     224           2 :   sensorVolume->VisibleDaughters(kFALSE);
     225           2 :   Int_t sid = sensorVolume->GetNumber();
     226             : 
     227           2 :   fSectorOff   = -1;
     228           2 :   fModuleOff   = 1;
     229           2 :   fRingOff     = 2;
     230           2 :   fDetectorOff = 3;
     231           2 :   if (fDetailed) {
     232           2 :     fSectorOff   = 1;
     233           2 :     fModuleOff   = 4;
     234           2 :     fRingOff     = 5;
     235           2 :     fDetectorOff = 6;
     236             :     // Virtual volume shape to divide - This volume is only defined if
     237             :     // the geometry is set to be detailed. 
     238           6 :     TGeoTubeSeg* activeShape = new TGeoTubeSeg(r->GetLowR(),
     239           2 :                                                r->GetHighR(), 
     240           2 :                                                siThick / 2, 
     241           2 :                                                - theta, 
     242             :                                                + theta);
     243           4 :     activeShape->SetName(Form(fgkActiveName, id));
     244           4 :     activeShape->SetTitle(Form("FMD %s active area", lName));
     245           2 :     TString activeName = TString::Format(fgkActiveName, id);
     246           6 :     TGeoVolume* activeVolume = new TGeoVolume(activeName,activeShape,fSi);
     247           4 :     activeVolume->SetTitle(Form("FMD %s active area", lName));
     248           2 :     TString sectorName = TString::Format(fgkSectorName,id);
     249           4 :     TGeoVolume* sectorVolume = activeVolume->Divide(sectorName, 2, 2, -theta,
     250             :                                                     0,0,"N");
     251             : 
     252           2 :     Int_t    ns       = r->GetNStrips();
     253           2 :     Double_t stripoff = r->GetLowR(); // 0; // a->Mod();
     254           2 :     Double_t dstrip   = (r->GetHighR() - stripoff) / ns;
     255             : 
     256           4 :     sectorVolume->SetTitle(Form("FMD %s sector", lName));
     257           2 :     TString stripName = TString::Format(fgkStripName, id);
     258           4 :     TGeoVolume* stripVolume  = sectorVolume->Divide(stripName, 
     259             :                                                     1, ns, stripoff, dstrip, 
     260             :                                                     0, "SX");
     261           4 :     stripVolume->SetTitle(Form("FMD %s strip", lName));
     262           2 :     sid = stripVolume->GetNumber();
     263           2 :     sensorVolume->AddNodeOverlap(activeVolume, 0);
     264           2 :   }
     265             :   
     266           2 :   switch (rng) {
     267           2 :   case 'I': fActiveId[0] = sid; break;
     268           2 :   case 'O': fActiveId[1] = sid; break;
     269             :   }
     270             : 
     271             :   //------------------------------------------------------------------
     272             :   // Hybrid
     273             :   // PCB layer of hybrid 
     274           2 :   TGeoShape* pcbShape = MakeXTRU(r->GetHybridVerticies(), pcbThick);
     275           4 :   pcbShape->SetName(Form("FMD%c_hybrid_pcb", id));
     276           4 :   pcbShape->SetTitle(Form("FMD %s hybrid PCB", lName));
     277           2 :   TString pcbName = TString::Format(fgkPCBName, id);
     278           6 :   TGeoVolume* pcbVolume = new TGeoVolume(pcbName, pcbShape, fPCB);
     279           4 :   pcbVolume->SetTitle(Form("FMD %s hybrid PCB", lName));
     280             : 
     281             :   // Copper layer
     282           2 :   TGeoShape* cuShape = MakeXTRU(r->GetHybridVerticies(), cuThick);
     283           4 :   cuShape->SetName(Form("FMD%c_hybrid_copper", id));
     284           4 :   cuShape->SetTitle(Form("FMD %s hybrid copper", lName));
     285           2 :   TString cuName = TString::Format(fgkCuName,id);
     286           6 :   TGeoVolume* cuVolume = new TGeoVolume(cuName,cuShape,fCopper);
     287           4 :   cuVolume->SetTitle(Form("FMD %s hybrid copper", lName));
     288             : 
     289             :   // Chip layer
     290           2 :   TGeoShape* chipShape = MakeXTRU(r->GetHybridVerticies(), chipThick);
     291           4 :   chipShape->SetName(Form("FMD%c_hybrid_chip", id));
     292           4 :   chipShape->SetTitle(Form("FMD %s hybrid chip", lName));
     293           2 :   TString chipName = TString::Format(fgkChipName,id);
     294           6 :   TGeoVolume* chipVolume = new TGeoVolume(chipName,chipShape,fChip);
     295           4 :   chipVolume->SetTitle(Form("FMD %s hybrid chip", lName));
     296             : 
     297             :   //------------------------------------------------------------------
     298             :   // Legs
     299           2 :   Double_t      legr     = r->GetLegRadius();
     300           2 :   Double_t      legl     = r->GetLegLength();
     301             :   Double_t      lege     = .05;
     302             : 
     303             :   // Short leg shape 
     304           4 :   TGeoTube*   shortLegShape  = new TGeoTube(0, legr, (legl-lege) / 2);
     305           4 :   shortLegShape->SetName(Form(fgkShortLegName, id));
     306           4 :   shortLegShape->SetTitle(Form("FMD %s short support foot", lName));
     307           2 :   TString shortLegName = TString::Format(fgkShortLegName, id);
     308           6 :   TGeoVolume* shortLegVolume = new TGeoVolume(shortLegName, 
     309           2 :                                               shortLegShape, fCopper);
     310           4 :   shortLegVolume->SetTitle(Form("FMD %s short support foot", lName));
     311             :   // Long leg shape
     312           6 :   TGeoTube*   longLegShape   = new TGeoTube(0, legr, 
     313           2 :                                             (legl - lege + modSpace) / 2);
     314           4 :   longLegShape->SetName(Form(fgkLongLegName, id));
     315           4 :   longLegShape->SetTitle(Form("FMD %s long support foot", lName));
     316           2 :   TString longLegName = TString::Format(fgkLongLegName, id);
     317           6 :   TGeoVolume* longLegVolume = new TGeoVolume(longLegName, 
     318           2 :                                               longLegShape, fCopper);
     319           4 :   longLegVolume->SetTitle(Form("FMD %s long support foot", lName));
     320             :   
     321             : 
     322             : 
     323             :   //------------------------------------------------------------------
     324             :   // Placement of module volumes in assemblies 
     325           2 :   TArrayD xfs(3);
     326           2 :   TArrayD yfs(3);
     327          16 :   for (Int_t i = 0; i < 3; i++) { 
     328           6 :     TVector2* vv = r->GetFootPosition(i);
     329             :     // TVector2  uu = vv->Rotate(TMath::Pi()/2);
     330          12 :     xfs[i]       = vv->Y();
     331          12 :     yfs[i]       = vv->X();
     332             :   }
     333             : 
     334             :   // Back container volume 
     335           8 :   TGeoVolume* backVolume     = new TGeoVolumeAssembly(Form(fgkBackVName, id));
     336           4 :   backVolume->SetTitle(Form("FMD %s back module", lName));
     337           8 :   TGeoVolume* frontVolume    = new TGeoVolumeAssembly(Form(fgkFrontVName, id));
     338           4 :   frontVolume->SetTitle(Form("FMD %s front module", lName));
     339             : 
     340           2 :   Double_t space    = r->GetSpacing();
     341             :   Double_t x        = 0;
     342             :   Double_t y        = 0;
     343           2 :   Double_t zb       = siThick / 2;
     344             :   Double_t zf       = siThick / 2;
     345           6 :   backVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zb));
     346           6 :   frontVolume->AddNode(sensorVolume, 0, new TGeoTranslation(x, y, zf));
     347           2 :   zb         += siThick / 2 + space + pcbThick / 2;
     348             :   zf         += siThick / 2 + space + pcbThick / 2;
     349           6 :   backVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zb));
     350           6 :   frontVolume->AddNode(pcbVolume, 0, new TGeoTranslation(x, y, zf));
     351           2 :   zb         += (pcbThick + cuThick) / 2;
     352             :   zf         += (pcbThick + cuThick) / 2;
     353           6 :   backVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zf));
     354           6 :   frontVolume->AddNode(cuVolume, 0, new TGeoTranslation(0, 0, zb));
     355           2 :   zb         += (cuThick + chipThick) / 2;
     356             :   zf         += (cuThick + chipThick) / 2;
     357           6 :   backVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zb));
     358           6 :   frontVolume->AddNode(chipVolume, 0, new TGeoTranslation(0, 0, zf));
     359           2 :   zb         += pcbThick / 2 + (legl)/ 2  - lege;
     360           2 :   zf         += pcbThick / 2 + (legl + modSpace)/ 2 - lege;
     361          16 :   for (Int_t i = 0; i < 3; i++) { 
     362          12 :     x          =  xfs[i]; // a->X() + legoff + legr;
     363          12 :     y          =  yfs[i]; // 0;
     364          18 :     backVolume->AddNode(shortLegVolume, i, new TGeoTranslation(x,y,zb));
     365          18 :     frontVolume->AddNode(longLegVolume, i, new TGeoTranslation(x,y,zf));
     366             :   }
     367             : 
     368             :   //------------------------------------------------------------------
     369             :   // FMDD 
     370           2 :   Double_t ddlr = r->GetFMDDLowR();
     371           2 :   Double_t ddhr = r->GetFMDDHighR();
     372           2 :   Double_t ddpt = r->GetFMDDPrintboardThickness();
     373           2 :   Double_t ddct = r->GetFMDDCopperThickness();
     374           2 :   Double_t ddit = r->GetFMDDChipThickness();
     375           2 :   Double_t ddt  = ddpt + ddct + ddit;
     376             :   
     377           4 :   TString    pcbdName(Form(fgkFMDDPCBName, id));
     378           4 :   TString    cudName(Form(fgkFMDDCuName, id));
     379           4 :   TString    chipdName(Form(fgkFMDDChipName, id));
     380           8 :   new TGeoTubeSeg(Form("%s_inner", pcbdName.Data()),  ddlr, ddhr, ddpt/2,0,180);
     381           8 :   new TGeoTubeSeg(Form("%s_inner", cudName.Data()),   ddlr, ddhr, ddct/2,0,180);
     382           8 :   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           2 :   if (rng == 'I') { 
     389             :     clipWX = ddhr;
     390           1 :     clipWY = ddhr/2;
     391           1 :   }
     392             :   else { 
     393           1 :     clipWX = ddlr+3;
     394           1 :     clipWY = ddhr/2;
     395             :   }
     396             :   
     397           8 :   new TGeoBBox(Form("%s_clip",  pcbdName.Data()), clipWX, clipWY, ddpt);
     398           8 :   new TGeoBBox(Form("%s_clip",  cudName.Data()),  clipWX, clipWY, ddct);
     399           8 :   new TGeoBBox(Form("%s_clip",  chipdName.Data()),clipWX, clipWY, ddit);
     400           8 :   TGeoTranslation* trans = new TGeoTranslation(Form("%s_trans",
     401           2 :                                                     pcbdName.Data()), 
     402           2 :                                                0, clipWY+clipY, 0);
     403           2 :   trans->RegisterYourself();
     404             :   TGeoShape* fmddPcbShape = 
     405           8 :     new TGeoCompositeShape(pcbdName.Data(), 
     406           2 :                            Form("%s_inner*%s_clip:%s_trans",
     407           2 :                                 pcbdName.Data(), 
     408           2 :                                 pcbdName.Data(), 
     409           2 :                                 pcbdName.Data())); 
     410             :   TGeoShape* fmddCuShape = 
     411           8 :     new TGeoCompositeShape(cudName.Data(), 
     412           2 :                            Form("%s_inner*%s_clip:%s_trans",
     413           2 :                                 cudName.Data(), 
     414           2 :                                 cudName.Data(), 
     415           2 :                                 pcbdName.Data()));
     416             :   TGeoShape* fmddChipShape = 
     417           8 :     new TGeoCompositeShape(chipdName.Data(), 
     418           2 :                            Form("%s_inner*%s_clip:%s_trans",
     419           2 :                                 chipdName.Data(), 
     420           2 :                                 chipdName.Data(), 
     421           2 :                                 pcbdName.Data()));
     422           4 :   fmddPcbShape->SetTitle(Form("FMD %s digitiser PCB", lName));
     423           4 :   fmddCuShape->SetTitle(Form("FMD %s digitiser copper", lName));
     424           4 :   fmddChipShape->SetTitle(Form("FMD %s digitiser chip", lName));
     425             : 
     426           2 :   TString fmddPcbName = TString::Format(fgkFMDDPCBName, id);
     427           6 :   TGeoVolume* fmddPcbVolume = new TGeoVolume(fmddPcbName,
     428           2 :                                               fmddPcbShape, fPCB);
     429           2 :   TString fmddCuName = TString::Format(fgkFMDDCuName, id);
     430           6 :   TGeoVolume* fmddCuVolume = new TGeoVolume(fmddCuName,
     431           2 :                                               fmddCuShape, fCopper);
     432           2 :   TString fmddChipName = TString::Format(fgkFMDDChipName, id);
     433           6 :   TGeoVolume* fmddChipVolume = new TGeoVolume(fmddChipName,
     434           2 :                                               fmddChipShape, fChip);
     435           4 :   fmddPcbVolume->SetTitle(Form("FMD %s digitiser PCB", lName));
     436           4 :   fmddCuVolume->SetTitle(Form("FMD %s digitiser copper", lName));
     437           4 :   fmddChipVolume->SetTitle(Form("FMD %s digitiser chip", lName));
     438             : 
     439             :   //------------------------------------------------------------------
     440             :   // Half ring mother volumes. 
     441           8 :   TGeoVolume* ringTopVolume = new TGeoVolumeAssembly(Form(fgkRingTopName,id));
     442           8 :   TGeoVolume* ringBotVolume = new TGeoVolumeAssembly(Form(fgkRingBotName,id));
     443             :   TGeoVolume* halfRing      = ringTopVolume;
     444           4 :   ringTopVolume->SetTitle(Form("FMD %s top half-ring", lName));
     445           4 :   ringBotVolume->SetTitle(Form("FMD %s bottom half-ring", lName));
     446             :   
     447             :   //------------------------------------------------------------------
     448             :   // Adding modules to half-rings
     449           2 :   Int_t    nmod =  r->GetNModules();
     450           8 :   AliFMDDebug(10, ("making %d modules in ring %c", nmod, id));
     451          64 :   for (Int_t i = 0; i < nmod; i++) {
     452          32 :     if (i == nmod / 2) halfRing = ringBotVolume;
     453          30 :     Bool_t      front =  (i % 2 == (rng == 'I' ? 1 : 0));
     454          30 :     TGeoVolume* vol   =  (front ? frontVolume : backVolume);
     455             :     // vol->AddNode(sensorVolume, i, new TGeoTranslation(0,0,siThick/2));
     456          30 :     Double_t    z1    =  (front ? -1 : 1) * modSpace / 2;
     457             :     // Double_t z1    =  (front ? 0 : modSpace);
     458          30 :     Double_t    th    =  (2 * i + 1) * theta;
     459          90 :     TGeoMatrix* mat1  =  new TGeoCombiTrans(0,0,z1,0); 
     460          30 :     mat1->RotateZ(th);
     461          60 :     mat1->SetName(Form("FMD%c_module_%02d", id, i));
     462          60 :     mat1->SetTitle(Form("FMD %s module %2d matrix", lName, i));
     463          30 :     halfRing->AddNode(vol, i, mat1);
     464             :   }
     465             : 
     466             :   //------------------------------------------------------------------
     467             :   // Add the FMDD 
     468           4 :   Double_t zi = r->GetFullDepth() - ddt;
     469             :   Int_t    n  = 2;
     470          12 :   for (Int_t i = 0; i  < n; i++) {
     471           4 :     halfRing             = (i == 0 ? ringTopVolume : ringBotVolume);
     472           4 :     Double_t      phi    = 360. / n * i;
     473          12 :     TGeoRotation* rot    = new TGeoRotation(Form("FMDD%c rotation %d", id, i));
     474           4 :     rot->RotateZ(phi);
     475           8 :     rot->SetTitle(Form("FMD %s digitiser rotation %2d", lName, i));
     476           4 :     Double_t z =  zi + ddpt / 2;
     477          12 :     halfRing->AddNode(fmddPcbVolume, i, new TGeoCombiTrans(0,0,z,rot));
     478           4 :     z          += (ddpt + ddct) / 2;
     479          12 :     halfRing->AddNode(fmddCuVolume, i, new TGeoCombiTrans(0,0,z,rot));
     480           4 :     z          += (ddct + ddit) / 2;
     481          12 :     halfRing->AddNode(fmddChipVolume, i, new TGeoCombiTrans(0,0,z,rot));
     482             :   }
     483             :   
     484             : 
     485             :   return 0;
     486           4 : }
     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          10 :   TString      form  = Form("FMD%d%c_%%c_%%c", id, ring);
     507          10 :   double       a1    = TMath::ATan2(c, r1) * 180  / TMath::Pi();
     508             : 
     509          15 :   TString      fn    = Form(form.Data(),'F','1');
     510          15 :   TString      bn    = Form(form.Data(),'B','1');
     511          15 :   TString      cn    = Form(form.Data(),'C','O');
     512          15 :   TString      in    = Form(form.Data(),'R','I');
     513          15 :   TString      on    = Form(form.Data(),'R','O');
     514          15 :   TString      en    = Form(form.Data(),'E','X');
     515             :   double       y     = c;
     516           5 :   double       x     = r1 * TMath::Cos(TMath::Pi()*a1/180);
     517          15 :   new TGeoTubeSeg(fn.Data(),r1,r2,t/2,0,180);
     518          15 :   new TGeoTubeSeg(bn.Data(),r1,r2,t/2,0,180);
     519          15 :   new TGeoBBox(cn.Data(),(r2-r1)/2,t/2,w/2);
     520          15 :   new TGeoTubeSeg(in.Data(),r1,r1+t,w/2,0,180);
     521          15 :   new TGeoTubeSeg(on.Data(),r2-t,r2,w/2,0,180);
     522          15 :   new TGeoBBox(en.Data(),r2+.005,c/2+.005,w/2+.005);
     523             :     
     524          15 :   TString          ftn = Form(form.Data(),'F','T');
     525          15 :   TString          btn = Form(form.Data(),'F','B');
     526          15 :   TString          ltn = Form(form.Data(),'C','L');
     527          15 :   TString          rtn = Form(form.Data(),'C','R');
     528          15 :   TString          etn = Form(form.Data(),'E','X');
     529          20 :   (new TGeoTranslation(ftn.Data(),0,0,+w/2-t/2))->RegisterYourself();
     530          20 :   (new TGeoTranslation(btn.Data(),0,0,-w/2+t/2))->RegisterYourself();
     531          20 :   (new TGeoTranslation(ltn.Data(),-(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
     532          20 :   (new TGeoTranslation(rtn.Data(),(x+(r2-r1)/2), y+t/2,0))->RegisterYourself();
     533          20 :   (new TGeoTranslation(etn.Data(),0, c/2,0))->RegisterYourself();
     534             :   
     535          15 :   TString comp(Form("(%s:%s+%s:%s+%s+%s+%s:%s+%s:%s)-%s:%s", 
     536          10 :                     fn.Data(),ftn.Data(),
     537          10 :                     bn.Data(),btn.Data(),
     538          10 :                     in.Data(),on.Data(),
     539          10 :                     cn.Data(),ltn.Data(),
     540          10 :                     cn.Data(),rtn.Data(),
     541          10 :                     en.Data(),etn.Data()));
     542          15 :   TGeoCompositeShape* shape = new TGeoCompositeShape(comp.Data());
     543          10 :   shape->SetName(Form(fgkHCName,id,ring));
     544          10 :   shape->SetTitle(Form("FMD%d%c Honeycomb shape", id, ring));
     545           5 :   return shape;
     546           5 : }
     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           5 :   if (tensionBox) return tensionBox;
     561             :   
     562           1 :   TGeoBBox* tensionEndS = new TGeoBBox("FMD_tension_end", .6, 3,  .25);
     563           1 :   TGeoBBox* tensionTopS = new TGeoBBox("FMD_tension_top", .1, .5, 3.5);
     564           1 :   TGeoVolume* tensionEndV = new TGeoVolume("FMD_tension_end", tensionEndS,fAl);
     565           1 :   TGeoVolume* tensionTopV = new TGeoVolume("FMD_tension_top", tensionTopS,fAl);
     566           2 :   tensionBox = new TGeoVolumeAssembly("FMD_tension_box");
     567           2 :   tensionBox->AddNode(tensionEndV, 1, new TGeoTranslation(.6, 0,   -3.75));
     568           2 :   tensionBox->AddNode(tensionEndV, 2, new TGeoTranslation(.6, 0,   +3.75));
     569           2 :   tensionBox->AddNode(tensionTopV, 1, new TGeoTranslation(0.1, +2.5, 0));
     570           2 :   tensionBox->AddNode(tensionTopV, 2, new TGeoTranslation(0.1, -2.5, 0));
     571           2 :   tensionBox->AddNode(tensionTopV, 3, new TGeoTranslation(1.1, +2.5, 0));
     572           2 :   tensionBox->AddNode(tensionTopV, 4, new TGeoTranslation(1.1, -2.5, 0));
     573           1 :   return tensionBox;
     574           2 : }
     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           6 :   if (!d) return 0;
     603             :   // Loop over the defined rings 
     604          18 :   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          12 :     switch (i) {
     612             :     case 0: 
     613           3 :       r      = d->GetInner();
     614           3 :       lowr   = d->GetInnerHoneyLowR();
     615           3 :       highr  = d->GetInnerHoneyHighR();
     616           3 :       rz     = d->GetInnerZ();
     617             :       tvol   = innerTop;
     618             :       bvol   = innerBot;
     619           3 :       break;
     620             :     case 1: 
     621           3 :       r      = d->GetOuter();
     622           3 :       lowr   = d->GetOuterHoneyLowR();
     623           3 :       highr  = d->GetOuterHoneyHighR();
     624           3 :       rz     = d->GetOuterZ();
     625             :       tvol   = outerTop;
     626             :       bvol   = outerBot;
     627           3 :       break;
     628             :     }
     629           7 :     if (!r) continue;
     630           5 :     Char_t   c       = r->GetId();
     631           5 :     Int_t    id      = d->GetId();
     632           5 :     Double_t hcThick = r->GetHoneycombThickness();
     633           5 :     Double_t alThick = r->GetAlThickness();
     634           5 :     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          10 :     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          10 :     topMother->AddNode(tvol, Int_t(c), new TGeoTranslation(0,0,z));
     642          10 :     botMother->AddNode(bvol, Int_t(c), new TGeoTranslation(0,0,z));
     643             : 
     644             :     // Honeycomp 
     645           5 :     TGeoShape*   hcSha = HoneycombShape(id, c, lowr, highr, hcThick, alThick);
     646          10 :     TGeoVolume*  hcVol = new TGeoVolume(Form(fgkHCName,id,c),hcSha,fAl);
     647           5 :     hcVol->SetTitle(Form("FMD%d%c honeycomb shell", id, c));
     648             :     
     649          10 :     z += (r->GetModuleDepth() 
     650           5 :           + r->GetModuleSpacing() / 2
     651           5 :           + r->GetHoneycombThickness() / 2);
     652             : 
     653          10 :     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          10 :     topMother->AddNode(hcVol, 0, new TGeoTranslation(0, 0, z));
     658             : 
     659             :     // Add to bottom
     660          10 :     TGeoMatrix*   bhcMatrix = new TGeoCombiTrans(0,0,z,0);
     661           5 :     bhcMatrix->SetName(Form("FMD%d%c_honeycomp", id, c));
     662           5 :     bhcMatrix->SetTitle(Form("FMD%d%c honeycomp", id, c));
     663           5 :     bhcMatrix->RotateZ(180);
     664           5 :     botMother->AddNode(hcVol, 1, bhcMatrix);
     665           5 :   }
     666           3 :   return 0;
     667           3 : }
     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           2 :   if (!fmd1 || !innerTop || !innerBot) return 0;
     681           1 :   AliFMDRing* r             = fmd1->GetInner();
     682           1 :   Double_t    z             = fmd1->GetInnerZ();  
     683             :   
     684             :   // `Top' or `Outside' master volume
     685           1 :   TString fmd1TopName = TString::Format(fgkFMDName, fmd1->GetId(), 'T');
     686           4 :   TGeoVolume* fmd1TopVolume = new TGeoVolumeAssembly(fmd1TopName);
     687           1 :   fmd1TopVolume->SetTitle("FMD1 top half");
     688             : 
     689             :   // `Bottom' or `Inside' master volume
     690           1 :   TString fmd1BotName = TString::Format(fgkFMDName, fmd1->GetId(), 'B');
     691           4 :   TGeoVolume* fmd1BotVolume = new TGeoVolumeAssembly(fmd1BotName);
     692           1 :   fmd1BotVolume->SetTitle("FMD1 bottom half");
     693             :   
     694             :   // Basic detector geometry 
     695           1 :   DetectorGeometry(fmd1, fmd1TopVolume, fmd1BotVolume, z, 
     696             :                    innerTop, innerBot, 0, 0);
     697             : 
     698           1 :   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           1 :   Double_t  lidZStart = lidP[11][0];
     711           2 :   TGeoPcon* lidBaseS  = new TGeoPcon("FMD1_lid_base", 0, 180, 12);
     712          26 :   for (size_t i = 0; i < 12; i++) 
     713          12 :     lidBaseS->DefineSection(i, lidP[i][0] - lidZStart, lidP[i][1], lidP[i][2]);
     714             :   
     715             :   
     716           1 :   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           2 :   new TGeoTube("FMD1_lid_hole", 0, lidHR, lidHL/2);
     724           1 :   TString lidComp("FMD1_lid_base-(");
     725             :   TGeoTranslation* trans = 0;
     726          10 :   for (size_t i = 0; i < 4; i++) { 
     727           8 :     trans = new TGeoTranslation(-lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
     728           8 :     trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+0)));
     729           4 :     trans->RegisterYourself();
     730           8 :     trans = new TGeoTranslation(+lidH[i][0], lidH[i][1], /*6.95*/-lidHL/2);
     731           8 :     trans->SetName(Form("FMD1_lid_hole_mat%d", int(2*i+1)));
     732           4 :     trans->RegisterYourself();
     733           8 :     lidComp.Append(Form("FMD1_lid_hole:FMD1_lid_hole_mat%d+" 
     734             :                         "FMD1_lid_hole:FMD1_lid_hole_mat%d%c", 
     735           4 :                         int(2 * i), int(2 * i + 1), int(i == 3 ? ')' : '+')));
     736             :   }
     737           3 :   TGeoCompositeShape* lidS = new TGeoCompositeShape(lidComp.Data());
     738           1 :   lidS->SetName("FMD1_lid");
     739           2 :   TGeoVolume* lidV = new TGeoVolume("FMD1_lid", lidS, fC);
     740           1 :   lidV->SetTransparency(63);
     741             :   
     742             :   // Place top cover
     743           1 :   Double_t lidZ = (lidZStart - 
     744           2 :                    (3.3 - r->GetModuleDepth() - r->GetModuleSpacing() / 2));
     745           4 :   AliFMDDebug(1, ("FMD1 lid offset in Z=%f", lidZ));
     746             : 
     747           6 :   for (Int_t i = 0; i  < 2; i++) {
     748           2 :     TGeoVolume*   mother = (i == 0 ? fmd1TopVolume : fmd1BotVolume);
     749           2 :     Double_t      phi    = 360. / 2 * i;
     750           6 :     TGeoRotation* rot    = new TGeoRotation(Form("FMD1_lid_rot%d",i));
     751           2 :     rot->RotateZ(phi);
     752           8 :     TGeoMatrix* matrix   = new TGeoCombiTrans(Form("FMD1_lid_mat%d", i),
     753             :                                               0, 0, lidZ, rot);
     754           2 :     mother->AddNode(lidV, i, matrix);    
     755             :   }
     756             : 
     757             :   // Must add this after filling the assembly.
     758           1 :   TGeoVolume* top    = gGeoManager->GetVolume("ALIC");
     759             :   // TGeoMatrix* matrix = new TGeoTranslation("FMD1 trans", 0, 0, z);
     760           2 :   TGeoRotation* rot = new TGeoRotation("FMD1 rotatation");
     761           1 :   rot->RotateZ(90);
     762           3 :   TGeoMatrix* matrix = new TGeoCombiTrans("FMD1 trans", 0, 0, z, rot);
     763             : 
     764           4 :   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
     765             :                    fmd1TopVolume->GetName(), fmd1BotVolume->GetName(), z));
     766           1 :   top->AddNode(fmd1TopVolume, fmd1->GetId(), matrix);
     767           1 :   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           2 :   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           1 :   Double_t loct[3], locb[3];
     788           1 :   outMat->MasterToLocal(oct, loct);
     789           1 :   outMat->MasterToLocal(ocb, locb);
     790           2 :   TGeoVolume* vOct = new TGeoVolume("V0L_OCT", surveyShape, fPlastic);
     791           2 :   TGeoVolume* vOcb = new TGeoVolume("V0L_OCB", surveyShape, fPlastic);
     792             :   
     793           3 :   fmd1TopVolume->AddNode(vOct, 1, new TGeoTranslation(loct[0],loct[1],loct[2]));
     794           3 :   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           1 :   Double_t lict[3], licb[3];
     806           1 :   inMat->MasterToLocal(ict, lict);
     807           1 :   inMat->MasterToLocal(icb, licb);
     808           2 :   TGeoVolume* vIct = new TGeoVolume("V0L_ICT", surveyShape, fPlastic);
     809           2 :   TGeoVolume* vIcb = new TGeoVolume("V0L_ICB", surveyShape, fPlastic);
     810             :   
     811           3 :   fmd1BotVolume->AddNode(vIct, 1, new TGeoTranslation(lict[0],lict[1],lict[2]));
     812           3 :   fmd1BotVolume->AddNode(vIcb, 1, new TGeoTranslation(licb[0],licb[1],licb[2]));
     813             : 
     814             :   return 0;
     815           2 : }
     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           2 :   if (!fmd2 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
     831           1 :   AliFMDRing* ring          = fmd2->GetOuter();
     832           1 :   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           1 :   Double_t    framelz       = -(2.38 
     839           1 :                                 - ring->GetModuleDepth() 
     840           1 :                                 - 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           1 :   TString fmd2TopName = TString::Format(fgkFMDName, fmd2->GetId(), 'T');
     847           4 :   TGeoVolume* fmd2TopVolume = new TGeoVolumeAssembly(fmd2TopName);
     848           1 :   TString fmd2BotName = TString::Format(fgkFMDName, fmd2->GetId(), 'B');
     849           4 :   TGeoVolume* fmd2BotVolume = new TGeoVolumeAssembly(fmd2BotName);
     850           1 :   fmd2TopVolume->SetTitle("FMD2 top half");
     851           1 :   fmd2BotVolume->SetTitle("FMD2 bottom half");
     852             :   
     853           1 :   DetectorGeometry(fmd2, fmd2TopVolume, fmd2BotVolume, z, 
     854             :                    innerTop, innerBot, outerTop, outerBot);
     855             : 
     856           2 :   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("FMD2_support");
     857           3 :   TGeoShape*  cylinderShape   = new TGeoTubeSeg(framelr,framehr,framel/2,0,180);
     858           3 :   TGeoVolume* cylinderVolume  = new TGeoVolume(Form(fgkBackName, fmd2->GetId()),
     859           1 :                                                cylinderShape, fC);
     860           3 :   TGeoShape*  coverShape      = new TGeoTubeSeg(coverlr,coverhr,backth/2,0,180);
     861           3 :   TGeoVolume* coverVolume     = new TGeoVolume(Form(fgkTopName, fmd2->GetId()), 
     862           1 :                                                coverShape, fC);
     863           2 :   cylinderShape->SetName(Form(fgkBackName, fmd2->GetId()));
     864           1 :   cylinderShape->SetTitle("FMD2 cylinder");
     865           1 :   cylinderVolume->SetTitle("FMD2 cylinder");
     866           1 :   cylinderVolume->SetTransparency(63);
     867           2 :   coverShape->SetName(Form(fgkTopName, fmd2->GetId()));
     868           1 :   coverShape->SetTitle("FMD2 cover");
     869           1 :   coverVolume->SetTitle("FMD2 cover");
     870           1 :   coverVolume->SetTransparency(63);
     871             :   
     872             :   TGeoTranslation* trans = 0;
     873           3 :   support->AddNode(coverVolume,1, new TGeoTranslation(0,0,backth/2));
     874           3 :   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           1 :   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           1 :   Double_t    flangeA        = TMath::Pi()/4;
     887             :   
     888           2 :   new TGeoBBox("FMD2_flange_base", f1l/2, f1w/2, f1d/2);
     889           2 :   new TGeoTube("FMD2_fiducial_hole", 0, precRadius, f1d/2+.1);
     890           1 :   Double_t         flangeX        = framehr + f1l/2;
     891           2 :   TVector2         flangeC(flangeX * TMath::Cos(flangeA), 
     892           1 :                            flangeX * TMath::Sin(flangeA));
     893           1 :   TString          flangeComb("FMD2_flange_base-(");  
     894           2 :   new TGeoBBox("FMD2_flange_slit", 7./2, 1.5/2, f1d/2+.1);
     895           2 :   trans = new TGeoTranslation(-f1l/2+1+7./2, +.5+1.5/2, 0);
     896           1 :   trans->SetName("FMD2_flange_slit_mat1");
     897           1 :   trans->RegisterYourself();
     898           2 :   trans = new TGeoTranslation(-f1l/2+1+7./2, -.5-1.5/2, 0);
     899           1 :   trans->SetName("FMD2_flange_slit_mat2");
     900           1 :   trans->RegisterYourself();
     901           1 :   flangeComb.Append("FMD2_flange_slit:FMD2_flange_slit_mat1+"
     902             :                     "FMD2_flange_slit:FMD2_flange_slit_mat2+");
     903          10 :   for (Int_t i = 0; i < nFiducialHoles; i++) { 
     904           4 :     TVector2         v(precHoles[i][0], precHoles[i][1]);
     905           4 :     v                   -= flangeC;
     906           4 :     TVector2         r  =  v.Rotate(-flangeA);
     907           8 :     TGeoTranslation* t1 =  new TGeoTranslation(r.X(),  r.Y(), 0);
     908           8 :     TGeoTranslation* t2 =  new TGeoTranslation(r.X(), -r.Y(), 0);
     909           8 :     t1->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+0));
     910           8 :     t2->SetName(Form("FMD2_fiducial_hole_rot%d", 2*i+1));
     911           4 :     t1->RegisterYourself();
     912           4 :     t2->RegisterYourself();
     913           8 :     flangeComb.Append(Form("FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d+"
     914             :                            "FMD2_fiducial_hole:FMD2_fiducial_hole_rot%d%c",
     915           4 :                            2*i+0, 2*i+1, (i == nFiducialHoles-1 ? ')' : '+')));
     916           4 :   }
     917             :   // Final flange shape, and at to full shape 
     918           3 :   TGeoCompositeShape* flangeS = new TGeoCompositeShape(flangeComb.Data());
     919           1 :   flangeS->SetName("FMD2_flange");
     920           2 :   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           2 :   new TGeoBBox("FMD2_flange_spacer_base", f2l/2, f2w/2, f2d/2);
     927           2 :   new TGeoTube("FMD2_flange_spacer_hole", 0, 2.5, f2w/2+.1);
     928           2 :   TGeoRotation* holeRot = new TGeoRotation();
     929           1 :   holeRot->RotateY(90);
     930           1 :   holeRot->RotateZ(90);
     931             :   TGeoCombiTrans* combo = 0;
     932           2 :   combo = new TGeoCombiTrans(0, 0, f2d/2-.5-2.5, holeRot);
     933           1 :   combo->SetName("FMD2_flange_spacer_hole_mat1");
     934           1 :   combo->RegisterYourself();
     935           2 :   combo = new TGeoCombiTrans(0, 0, -f2d/2+.5+2.5, holeRot);
     936           1 :   combo->SetName("FMD2_flange_spacer_hole_mat2");
     937           1 :   combo->RegisterYourself();
     938           1 :   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           3 :   TGeoCompositeShape* spacerS = new TGeoCompositeShape(spacerComp.Data());
     942           3 :   TGeoVolume*         spacerV = new TGeoVolume("FMD2_flange_spacer",
     943           1 :                                                spacerS, fAl);
     944             : 
     945             :   Double_t            extraL  = framehr-framelr;
     946           3 :   TGeoBBox*           extraS  = new TGeoBBox("FMD2_flange_extra", 
     947           1 :                                              extraL/2, f1w/2, f1d/2);
     948           2 :   TGeoVolume*         extraV  = new TGeoVolume("FMD2_flange_extra", extraS,fAl);
     949           2 :   TGeoVolumeAssembly* wingV   = new TGeoVolumeAssembly("FMD2_wing");
     950           1 :   TGeoVolume*         tension = TensionBox();
     951           2 :   TGeoTube*           wireS   = new TGeoTube(0, .05, (framehr-coverlr)/2);
     952           3 :   TGeoVolume*         wireV   = new TGeoVolume("FMD2_tension_wire", 
     953           1 :                                                wireS, fSteel);
     954           3 :   wingV->AddNode(flangeV, 1, new TGeoTranslation(f1l/2,    0, f1d/2));
     955           3 :   wingV->AddNode(flangeV, 2, new TGeoTranslation(f1l/2,    0, -f2d-f1d/2));
     956           3 :   wingV->AddNode(extraV, 1, new TGeoCombiTrans(-extraL/2, 0, f1d/2, 0));
     957           3 :   wingV->AddNode(spacerV, 1, new TGeoTranslation(1+f2l/2,-f2w/2+f1w/2,
     958             :                                                  -f2d/2));
     959           3 :   wingV->AddNode(spacerV, 2, new TGeoTranslation(1+f2l/2,+f2w/2-f1w/2,
     960             :                                                  -f2d/2));
     961           2 :   TGeoRotation* tensionR = new TGeoRotation;
     962           1 :   tensionR->RotateY(90);
     963           3 :   wingV->AddNode(tension, 1, new TGeoCombiTrans(4, 0, f1d+1.2, tensionR));
     964           2 :   TGeoRotation* wireR = new TGeoRotation;
     965           1 :   wireR->RotateY(90);
     966           3 :   wingV->AddNode(wireV, 1, new TGeoCombiTrans(-(framehr-coverlr)/2, 0, f1d+1,
     967             :                                               wireR));
     968             :   
     969           2 :   TGeoCombiTrans* extraM1 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
     970           1 :   extraM1->RotateZ(45);
     971           1 :   extraM1->RegisterYourself();
     972           1 :   extraM1->SetName("FMD2_back_cover_slit1");
     973           2 :   TGeoCombiTrans* extraM2 = new TGeoCombiTrans(coverhr-extraL/2,0,0,0);
     974           1 :   extraM2->RotateZ(135);
     975           1 :   extraM2->RegisterYourself();
     976           1 :   extraM2->SetName("FMD2_back_cover_slit2");
     977           2 :   TString coverComp(Form(fgkTopName, fmd2->GetId()));
     978           1 :   coverComp.Append("-(FMD2_flange_extra:FMD2_back_cover_slit1"
     979             :                    "+FMD2_flange_extra:FMD2_back_cover_slit2)");
     980           3 :   TGeoCompositeShape* cover2Shape = new TGeoCompositeShape(coverComp.Data());
     981           1 :   cover2Shape->SetName("FMD2_back_cover");
     982           2 :   TGeoVolume* cover2Volume = new TGeoVolume("FMD2_back_cover", cover2Shape,fC);
     983           2 :   support->AddNode(cover2Volume,2, 
     984           3 :                    new TGeoTranslation(0,0,backth+framel+backth/2));
     985             : 
     986           2 :   TGeoCombiTrans* trans1 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
     987           2 :   TGeoCombiTrans* trans2 = new TGeoCombiTrans(framehr, 0, backth+framel, 0);
     988           1 :   trans1->RotateZ(45);
     989           1 :   trans2->RotateZ(135);
     990           1 :   support->AddNode(wingV, 1, trans1);
     991           1 :   support->AddNode(wingV, 2, trans2);
     992           4 :   AliFMDDebug(1, ("FMD2 support offset is %f", framelz));
     993             :   
     994           6 :   for (Int_t i = 0; i  < 2; i++) {
     995           2 :     TGeoVolume*   mother = (i < 1 ? fmd2TopVolume : fmd2BotVolume);
     996             :     
     997           2 :     Double_t      phi    = 360. / 2 * i;
     998           6 :     TGeoRotation* rot    = new TGeoRotation(Form("FMD2 support rot %d",i)); 
     999           2 :     rot->RotateZ(phi);
    1000           6 :     TGeoMatrix*   matrix = new TGeoCombiTrans(0, 0, framelz, rot);
    1001           2 :     mother->AddNode(support, i, matrix);    
    1002             :   }
    1003             :   
    1004             :   // Must be done after filling the assemblies 
    1005           1 :   TGeoVolume* top = gGeoManager->GetVolume("ALIC");
    1006           3 :   TGeoMatrix* matrix = new TGeoTranslation("FMD2 trans", 0, 0, z);
    1007           4 :   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
    1008             :                    fmd2TopVolume->GetName(), fmd2BotVolume->GetName(), z));
    1009           1 :   top->AddNode(fmd2TopVolume, fmd2->GetId(), matrix);
    1010           1 :   top->AddNode(fmd2BotVolume, fmd2->GetId(), matrix);
    1011             : 
    1012             : 
    1013             :   return 0;
    1014           2 : }
    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           2 :   if (!fmd3 || !innerTop || !innerBot || !outerTop || !outerBot) return 0;
    1031             : 
    1032             :   //__________________________________________________________________
    1033             :   // Basic detector set-up.
    1034           1 :   TString fmd3TopName = TString::Format(fgkFMDName, fmd3->GetId(), 'T');
    1035           4 :   TGeoVolume* fmd3TopVolume = new TGeoVolumeAssembly(fmd3TopName);
    1036           1 :   TString fmd3BotName = TString::Format(fgkFMDName, fmd3->GetId(), 'B');
    1037           4 :   TGeoVolume* fmd3BotVolume = new TGeoVolumeAssembly(fmd3BotName);
    1038           1 :   fmd3TopVolume->SetTitle("FMD3 top half");
    1039           1 :   fmd3BotVolume->SetTitle("FMD3 bottom half");
    1040           1 :   DetectorGeometry(fmd3, fmd3TopVolume, fmd3BotVolume, fmd3->GetInnerZ(), 
    1041             :                    innerTop, innerBot, outerTop, outerBot);
    1042             : 
    1043             :   //__________________________________________________________________
    1044             :   // Mother for all support material
    1045           2 :   TGeoVolumeAssembly* support = new TGeoVolumeAssembly("F3SU");
    1046           1 :   support->SetTitle("FMD3 support");
    1047             : 
    1048             :   //__________________________________________________________________
    1049             :   // Base of cone
    1050           1 :   const TObjArray& radii    = fmd3->ConeRadii();
    1051           1 :   Int_t            nRadii   = radii.GetEntriesFast();
    1052           2 :   TGeoPcon*        coneBase = new TGeoPcon("FMD3_cone_base", 0., 180., nRadii);
    1053             :   TVector3*        r5       = 0;
    1054             :   TVector3*        r4       = 0;
    1055          14 :   for (Int_t i = 0; i < nRadii; i++) { 
    1056          12 :     TVector3* v = static_cast<TVector3*>(radii.At(i));
    1057           6 :     coneBase->DefineSection(i, v->X(), v->Y(), v->Z());
    1058           7 :     if      (i == 5) r5 = v;
    1059           6 :     else if (i == 4) r4 = v;
    1060             :   }
    1061           1 :   TString          coneComb("(FMD3_cone_base");
    1062             : 
    1063             :   //__________________________________________________________________
    1064             :   // Flanges 
    1065           1 :   double    flangeDepth    = fmd3->GetFlangeDepth() / 2;
    1066           1 :   double    flangeLength   = fmd3->GetFlangeLength() / 2;
    1067           1 :   double    flangeWidth    = fmd3->GetFlangeWidth() / 2;
    1068           2 :   new TGeoBBox("FMD3_flange_base", flangeLength, flangeWidth, flangeDepth);
    1069             : 
    1070             :   // Fiducial holes 
    1071           1 :   const TObjArray& fiducialHoles  = fmd3->FiducialHoles();
    1072           1 :   double           fiducialRadius = fmd3->GetFiducialRadius();
    1073             : #if 0
    1074             :   TGeoTube*        fiducialShape  = 
    1075             : #endif
    1076           2 :     new TGeoTube("FMD3_fiducial_hole", 0, fiducialRadius, flangeDepth+.1);
    1077           1 :   Int_t            nFiducialHoles = fiducialHoles.GetEntriesFast();
    1078           1 :   double           flangeAngle    = TMath::Pi() / 4;
    1079           1 :   double           flangeX        = r5->Y()+flangeLength;
    1080           2 :   TVector2         flangeC(flangeX * TMath::Cos(flangeAngle), 
    1081           1 :                            flangeX * TMath::Sin(flangeAngle));
    1082           1 :   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          10 :   for (Int_t i = 0; i < nFiducialHoles; i++) { 
    1088           8 :     TVector2&        v  =  *(static_cast<TVector2*>(fiducialHoles.At(i)));
    1089           4 :     v                   -= flangeC;
    1090           4 :     TVector2         r  =  v.Rotate(-flangeAngle);
    1091           8 :     TGeoTranslation* t1 =  new TGeoTranslation(r.X(),  r.Y(), 0);
    1092           8 :     TGeoTranslation* t2 =  new TGeoTranslation(r.X(), -r.Y(), 0);
    1093           8 :     t1->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+0));
    1094           8 :     t2->SetName(Form("FMD3_fiducial_hole_rot%d", 2*i+1));
    1095           4 :     t1->RegisterYourself();
    1096           4 :     t2->RegisterYourself();
    1097           8 :     flangeComb.Append(Form("FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d+"
    1098             :                            "FMD3_fiducial_hole:FMD3_fiducial_hole_rot%d%c",
    1099           4 :                            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           4 :   }
    1105             :   
    1106             :   // Final flange shape, and at to full shape 
    1107           3 :   TGeoCompositeShape* flangeShape = new TGeoCompositeShape(flangeComb.Data());
    1108           1 :   flangeShape->SetName("FMD3_flange");
    1109           6 :   for (Int_t i = 0; i < 2; i++) { 
    1110           4 :     TGeoRotation* rot = new TGeoRotation();
    1111           2 :     rot->RotateZ((i+.5)*90);
    1112           2 :     TVector2 v(flangeX, 0);
    1113           2 :     TVector2 w = v.Rotate((i+.5) * 2 * flangeAngle);
    1114           6 :     TGeoCombiTrans* trans = new TGeoCombiTrans(w.X(),w.Y(),
    1115           2 :                                                r4->X()+flangeDepth, rot);
    1116           4 :     trans->SetName(Form("FMD3_flange_matrix%d", i));
    1117           2 :     trans->RegisterYourself();
    1118           4 :     coneComb.Append(Form("+FMD3_flange:FMD3_flange_matrix%d", i));
    1119           2 :   }
    1120           1 :   coneComb.Append(")-(");
    1121             :   
    1122             :   //__________________________________________________________________
    1123             :   // Holes 
    1124           1 :   Double_t holeL  = fmd3->GetHoleLength()/2;
    1125           1 :   Double_t holeD  = fmd3->GetHoleDepth()/2;
    1126           1 :   Double_t holeLW = fmd3->GetHoleLowWidth()/2;
    1127           1 :   Double_t holeHW = fmd3->GetHoleHighWidth()/2;
    1128           1 :   Double_t holeA  = fmd3->GetConeOuterAngle();
    1129           1 :   Double_t holeA2 = TMath::Pi() - fmd3->GetConeOuterAngle();
    1130           1 :   Double_t holeO  = fmd3->GetHoleOffset();
    1131             :   Double_t holeZ  = (holeO
    1132           1 :                      + holeL * TMath::Cos(holeA)
    1133           1 :                      - holeD * TMath::Sin(holeA2));
    1134           1 :   Double_t holeX  = (fmd3->ConeR(-holeZ + fmd3->GetInnerZ() + fmd3->GetNoseZ())
    1135           1 :                      - holeD * TMath::Sin(holeA2));
    1136           2 :   new TGeoTrd1("FMD3_cone_hole", holeLW, holeHW, holeD, holeL);
    1137           2 :   TGeoTrd1* plateShape = new TGeoTrd1("FMD3_cooling_plate", 
    1138             :                                       holeLW, holeHW, .033, holeL);
    1139           2 :   TGeoRotation* holeRot = new TGeoRotation();
    1140           1 :   holeRot->SetName("FMD3_cone_hole_rotation");
    1141           1 :   holeRot->RotateZ(90);
    1142           1 :   holeRot->RotateY(holeA*180/TMath::Pi());
    1143           2 :   TGeoCombiTrans* holeBaseTrans = new TGeoCombiTrans(holeX, 0, holeZ, holeRot);
    1144           1 :   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           3 :   TGeoVolume* plateVolume = new TGeoVolume("FMD3_cooling_plate", 
    1152           1 :                                            plateShape, fAl);
    1153           1 :   plateShape->SetTitle("FMD3 cooling plate");
    1154           1 :   plateVolume->SetTitle("FMD3 cooling plate");
    1155          10 :   for (Int_t i = 0; i < 4; i++) { 
    1156           4 :     Double_t        ang   = 360. / 8 * (i + .5);
    1157           8 :     TGeoCombiTrans* trans = new TGeoCombiTrans(*holeBaseTrans);
    1158           4 :     trans->RotateZ(ang);
    1159           8 :     trans->SetName(Form("FMD3_cone_hole_matrix%d", i));
    1160           4 :     trans->RegisterYourself();
    1161           8 :     trans = new TGeoCombiTrans(*holeBaseTrans);
    1162           4 :     trans->RotateZ(ang);
    1163           8 :     trans->SetName(Form("FMD3_cooling_plate_matrix%d", i));
    1164           8 :     coneComb.Append(Form("FMD3_cone_hole:FMD3_cone_hole_matrix%d+", i));
    1165           4 :     support->AddNode(plateVolume, i, trans);
    1166             :   }
    1167             :   
    1168             :   //__________________________________________________________________
    1169             :   // Bolts
    1170           1 :   Double_t boltRadius = fmd3->GetBoltRadius();
    1171           1 :   Double_t boltLength = fmd3->GetBoltLength() / 2;
    1172           1 :   Double_t boltZ1     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-10;
    1173           1 :   Double_t boltZ2     = fmd3->GetInnerZ()+fmd3->GetNoseZ()-20;
    1174           1 :   Double_t boltXE     = 2*boltLength*TMath::Cos(fmd3->GetConeOuterAngle());
    1175           2 :   Double_t boltX1     = (fmd3->ConeR(boltZ1) - boltXE);
    1176           2 :   Double_t boltX2     = (fmd3->ConeR(boltZ2) - boltXE);
    1177             :   
    1178           2 :   new TGeoTube("FMD3_bolt_hole", 0, boltRadius, boltLength+.2);
    1179           2 :   TGeoTube* boltShape = new TGeoTube("FMD3_bolt", 0, boltRadius, boltLength);
    1180           2 :   TGeoRotation* boltRot = new TGeoRotation();
    1181           1 :   boltRot->RotateY(-fmd3->GetConeOuterAngle()*180/TMath::Pi());
    1182           2 :   TGeoCombiTrans* boltTrans1 = new TGeoCombiTrans(boltX1, 0, 10, boltRot);
    1183           2 :   TGeoCombiTrans* boltTrans2 = new TGeoCombiTrans(boltX2, 0, 20, boltRot);
    1184           2 :   TGeoCombiTrans* boltTrans3 = new TGeoCombiTrans(*boltTrans1);
    1185           2 :   TGeoCombiTrans* boltTrans4 = new TGeoCombiTrans(*boltTrans2);
    1186           1 :   boltTrans3->RotateZ(180);
    1187           1 :   boltTrans4->RotateZ(180);
    1188           1 :   boltTrans1->SetName("FMD3_bolt_matrix1");
    1189           1 :   boltTrans2->SetName("FMD3_bolt_matrix2");
    1190           1 :   boltTrans3->SetName("FMD3_bolt_matrix3");
    1191           1 :   boltTrans4->SetName("FMD3_bolt_matrix4");
    1192           1 :   boltTrans1->RegisterYourself();
    1193           1 :   boltTrans2->RegisterYourself();
    1194           1 :   boltTrans3->RegisterYourself();
    1195           1 :   boltTrans4->RegisterYourself();
    1196           1 :   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           2 :   TGeoVolume*     boltVolume = new TGeoVolume("FMD3_bolt", boltShape, fSteel);
    1201           1 :   support->AddNode(boltVolume, 1, boltTrans1);
    1202           1 :   support->AddNode(boltVolume, 2, boltTrans2);
    1203           1 :   boltShape->SetTitle("FMD3 steering bolt");
    1204           1 :   boltVolume->SetTitle("FMD3 steering bolt");
    1205             :   
    1206             :   //__________________________________________________________________
    1207             :   // Cut-outs for tension wheel sheeve 
    1208           2 :   new TGeoBBox("FMD3_sheeve_hole", .55, .75, 1.16);
    1209           1 :   Double_t        sheeveHoleZ = fmd3->GetInnerZ() + fmd3->GetNoseZ() - .75;
    1210           2 :   Double_t        sheeveHoleR = fmd3->ConeR(sheeveHoleZ) - .55 + .2572222;
    1211           2 :   TGeoCombiTrans* sheeveMat1  = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
    1212           2 :   TGeoCombiTrans* sheeveMat2  = new TGeoCombiTrans(sheeveHoleR,0,1.15,0);
    1213           1 :   sheeveMat1->RotateZ(45);
    1214           1 :   sheeveMat2->RotateZ(135);
    1215           1 :   sheeveMat1->SetName("FMD3_sheeve_hole_matrix1");
    1216           1 :   sheeveMat2->SetName("FMD3_sheeve_hole_matrix2");
    1217           1 :   sheeveMat1->RegisterYourself();
    1218           1 :   sheeveMat2->RegisterYourself();
    1219           1 :   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           2 :   TGeoBBox*      sheeveSideS = new TGeoBBox("FMD3_sheeve_side",
    1226             :                                            .55, .25, 1.15);
    1227           2 :   TGeoBBox*      sheeveBackS = new TGeoBBox("FMD3_sheeve_back", 
    1228             :                                             .55, .25, .15);
    1229           2 :   TGeoBBox*      sheeveWingS = new TGeoBBox("FMD3_sheeve_wing", 
    1230             :                                             .15, .15, 1.15);
    1231           2 :   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           1 :   sheeveWheelS->DefineSection(0, -.25,   sheeveInnerR, 1);
    1236           1 :   sheeveWheelS->DefineSection(1, -.125,  sheeveInnerR, 1);
    1237           1 :   sheeveWheelS->DefineSection(2, -.125,  sheeveInnerR, sheeveWheelZ);
    1238           1 :   sheeveWheelS->DefineSection(3, -.0625, sheeveInnerR, sheeveR+.02);
    1239           1 :   sheeveWheelS->DefineSection(4, 0.000,  sheeveInnerR, sheeveR);
    1240           1 :   sheeveWheelS->DefineSection(5, +.0625, sheeveInnerR, sheeveR+.02);
    1241           1 :   sheeveWheelS->DefineSection(6, +.125,  sheeveInnerR, sheeveWheelZ);
    1242           1 :   sheeveWheelS->DefineSection(7, +.125,  sheeveInnerR, 1);
    1243           1 :   sheeveWheelS->DefineSection(8, +.25,   sheeveInnerR, 1);
    1244           3 :   TGeoVolume*    sheeveSideV = new TGeoVolume("FMD3_sheeve_side", 
    1245           1 :                                               sheeveSideS, fPlastic);
    1246           3 :   TGeoVolume*    sheeveBackV = new TGeoVolume("FMD3_sheeve_back", 
    1247           1 :                                               sheeveBackS, fPlastic);
    1248           3 :   TGeoVolume*    sheeveWingV = new TGeoVolume("FMD3_sheeve_wing", 
    1249           1 :                                               sheeveWingS, fPlastic);
    1250           3 :   TGeoVolume*    sheeveWheelV= new TGeoVolume("FMD3_sheeve_wheel", 
    1251           1 :                                               sheeveWheelS, fPlastic);
    1252           2 :   TGeoVolumeAssembly* sheeveBox = new TGeoVolumeAssembly("FMD3_sheeve_box");
    1253           3 :   sheeveBox->AddNode(sheeveSideV, 1, new TGeoTranslation(0, -.5, 0));
    1254           3 :   sheeveBox->AddNode(sheeveSideV, 2, new TGeoTranslation(0, +.5, 0));
    1255           3 :   sheeveBox->AddNode(sheeveBackV, 1, new TGeoTranslation(0, 0, 2.0+.15-1.15));
    1256           3 :   sheeveBox->AddNode(sheeveWingV, 1, new TGeoTranslation(.55-.15, -.90, 0));
    1257           3 :   sheeveBox->AddNode(sheeveWingV, 2, new TGeoTranslation(.55-.15, +.90, 0));
    1258           2 :   TGeoRotation*   sheeveWheelR = new TGeoRotation;
    1259           1 :   sheeveWheelR->RotateX(90);
    1260           2 :   TGeoCombiTrans* sheeveWheelM = new TGeoCombiTrans(0, 0, sheeveWheelZ-sheeveL,
    1261             :                                                     sheeveWheelR);
    1262           1 :   sheeveBox->AddNode(sheeveWheelV, 1, sheeveWheelM);
    1263           1 :   support->AddNode(sheeveBox, 1, sheeveMat1);
    1264           1 :   support->AddNode(sheeveBox, 2, sheeveMat2);
    1265             :   
    1266             :   
    1267             : 
    1268             :   //__________________________________________________________________
    1269             :   // Final cone
    1270           3 :   TGeoCompositeShape* coneShape = new TGeoCompositeShape(coneComb.Data());
    1271           1 :   coneShape->SetName("FMD3_cone");
    1272           1 :   coneShape->SetTitle("FMD3 cone");
    1273           2 :   TGeoVolume*  coneVolume = new TGeoVolume("FMD3_Cone", coneShape, fC);
    1274           1 :   coneVolume->SetLineColor(kRed);
    1275           3 :   support->AddNode(coneVolume, 0, new TGeoTranslation(0, 0, 0));
    1276             : 
    1277             :   //__________________________________________________________________
    1278             :   // Tension boxes. 
    1279           1 :   TGeoVolume*     tensionBox = TensionBox();
    1280             :   Double_t        tensionH  = .6;
    1281             :   Double_t        tensionL  = 4;
    1282             :   Double_t        tensionZ  = 23.654;
    1283           2 :   Double_t        tensionR  = fmd3->ConeR(fmd3->GetInnerZ() + fmd3->GetNoseZ() 
    1284           1 :                                           -  tensionZ);
    1285           1 :   Double_t        tensionAr = fmd3->GetConeOuterAngle();
    1286           1 :   Double_t        tensionA  = tensionAr * 180 / TMath::Pi();
    1287           2 :   TGeoRotation*   tensionQ  = new TGeoRotation;
    1288           1 :   tensionQ->RotateY(tensionA);
    1289           2 :   TGeoCombiTrans* tensionM1 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
    1290           2 :   TGeoCombiTrans* tensionM2 = new TGeoCombiTrans(tensionR,0,tensionZ, tensionQ);
    1291           1 :   tensionM1->RotateZ(45);
    1292           1 :   tensionM2->RotateZ(135);
    1293           1 :   support->AddNode(tensionBox, 1, tensionM1);
    1294           1 :   support->AddNode(tensionBox, 2, tensionM2);
    1295             :   
    1296             :   // Double_t         tensionHR    = 0.15;
    1297             :   Double_t         wireT        = .1/2;
    1298             :   Double_t         wireZ1       = (tensionZ
    1299           1 :                                    - tensionL * TMath::Cos(tensionAr) 
    1300           1 :                                    - tensionH * TMath::Sin(tensionAr));
    1301             :   Double_t         wireR1       = (tensionR 
    1302           1 :                                    - tensionL * TMath::Sin(tensionAr) 
    1303           1 :                                    + tensionH * TMath::Cos(tensionAr));
    1304           4 :   AliFMDDebug(10, ("Wire Z1: %f=%f-%f*cos(%f)-%f*sin(%f)", 
    1305             :                   wireZ1, tensionZ, tensionL, tensionAr, tensionH, tensionAr));
    1306           4 :   AliFMDDebug(10, ("Wire R1: %f=%f-%f*sin(%f)-%f*cos(%f)", 
    1307             :                   wireR1, tensionR, tensionL, tensionAr, tensionH, tensionAr));
    1308             :   
    1309           1 :   Double_t         wireStartA   = 42.3 * TMath::Pi() / 180;
    1310           1 :   Double_t         wireZ2       = (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
    1311             :                                    // - sheeveL - 
    1312           1 :                                    - wireT * TMath::Sin(wireStartA));
    1313             :   /* (sheeveWheelZ * (1 - TMath::Sin(wireStartA))
    1314             :                                    - wireT * TMath::Sin(wireStartA) 
    1315             :                                    - sheeveL); */
    1316           4 :   AliFMDDebug(10, ("wireZ2=%f=%f*(1-%f)", wireZ2, sheeveWheelZ, 
    1317             :                   TMath::Sin(wireStartA)));
    1318           1 :   Double_t         wireR2       = (sheeveHoleR + 
    1319           2 :                                    sheeveWheelZ * TMath::Cos(wireStartA) + 
    1320           1 :                                    wireT * TMath::Cos(wireStartA));
    1321           1 :   Double_t         wireDR       = wireR1-wireR2;
    1322           1 :   Double_t         wireDZ       = wireZ1-wireZ2;
    1323           1 :   Double_t         wireL        = TMath::Sqrt(wireDR*wireDR+wireDZ*wireDZ)-.01;
    1324           1 :   Double_t         wireAngle    = TMath::ATan2(wireDR,wireDZ);
    1325           2 :   TGeoTube*        wireShape    = new TGeoTube("FMD3_wire", 0, wireT, wireL/2);
    1326           2 :   TGeoVolume*      wireVolume   = new TGeoVolume("FMD3_wire", wireShape,fSteel);
    1327           2 :   TGeoRotation*    wireRot      = new TGeoRotation();
    1328           1 :   wireRot->RotateY(180/TMath::Pi()*wireAngle);
    1329           1 :   Double_t         wireR        = wireR2 + wireDR / 2;
    1330           1 :   Double_t         wireZ        = wireZ2 + wireDZ / 2;
    1331           2 :   TGeoCombiTrans*  wireM1       = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
    1332           2 :   TGeoCombiTrans*  wireM2       = new TGeoCombiTrans(wireR, 0,wireZ, wireRot);
    1333           1 :   wireM1->RotateZ(45);
    1334           1 :   wireM2->RotateZ(135);
    1335           1 :   support->AddNode(wireVolume, 1, wireM1);
    1336           1 :   support->AddNode(wireVolume, 2, wireM2);
    1337             : 
    1338             : 
    1339           3 :   TGeoTorus*       wireTS  = new TGeoTorus(sheeveWheelZ+wireT, 0, wireT, 0, 
    1340           1 :                                            90-wireStartA*180/TMath::Pi());
    1341           2 :   TGeoVolume*      wireTV  = new TGeoVolume("FMD3_bend_wire",wireTS,fSteel);
    1342           2 :   TGeoRotation*    wireTR  = new TGeoRotation;
    1343           1 :   wireTR->RotateY(90);
    1344           1 :   wireTR->RotateZ(-90);
    1345             :   Double_t         wireTZ  = sheeveWheelZ;
    1346           2 :   TGeoCombiTrans*  wireTM1 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
    1347           2 :   TGeoCombiTrans*  wireTM2 = new TGeoCombiTrans(sheeveHoleR,0,wireTZ,wireTR);
    1348           1 :   wireTM1->RotateZ(45);
    1349           1 :   wireTM2->RotateZ(135);
    1350           1 :   support->AddNode(wireTV, 1, wireTM1);
    1351           1 :   support->AddNode(wireTV, 2, wireTM2);
    1352             : 
    1353             :   Double_t         colarR = 4.05;
    1354           1 :   Double_t         wireEL = sheeveHoleR - colarR;
    1355           2 :   TGeoTube*        wireES = new TGeoTube("FMD3_end_wire", 0, wireT, wireEL/2);
    1356           2 :   TGeoVolume*      wireEV = new TGeoVolume("FMD3_end_wire", wireES, fSteel);
    1357           2 :   TGeoRotation*    wireER = new TGeoRotation;
    1358           1 :   wireER->RotateY(90);
    1359           2 :   TGeoCombiTrans*  wireEM1 = new TGeoCombiTrans(colarR+wireEL/2,0,
    1360             :                                                 -wireT,wireER);
    1361           2 :   TGeoCombiTrans*  wireEM2 = new TGeoCombiTrans(colarR+wireEL/2,0,
    1362             :                                                 -wireT,wireER);
    1363           1 :   wireEM1->RotateZ(45);
    1364           1 :   wireEM2->RotateZ(135);
    1365           1 :   support->AddNode(wireEV, 1, wireEM1);
    1366           1 :   support->AddNode(wireEV, 2, wireEM2);
    1367             :   
    1368             :   
    1369             : 
    1370             :   
    1371             :   //__________________________________________________________________
    1372             :   // Place support volumes in half-detector volumes 
    1373           1 :   Double_t         z  = fmd3->GetInnerZ();
    1374           4 :   AliFMDDebug(1, ("FMD3 support at z=%f", -fmd3->GetNoseZ()));
    1375           2 :   TGeoTranslation* t1 = new TGeoTranslation(0, 0, -fmd3->GetNoseZ());
    1376           1 :   fmd3TopVolume->AddNode(support, 1, t1);
    1377           2 :   TGeoCombiTrans*  t2 = new TGeoCombiTrans(*t1);
    1378           1 :   t2->RotateZ(180);
    1379           1 :   fmd3BotVolume->AddNode(support, 2, t2);
    1380             : 
    1381           2 :   TGeoRotation*   rot        = new TGeoRotation("FMD3 rotatation");
    1382           1 :   rot->RotateY(180);
    1383           1 :   TGeoVolume*     top        = gGeoManager->GetVolume("ALIC");
    1384           3 :   TGeoMatrix* mmatrix        = new TGeoCombiTrans("FMD3 trans", 0, 0, z, rot);
    1385           4 :   AliFMDDebug(5, ("Placing volumes %s and %s in ALIC at z=%f", 
    1386             :                    fmd3TopVolume->GetName(), fmd3BotVolume->GetName(), z));
    1387           1 :   top->AddNode(fmd3TopVolume, fmd3->GetId(), mmatrix);
    1388           1 :   top->AddNode(fmd3BotVolume, fmd3->GetId(), mmatrix);
    1389             : 
    1390             :   return 0;
    1391           2 : }
    1392             : 
    1393             : 
    1394             : //____________________________________________________________________
    1395             : void
    1396             : AliFMDGeometryBuilder::Exec(Option_t*) 
    1397             : {
    1398             :   // Setup up the FMD geometry. 
    1399           3 :   AliFMDDebug(1, ("\tGeometry options: %s",
    1400             :                     (fDetailed  ? "divided into strips" : "one volume")));
    1401           1 :   if (!gGeoManager) {
    1402           0 :     AliFatal("No TGeoManager defined");
    1403           0 :     return;
    1404             :   }
    1405             : 
    1406           1 :   fSi      = gGeoManager->GetMedium("FMD_Si$");
    1407           1 :   fC       = gGeoManager->GetMedium("FMD_Carbon$");
    1408           1 :   fAl      = gGeoManager->GetMedium("FMD_Aluminum$");
    1409           1 :   fChip    = gGeoManager->GetMedium("FMD_Si Chip$");
    1410           1 :   fAir     = gGeoManager->GetMedium("FMD_Air$");
    1411           1 :   fPCB     = gGeoManager->GetMedium("FMD_PCB$");
    1412           1 :   fPlastic = gGeoManager->GetMedium("FMD_Plastic$");
    1413           1 :   fCopper  = gGeoManager->GetMedium("FMD_Copper$");
    1414           1 :   fSteel   = gGeoManager->GetMedium("FMD_Steel$");
    1415             : 
    1416           9 :   if (!fSi||!fC||!fAl||!fChip||!fAir||!fPCB||!fPlastic||!fCopper||!fSteel) {
    1417           0 :     AliError("Failed to get some or all tracking mediums");
    1418           0 :     return;
    1419             :   }    
    1420           1 :   AliFMDGeometry* fmd = AliFMDGeometry::Instance();
    1421           1 :   AliFMDRing* inner = fmd->GetInner();
    1422           1 :   AliFMDRing* outer = fmd->GetOuter();
    1423           1 :   RingGeometry(inner);
    1424           1 :   RingGeometry(outer);
    1425           2 :   TGeoVolume* innerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
    1426           1 :                                                      inner->GetId()));
    1427           2 :   TGeoVolume* innerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
    1428           1 :                                                      inner->GetId()));
    1429           2 :   TGeoVolume* outerTop = gGeoManager->GetVolume(Form(fgkRingTopName, 
    1430           1 :                                                      outer->GetId()));
    1431           2 :   TGeoVolume* outerBot = gGeoManager->GetVolume(Form(fgkRingBotName, 
    1432           1 :                                                      outer->GetId()));
    1433             :   
    1434           1 :   FMD1Geometry(fmd->GetFMD1(), innerTop, innerBot);
    1435           1 :   FMD2Geometry(fmd->GetFMD2(), innerTop, innerBot, outerTop, outerBot);
    1436           1 :   FMD3Geometry(fmd->GetFMD3(), innerTop, innerBot, outerTop, outerBot);
    1437             : #ifndef USE_PRE_MOVE
    1438           1 :   fmd->SetSectorOff(fSectorOff);
    1439           1 :   fmd->SetModuleOff(fModuleOff);
    1440           1 :   fmd->SetRingOff(fRingOff);
    1441           1 :   fmd->SetDetectorOff(fDetectorOff);
    1442           1 :   fmd->SetActive(fActiveId.fArray, fActiveId.fN);
    1443             : #endif
    1444             :   // fmd->ExtractGeomInfo();
    1445             :   
    1446           2 : }
    1447             : 
    1448             : 
    1449             : //____________________________________________________________________
    1450             : //
    1451             : // EOF
    1452             : //

Generated by: LCOV version 1.11